1#
2# x86 register and target modifier recognition
3#
4#  Copyright (C) 2002-2007  Peter Johnson
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
16# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
19# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25# POSSIBILITY OF SUCH DAMAGE.
26%{
27#include <util.h>
28
29#include <ctype.h>
30#include <libyasm.h>
31#include <libyasm/phash.h>
32
33#include "modules/arch/x86/x86arch.h"
34
35enum regtmod_type {
36    REG = 1,
37    REGGROUP,
38    SEGREG,
39    TARGETMOD
40};
41%}
42%ignore-case
43%language=ANSI-C
44%compare-strncmp
45%readonly-tables
46%enum
47%struct-type
48%define hash-function-name regtmod_hash
49%define lookup-function-name regtmod_find
50struct regtmod_parse_data {
51    const char *name;
52    unsigned int type:8;                /* regtmod_type */
53
54    /* REG: register size
55     * SEGREG: prefix encoding
56     * Others: 0
57     */
58    unsigned int size_prefix:8;
59
60    /* REG: register index
61     * REGGROUP: register group type
62     * SEGREG: register encoding
63     * TARGETMOD: target modifier
64     */
65    unsigned int data:8;
66
67    /* REG: required bits setting
68     * SEGREG: BITS in which the segment is ignored
69     * Others: 0
70     */
71    unsigned int bits:8;
72};
73%%
74#
75# control, debug, and test registers
76#
77cr0,	REG,	X86_CRREG,	0,	0
78cr2,	REG,	X86_CRREG,	2,	0
79cr3,	REG,	X86_CRREG,	3,	0
80cr4,	REG,	X86_CRREG,	4,	0
81cr8,	REG,	X86_CRREG,	8,	64
82#
83dr0,	REG,	X86_DRREG,	0,	0
84dr1,	REG,	X86_DRREG,	1,	0
85dr2,	REG,	X86_DRREG,	2,	0
86dr3,	REG,	X86_DRREG,	3,	0
87dr4,	REG,	X86_DRREG,	4,	0
88dr5,	REG,	X86_DRREG,	5,	0
89dr6,	REG,	X86_DRREG,	6,	0
90dr7,	REG,	X86_DRREG,	7,	0
91#
92tr0,	REG,	X86_TRREG,	0,	0
93tr1,	REG,	X86_TRREG,	1,	0
94tr2,	REG,	X86_TRREG,	2,	0
95tr3,	REG,	X86_TRREG,	3,	0
96tr4,	REG,	X86_TRREG,	4,	0
97tr5,	REG,	X86_TRREG,	5,	0
98tr6,	REG,	X86_TRREG,	6,	0
99tr7,	REG,	X86_TRREG,	7,	0
100#
101# floating point, MMX, and SSE/SSE2 registers
102#
103st0,	REG,	X86_FPUREG,	0,	0
104st1,	REG,	X86_FPUREG,	1,	0
105st2,	REG,	X86_FPUREG,	2,	0
106st3,	REG,	X86_FPUREG,	3,	0
107st4,	REG,	X86_FPUREG,	4,	0
108st5,	REG,	X86_FPUREG,	5,	0
109st6,	REG,	X86_FPUREG,	6,	0
110st7,	REG,	X86_FPUREG,	7,	0
111#
112mm0,	REG,	X86_MMXREG,	0,	0
113mm1,	REG,	X86_MMXREG,	1,	0
114mm2,	REG,	X86_MMXREG,	2,	0
115mm3,	REG,	X86_MMXREG,	3,	0
116mm4,	REG,	X86_MMXREG,	4,	0
117mm5,	REG,	X86_MMXREG,	5,	0
118mm6,	REG,	X86_MMXREG,	6,	0
119mm7,	REG,	X86_MMXREG,	7,	0
120#
121xmm0,	REG,	X86_XMMREG,	0,	0
122xmm1,	REG,	X86_XMMREG,	1,	0
123xmm2,	REG,	X86_XMMREG,	2,	0
124xmm3,	REG,	X86_XMMREG,	3,	0
125xmm4,	REG,	X86_XMMREG,	4,	0
126xmm5,	REG,	X86_XMMREG,	5,	0
127xmm6,	REG,	X86_XMMREG,	6,	0
128xmm7,	REG,	X86_XMMREG,	7,	0
129xmm8,	REG,	X86_XMMREG,	8,	64
130xmm9,	REG,	X86_XMMREG,	9,	64
131xmm10,	REG,	X86_XMMREG,	10,	64
132xmm11,	REG,	X86_XMMREG,	11,	64
133xmm12,	REG,	X86_XMMREG,	12,	64
134xmm13,	REG,	X86_XMMREG,	13,	64
135xmm14,	REG,	X86_XMMREG,	14,	64
136xmm15,	REG,	X86_XMMREG,	15,	64
137# AVX registers
138ymm0,	REG,	X86_YMMREG,	0,	0
139ymm1,	REG,	X86_YMMREG,	1,	0
140ymm2,	REG,	X86_YMMREG,	2,	0
141ymm3,	REG,	X86_YMMREG,	3,	0
142ymm4,	REG,	X86_YMMREG,	4,	0
143ymm5,	REG,	X86_YMMREG,	5,	0
144ymm6,	REG,	X86_YMMREG,	6,	0
145ymm7,	REG,	X86_YMMREG,	7,	0
146ymm8,	REG,	X86_YMMREG,	8,	64
147ymm9,	REG,	X86_YMMREG,	9,	64
148ymm10,	REG,	X86_YMMREG,	10,	64
149ymm11,	REG,	X86_YMMREG,	11,	64
150ymm12,	REG,	X86_YMMREG,	12,	64
151ymm13,	REG,	X86_YMMREG,	13,	64
152ymm14,	REG,	X86_YMMREG,	14,	64
153ymm15,	REG,	X86_YMMREG,	15,	64
154#
155# integer registers
156#
157rax,	REG,	X86_REG64,	0,	64
158rcx,	REG,	X86_REG64,	1,	64
159rdx,	REG,	X86_REG64,	2,	64
160rbx,	REG,	X86_REG64,	3,	64
161rsp,	REG,	X86_REG64,	4,	64
162rbp,	REG,	X86_REG64,	5,	64
163rsi,	REG,	X86_REG64,	6,	64
164rdi,	REG,	X86_REG64,	7,	64
165r8,	REG,	X86_REG64,	8,	64
166r9,	REG,	X86_REG64,	9,	64
167r10,	REG,	X86_REG64,	10,	64
168r11,	REG,	X86_REG64,	11,	64
169r12,	REG,	X86_REG64,	12,	64
170r13,	REG,	X86_REG64,	13,	64
171r14,	REG,	X86_REG64,	14,	64
172r15,	REG,	X86_REG64,	15,	64
173#
174eax,	REG,	X86_REG32,	0,	0
175ecx,	REG,	X86_REG32,	1,	0
176edx,	REG,	X86_REG32,	2,	0
177ebx,	REG,	X86_REG32,	3,	0
178esp,	REG,	X86_REG32,	4,	0
179ebp,	REG,	X86_REG32,	5,	0
180esi,	REG,	X86_REG32,	6,	0
181edi,	REG,	X86_REG32,	7,	0
182r8d,	REG,	X86_REG32,	8,	64
183r9d,	REG,	X86_REG32,	9,	64
184r10d,	REG,	X86_REG32,	10,	64
185r11d,	REG,	X86_REG32,	11,	64
186r12d,	REG,	X86_REG32,	12,	64
187r13d,	REG,	X86_REG32,	13,	64
188r14d,	REG,	X86_REG32,	14,	64
189r15d,	REG,	X86_REG32,	15,	64
190#
191ax,	REG,	X86_REG16,	0,	0
192cx,	REG,	X86_REG16,	1,	0
193dx,	REG,	X86_REG16,	2,	0
194bx,	REG,	X86_REG16,	3,	0
195sp,	REG,	X86_REG16,	4,	0
196bp,	REG,	X86_REG16,	5,	0
197si,	REG,	X86_REG16,	6,	0
198di,	REG,	X86_REG16,	7,	0
199r8w,	REG,	X86_REG16,	8,	64
200r9w,	REG,	X86_REG16,	9,	64
201r10w,	REG,	X86_REG16,	10,	64
202r11w,	REG,	X86_REG16,	11,	64
203r12w,	REG,	X86_REG16,	12,	64
204r13w,	REG,	X86_REG16,	13,	64
205r14w,	REG,	X86_REG16,	14,	64
206r15w,	REG,	X86_REG16,	15,	64
207#
208al,	REG,	X86_REG8,	0,	0
209cl,	REG,	X86_REG8,	1,	0
210dl,	REG,	X86_REG8,	2,	0
211bl,	REG,	X86_REG8,	3,	0
212ah,	REG,	X86_REG8,	4,	0
213ch,	REG,	X86_REG8,	5,	0
214dh,	REG,	X86_REG8,	6,	0
215bh,	REG,	X86_REG8,	7,	0
216r8b,	REG,	X86_REG8,	8,	64
217r9b,	REG,	X86_REG8,	9,	64
218r10b,	REG,	X86_REG8,	10,	64
219r11b,	REG,	X86_REG8,	11,	64
220r12b,	REG,	X86_REG8,	12,	64
221r13b,	REG,	X86_REG8,	13,	64
222r14b,	REG,	X86_REG8,	14,	64
223r15b,	REG,	X86_REG8,	15,	64
224#
225spl,	REG,	X86_REG8X,	4,	64
226bpl,	REG,	X86_REG8X,	5,	64
227sil,	REG,	X86_REG8X,	6,	64
228dil,	REG,	X86_REG8X,	7,	64
229#
230rip,	REG,	X86_RIP,	0,	64
231#
232# floating point, MMX, and SSE/SSE2 registers
233#
234st,	REGGROUP,	0,	X86_FPUREG,	0
235mm,	REGGROUP,	0,	X86_MMXREG,	0
236xmm,	REGGROUP,	0,	X86_XMMREG,	0
237ymm,	REGGROUP,	0,	X86_YMMREG,	0
238#
239# segment registers
240#
241es,	SEGREG,	0x26,	0x00,	64
242cs,	SEGREG,	0x2e,	0x01,	0
243ss,	SEGREG,	0x36,	0x02,	64
244ds,	SEGREG,	0x3e,	0x03,	64
245fs,	SEGREG,	0x64,	0x04,	0
246gs,	SEGREG,	0x65,	0x05,	0
247#
248# target modifiers
249#
250near,	TARGETMOD,	0,	X86_NEAR,	0
251short,	TARGETMOD,	0,	X86_SHORT,	0
252far,	TARGETMOD,	0,	X86_FAR,	0
253to,	TARGETMOD,	0,	X86_TO,		0
254%%
255
256yasm_arch_regtmod
257yasm_x86__parse_check_regtmod(yasm_arch *arch, const char *id, size_t id_len,
258                              uintptr_t *data)
259{
260    yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch;
261    /*@null@*/ const struct regtmod_parse_data *pdata;
262    size_t i;
263    static char lcaseid[8];
264    unsigned int bits;
265    yasm_arch_regtmod type;
266
267    if (id_len > 7)
268        return YASM_ARCH_NOTREGTMOD;
269    for (i=0; i<id_len; i++)
270        lcaseid[i] = tolower(id[i]);
271    lcaseid[id_len] = '\0';
272
273    pdata = regtmod_find(lcaseid, id_len);
274    if (!pdata)
275        return YASM_ARCH_NOTREGTMOD;
276
277    type = (yasm_arch_regtmod)pdata->type;
278    bits = pdata->bits;
279
280    if (type == YASM_ARCH_REG && bits != 0 && arch_x86->mode_bits != bits) {
281        yasm_warn_set(YASM_WARN_GENERAL,
282                      N_("`%s' is a register in %u-bit mode"), id, bits);
283        return YASM_ARCH_NOTREGTMOD;
284    }
285
286    if (type == YASM_ARCH_SEGREG && bits != 0 && arch_x86->mode_bits == bits) {
287        yasm_warn_set(YASM_WARN_GENERAL,
288                      N_("`%s' segment register ignored in %u-bit mode"), id,
289                      bits);
290    }
291
292    if (type == YASM_ARCH_SEGREG)
293        *data = (pdata->size_prefix<<8) | pdata->data;
294    else
295        *data = pdata->size_prefix | pdata->data;
296    return type;
297}
298