| # |
| # x86 register and target modifier recognition |
| # |
| # Copyright (C) 2002-2007 Peter Johnson |
| # |
| # Redistribution and use in source and binary forms, with or without |
| # modification, are permitted provided that the following conditions |
| # are met: |
| # 1. Redistributions of source code must retain the above copyright |
| # notice, this list of conditions and the following disclaimer. |
| # 2. Redistributions in binary form must reproduce the above copyright |
| # notice, this list of conditions and the following disclaimer in the |
| # documentation and/or other materials provided with the distribution. |
| # |
| # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' |
| # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE |
| # LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| # POSSIBILITY OF SUCH DAMAGE. |
| %{ |
| #include <util.h> |
| |
| #include <ctype.h> |
| #include <libyasm.h> |
| #include <libyasm/phash.h> |
| |
| #include "modules/arch/x86/x86arch.h" |
| |
| enum regtmod_type { |
| REG = 1, |
| REGGROUP, |
| SEGREG, |
| TARGETMOD |
| }; |
| %} |
| %ignore-case |
| %language=ANSI-C |
| %compare-strncmp |
| %readonly-tables |
| %enum |
| %struct-type |
| %define hash-function-name regtmod_hash |
| %define lookup-function-name regtmod_find |
| struct regtmod_parse_data { |
| const char *name; |
| unsigned int type:8; /* regtmod_type */ |
| |
| /* REG: register size |
| * SEGREG: prefix encoding |
| * Others: 0 |
| */ |
| unsigned int size_prefix:8; |
| |
| /* REG: register index |
| * REGGROUP: register group type |
| * SEGREG: register encoding |
| * TARGETMOD: target modifier |
| */ |
| unsigned int data:8; |
| |
| /* REG: required bits setting |
| * SEGREG: BITS in which the segment is ignored |
| * Others: 0 |
| */ |
| unsigned int bits:8; |
| }; |
| %% |
| # |
| # control, debug, and test registers |
| # |
| cr0, REG, X86_CRREG, 0, 0 |
| cr2, REG, X86_CRREG, 2, 0 |
| cr3, REG, X86_CRREG, 3, 0 |
| cr4, REG, X86_CRREG, 4, 0 |
| cr8, REG, X86_CRREG, 8, 64 |
| # |
| dr0, REG, X86_DRREG, 0, 0 |
| dr1, REG, X86_DRREG, 1, 0 |
| dr2, REG, X86_DRREG, 2, 0 |
| dr3, REG, X86_DRREG, 3, 0 |
| dr4, REG, X86_DRREG, 4, 0 |
| dr5, REG, X86_DRREG, 5, 0 |
| dr6, REG, X86_DRREG, 6, 0 |
| dr7, REG, X86_DRREG, 7, 0 |
| # |
| tr0, REG, X86_TRREG, 0, 0 |
| tr1, REG, X86_TRREG, 1, 0 |
| tr2, REG, X86_TRREG, 2, 0 |
| tr3, REG, X86_TRREG, 3, 0 |
| tr4, REG, X86_TRREG, 4, 0 |
| tr5, REG, X86_TRREG, 5, 0 |
| tr6, REG, X86_TRREG, 6, 0 |
| tr7, REG, X86_TRREG, 7, 0 |
| # |
| # floating point, MMX, and SSE/SSE2 registers |
| # |
| st0, REG, X86_FPUREG, 0, 0 |
| st1, REG, X86_FPUREG, 1, 0 |
| st2, REG, X86_FPUREG, 2, 0 |
| st3, REG, X86_FPUREG, 3, 0 |
| st4, REG, X86_FPUREG, 4, 0 |
| st5, REG, X86_FPUREG, 5, 0 |
| st6, REG, X86_FPUREG, 6, 0 |
| st7, REG, X86_FPUREG, 7, 0 |
| # |
| mm0, REG, X86_MMXREG, 0, 0 |
| mm1, REG, X86_MMXREG, 1, 0 |
| mm2, REG, X86_MMXREG, 2, 0 |
| mm3, REG, X86_MMXREG, 3, 0 |
| mm4, REG, X86_MMXREG, 4, 0 |
| mm5, REG, X86_MMXREG, 5, 0 |
| mm6, REG, X86_MMXREG, 6, 0 |
| mm7, REG, X86_MMXREG, 7, 0 |
| # |
| xmm0, REG, X86_XMMREG, 0, 0 |
| xmm1, REG, X86_XMMREG, 1, 0 |
| xmm2, REG, X86_XMMREG, 2, 0 |
| xmm3, REG, X86_XMMREG, 3, 0 |
| xmm4, REG, X86_XMMREG, 4, 0 |
| xmm5, REG, X86_XMMREG, 5, 0 |
| xmm6, REG, X86_XMMREG, 6, 0 |
| xmm7, REG, X86_XMMREG, 7, 0 |
| xmm8, REG, X86_XMMREG, 8, 64 |
| xmm9, REG, X86_XMMREG, 9, 64 |
| xmm10, REG, X86_XMMREG, 10, 64 |
| xmm11, REG, X86_XMMREG, 11, 64 |
| xmm12, REG, X86_XMMREG, 12, 64 |
| xmm13, REG, X86_XMMREG, 13, 64 |
| xmm14, REG, X86_XMMREG, 14, 64 |
| xmm15, REG, X86_XMMREG, 15, 64 |
| # AVX registers |
| ymm0, REG, X86_YMMREG, 0, 0 |
| ymm1, REG, X86_YMMREG, 1, 0 |
| ymm2, REG, X86_YMMREG, 2, 0 |
| ymm3, REG, X86_YMMREG, 3, 0 |
| ymm4, REG, X86_YMMREG, 4, 0 |
| ymm5, REG, X86_YMMREG, 5, 0 |
| ymm6, REG, X86_YMMREG, 6, 0 |
| ymm7, REG, X86_YMMREG, 7, 0 |
| ymm8, REG, X86_YMMREG, 8, 64 |
| ymm9, REG, X86_YMMREG, 9, 64 |
| ymm10, REG, X86_YMMREG, 10, 64 |
| ymm11, REG, X86_YMMREG, 11, 64 |
| ymm12, REG, X86_YMMREG, 12, 64 |
| ymm13, REG, X86_YMMREG, 13, 64 |
| ymm14, REG, X86_YMMREG, 14, 64 |
| ymm15, REG, X86_YMMREG, 15, 64 |
| # |
| # integer registers |
| # |
| rax, REG, X86_REG64, 0, 64 |
| rcx, REG, X86_REG64, 1, 64 |
| rdx, REG, X86_REG64, 2, 64 |
| rbx, REG, X86_REG64, 3, 64 |
| rsp, REG, X86_REG64, 4, 64 |
| rbp, REG, X86_REG64, 5, 64 |
| rsi, REG, X86_REG64, 6, 64 |
| rdi, REG, X86_REG64, 7, 64 |
| r8, REG, X86_REG64, 8, 64 |
| r9, REG, X86_REG64, 9, 64 |
| r10, REG, X86_REG64, 10, 64 |
| r11, REG, X86_REG64, 11, 64 |
| r12, REG, X86_REG64, 12, 64 |
| r13, REG, X86_REG64, 13, 64 |
| r14, REG, X86_REG64, 14, 64 |
| r15, REG, X86_REG64, 15, 64 |
| # |
| eax, REG, X86_REG32, 0, 0 |
| ecx, REG, X86_REG32, 1, 0 |
| edx, REG, X86_REG32, 2, 0 |
| ebx, REG, X86_REG32, 3, 0 |
| esp, REG, X86_REG32, 4, 0 |
| ebp, REG, X86_REG32, 5, 0 |
| esi, REG, X86_REG32, 6, 0 |
| edi, REG, X86_REG32, 7, 0 |
| r8d, REG, X86_REG32, 8, 64 |
| r9d, REG, X86_REG32, 9, 64 |
| r10d, REG, X86_REG32, 10, 64 |
| r11d, REG, X86_REG32, 11, 64 |
| r12d, REG, X86_REG32, 12, 64 |
| r13d, REG, X86_REG32, 13, 64 |
| r14d, REG, X86_REG32, 14, 64 |
| r15d, REG, X86_REG32, 15, 64 |
| # |
| ax, REG, X86_REG16, 0, 0 |
| cx, REG, X86_REG16, 1, 0 |
| dx, REG, X86_REG16, 2, 0 |
| bx, REG, X86_REG16, 3, 0 |
| sp, REG, X86_REG16, 4, 0 |
| bp, REG, X86_REG16, 5, 0 |
| si, REG, X86_REG16, 6, 0 |
| di, REG, X86_REG16, 7, 0 |
| r8w, REG, X86_REG16, 8, 64 |
| r9w, REG, X86_REG16, 9, 64 |
| r10w, REG, X86_REG16, 10, 64 |
| r11w, REG, X86_REG16, 11, 64 |
| r12w, REG, X86_REG16, 12, 64 |
| r13w, REG, X86_REG16, 13, 64 |
| r14w, REG, X86_REG16, 14, 64 |
| r15w, REG, X86_REG16, 15, 64 |
| # |
| al, REG, X86_REG8, 0, 0 |
| cl, REG, X86_REG8, 1, 0 |
| dl, REG, X86_REG8, 2, 0 |
| bl, REG, X86_REG8, 3, 0 |
| ah, REG, X86_REG8, 4, 0 |
| ch, REG, X86_REG8, 5, 0 |
| dh, REG, X86_REG8, 6, 0 |
| bh, REG, X86_REG8, 7, 0 |
| r8b, REG, X86_REG8, 8, 64 |
| r9b, REG, X86_REG8, 9, 64 |
| r10b, REG, X86_REG8, 10, 64 |
| r11b, REG, X86_REG8, 11, 64 |
| r12b, REG, X86_REG8, 12, 64 |
| r13b, REG, X86_REG8, 13, 64 |
| r14b, REG, X86_REG8, 14, 64 |
| r15b, REG, X86_REG8, 15, 64 |
| # |
| spl, REG, X86_REG8X, 4, 64 |
| bpl, REG, X86_REG8X, 5, 64 |
| sil, REG, X86_REG8X, 6, 64 |
| dil, REG, X86_REG8X, 7, 64 |
| # |
| rip, REG, X86_RIP, 0, 64 |
| # |
| # floating point, MMX, and SSE/SSE2 registers |
| # |
| st, REGGROUP, 0, X86_FPUREG, 0 |
| mm, REGGROUP, 0, X86_MMXREG, 0 |
| xmm, REGGROUP, 0, X86_XMMREG, 0 |
| ymm, REGGROUP, 0, X86_YMMREG, 0 |
| # |
| # segment registers |
| # |
| es, SEGREG, 0x26, 0x00, 64 |
| cs, SEGREG, 0x2e, 0x01, 0 |
| ss, SEGREG, 0x36, 0x02, 64 |
| ds, SEGREG, 0x3e, 0x03, 64 |
| fs, SEGREG, 0x64, 0x04, 0 |
| gs, SEGREG, 0x65, 0x05, 0 |
| # |
| # target modifiers |
| # |
| near, TARGETMOD, 0, X86_NEAR, 0 |
| short, TARGETMOD, 0, X86_SHORT, 0 |
| far, TARGETMOD, 0, X86_FAR, 0 |
| to, TARGETMOD, 0, X86_TO, 0 |
| %% |
| |
| yasm_arch_regtmod |
| yasm_x86__parse_check_regtmod(yasm_arch *arch, const char *id, size_t id_len, |
| uintptr_t *data) |
| { |
| yasm_arch_x86 *arch_x86 = (yasm_arch_x86 *)arch; |
| /*@null@*/ const struct regtmod_parse_data *pdata; |
| size_t i; |
| static char lcaseid[8]; |
| unsigned int bits; |
| yasm_arch_regtmod type; |
| |
| if (id_len > 7) |
| return YASM_ARCH_NOTREGTMOD; |
| for (i=0; i<id_len; i++) |
| lcaseid[i] = tolower(id[i]); |
| lcaseid[id_len] = '\0'; |
| |
| pdata = regtmod_find(lcaseid, id_len); |
| if (!pdata) |
| return YASM_ARCH_NOTREGTMOD; |
| |
| type = (yasm_arch_regtmod)pdata->type; |
| bits = pdata->bits; |
| |
| if (type == YASM_ARCH_REG && bits != 0 && arch_x86->mode_bits != bits) { |
| yasm_warn_set(YASM_WARN_GENERAL, |
| N_("`%s' is a register in %u-bit mode"), id, bits); |
| return YASM_ARCH_NOTREGTMOD; |
| } |
| |
| if (type == YASM_ARCH_SEGREG && bits != 0 && arch_x86->mode_bits == bits) { |
| yasm_warn_set(YASM_WARN_GENERAL, |
| N_("`%s' segment register ignored in %u-bit mode"), id, |
| bits); |
| } |
| |
| if (type == YASM_ARCH_SEGREG) |
| *data = (pdata->size_prefix<<8) | pdata->data; |
| else |
| *data = pdata->size_prefix | pdata->data; |
| return type; |
| } |