mirror of
https://github.com/mirror/tinycc.git
synced 2025-02-10 06:50:10 +08:00
integrate x86_64-asm.c into i386-asm.c
Also, disable 16bit support for now as it causes bugs in 32bit mode. #define I386_ASM_16 if you want it.
This commit is contained in:
parent
e81569bc70
commit
1308e8ebcf
4
Makefile
4
Makefile
@ -82,9 +82,9 @@ CORE_FILES = tcc.c libtcc.c tccpp.c tccgen.c tccelf.c tccasm.c \
|
||||
tcc.h config.h libtcc.h tcctok.h
|
||||
I386_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h i386-tok.h
|
||||
WIN32_FILES = $(CORE_FILES) i386-gen.c i386-asm.c i386-asm.h i386-tok.h tccpe.c
|
||||
WIN64_FILES = $(CORE_FILES) x86_64-gen.c x86_64-asm.c x86_64-asm.h x86_64-tok.h tccpe.c
|
||||
WIN64_FILES = $(CORE_FILES) x86_64-gen.c i386-asm.c x86_64-asm.h tccpe.c
|
||||
WINCE_FILES = $(CORE_FILES) arm-gen.c tccpe.c
|
||||
X86_64_FILES = $(CORE_FILES) x86_64-gen.c x86_64-asm.c x86_64-asm.h x86_64-tok.h
|
||||
X86_64_FILES = $(CORE_FILES) x86_64-gen.c i386-asm.c x86_64-asm.h
|
||||
ARM_FILES = $(CORE_FILES) arm-gen.c
|
||||
C67_FILES = $(CORE_FILES) c67-gen.c tcccoff.c
|
||||
|
||||
|
446
i386-asm.c
446
i386-asm.c
@ -2,6 +2,7 @@
|
||||
* i386 specific functions for TCC assembler
|
||||
*
|
||||
* Copyright (c) 2001, 2002 Fabrice Bellard
|
||||
* Copyright (c) 2009 Frédéric Feret (x86_64 support)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
@ -20,12 +21,11 @@
|
||||
|
||||
#define MAX_OPERANDS 3
|
||||
|
||||
typedef struct ASMInstr {
|
||||
uint16_t sym;
|
||||
uint16_t opcode;
|
||||
uint16_t instr_type;
|
||||
#define TOK_ASM_first TOK_ASM_clc
|
||||
#define TOK_ASM_last TOK_ASM_emms
|
||||
|
||||
#define OPC_JMP 0x01 /* jmp operand */
|
||||
#define OPC_B 0x02 /* only used zith OPC_WL */
|
||||
#define OPC_B 0x02 /* only used with OPC_WL */
|
||||
#define OPC_WL 0x04 /* accepts w, l or no suffix */
|
||||
#define OPC_BWL (OPC_B | OPC_WL) /* accepts b, w, l or no suffix */
|
||||
#define OPC_REG 0x08 /* register is added to opcode */
|
||||
@ -37,47 +37,58 @@ typedef struct ASMInstr {
|
||||
#define OPC_ARITH 0x0200 /* arithmetic opcodes */
|
||||
#define OPC_SHORTJMP 0x0400 /* short jmp operand */
|
||||
#define OPC_FARITH 0x0800 /* FPU arithmetic opcodes */
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
# define OPC_WLQ 0x1000 /* accepts w, l, q or no suffix */
|
||||
# define OPC_BWLQ (OPC_B | OPC_WLQ) /* accepts b, w, l, q or no suffix */
|
||||
# define OPC_WLX OPC_WLQ
|
||||
#else
|
||||
# define OPC_WLX OPC_WL
|
||||
#endif
|
||||
|
||||
#define OPC_GROUP_SHIFT 13
|
||||
|
||||
/* in order to compress the operand type, we use specific operands and
|
||||
we or only with EA */
|
||||
#define OPT_REG8 0 /* warning: value is hardcoded from TOK_ASM_xxx */
|
||||
#define OPT_REG16 1 /* warning: value is hardcoded from TOK_ASM_xxx */
|
||||
#define OPT_REG32 2 /* warning: value is hardcoded from TOK_ASM_xxx */
|
||||
#define OPT_MMX 3 /* warning: value is hardcoded from TOK_ASM_xxx */
|
||||
#define OPT_SSE 4 /* warning: value is hardcoded from TOK_ASM_xxx */
|
||||
#define OPT_CR 5 /* warning: value is hardcoded from TOK_ASM_xxx */
|
||||
#define OPT_TR 6 /* warning: value is hardcoded from TOK_ASM_xxx */
|
||||
#define OPT_DB 7 /* warning: value is hardcoded from TOK_ASM_xxx */
|
||||
#define OPT_SEG 8
|
||||
#define OPT_ST 9
|
||||
#define OPT_IM8 10
|
||||
#define OPT_IM8S 11
|
||||
#define OPT_IM16 12
|
||||
#define OPT_IM32 13
|
||||
#define OPT_EAX 14 /* %al, %ax or %eax register */
|
||||
#define OPT_ST0 15 /* %st(0) register */
|
||||
#define OPT_CL 16 /* %cl register */
|
||||
#define OPT_DX 17 /* %dx register */
|
||||
#define OPT_ADDR 18 /* OP_EA with only offset */
|
||||
#define OPT_INDIR 19 /* *(expr) */
|
||||
enum {
|
||||
OPT_REG8=0, /* warning: value is hardcoded from TOK_ASM_xxx */
|
||||
OPT_REG16, /* warning: value is hardcoded from TOK_ASM_xxx */
|
||||
OPT_REG32, /* warning: value is hardcoded from TOK_ASM_xxx */
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
OPT_REG64, /* warning: value is hardcoded from TOK_ASM_xxx */
|
||||
#endif
|
||||
OPT_MMX, /* warning: value is hardcoded from TOK_ASM_xxx */
|
||||
OPT_SSE, /* warning: value is hardcoded from TOK_ASM_xxx */
|
||||
OPT_CR, /* warning: value is hardcoded from TOK_ASM_xxx */
|
||||
OPT_TR, /* warning: value is hardcoded from TOK_ASM_xxx */
|
||||
OPT_DB, /* warning: value is hardcoded from TOK_ASM_xxx */
|
||||
OPT_SEG,
|
||||
OPT_ST,
|
||||
OPT_IM8,
|
||||
OPT_IM8S,
|
||||
OPT_IM16,
|
||||
OPT_IM32,
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
OPT_IM64,
|
||||
#endif
|
||||
OPT_EAX, /* %al, %ax, %eax or %rax register */
|
||||
OPT_ST0, /* %st(0) register */
|
||||
OPT_CL, /* %cl register */
|
||||
OPT_DX, /* %dx register */
|
||||
OPT_ADDR, /* OP_EA with only offset */
|
||||
OPT_INDIR, /* *(expr) */
|
||||
/* composite types */
|
||||
OPT_COMPOSITE_FIRST,
|
||||
OPT_IM, /* IM8 | IM16 | IM32 | IM64 */
|
||||
OPT_REG, /* REG8 | REG16 | REG32 | REG64 */
|
||||
OPT_REGW, /* REG16 | REG32 | REG64 */
|
||||
OPT_IMW, /* IM16 | IM32 | IM64 */
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
OPT_IMNO64, /* IM16 | IM32 */
|
||||
#endif
|
||||
/* can be ored with any OPT_xxx */
|
||||
OPT_EA = 0x80
|
||||
};
|
||||
|
||||
/* composite types */
|
||||
#define OPT_COMPOSITE_FIRST 20
|
||||
#define OPT_IM 20 /* IM8 | IM16 | IM32 */
|
||||
#define OPT_REG 21 /* REG8 | REG16 | REG32 */
|
||||
#define OPT_REGW 22 /* REG16 | REG32 */
|
||||
#define OPT_IMW 23 /* IM16 | IM32 */
|
||||
|
||||
/* can be ored with any OPT_xxx */
|
||||
#define OPT_EA 0x80
|
||||
|
||||
uint8_t nb_ops;
|
||||
uint8_t op_type[MAX_OPERANDS]; /* see OP_xxx */
|
||||
} ASMInstr;
|
||||
|
||||
typedef struct Operand {
|
||||
uint32_t type;
|
||||
#define OP_REG8 (1 << OPT_REG8)
|
||||
#define OP_REG16 (1 << OPT_REG16)
|
||||
#define OP_REG32 (1 << OPT_REG32)
|
||||
@ -98,23 +109,55 @@ typedef struct Operand {
|
||||
#define OP_DX (1 << OPT_DX)
|
||||
#define OP_ADDR (1 << OPT_ADDR)
|
||||
#define OP_INDIR (1 << OPT_INDIR)
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
# define OP_REG64 (1 << OPT_REG64)
|
||||
# define OP_IM64 (1 << OPT_IM64)
|
||||
#else
|
||||
# define OP_REG64 0
|
||||
# define OP_IM64 0
|
||||
#endif
|
||||
|
||||
#define OP_EA 0x40000000
|
||||
#define OP_REG (OP_REG8 | OP_REG16 | OP_REG32)
|
||||
#define OP_IM OP_IM32
|
||||
#define OP_REG (OP_REG8 | OP_REG16 | OP_REG32 | OP_REG64)
|
||||
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
# define OP_IM OP_IM64
|
||||
# define TREG_XAX TREG_RAX
|
||||
# define TREG_XCX TREG_RCX
|
||||
# define TREG_XDX TREG_RDX
|
||||
#else
|
||||
# define OP_IM OP_IM32
|
||||
# define TREG_XAX TREG_EAX
|
||||
# define TREG_XCX TREG_ECX
|
||||
# define TREG_XDX TREG_EDX
|
||||
#endif
|
||||
|
||||
typedef struct ASMInstr {
|
||||
uint16_t sym;
|
||||
uint16_t opcode;
|
||||
uint16_t instr_type;
|
||||
uint8_t nb_ops;
|
||||
uint8_t op_type[MAX_OPERANDS]; /* see OP_xxx */
|
||||
} ASMInstr;
|
||||
|
||||
typedef struct Operand {
|
||||
uint32_t type;
|
||||
int8_t reg; /* register, -1 if none */
|
||||
int8_t reg2; /* second register, -1 if none */
|
||||
uint8_t shift;
|
||||
ExprValue e;
|
||||
} Operand;
|
||||
|
||||
static const uint8_t reg_to_size[5] = {
|
||||
static const uint8_t reg_to_size[9] = {
|
||||
/*
|
||||
[OP_REG8] = 0,
|
||||
[OP_REG16] = 1,
|
||||
[OP_REG32] = 2,
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
[OP_REG64] = 3,
|
||||
#endif
|
||||
*/
|
||||
0, 0, 1, 0, 2
|
||||
0, 0, 1, 0, 2, 0, 0, 0, 3
|
||||
};
|
||||
|
||||
#define NB_TEST_OPCODES 30
|
||||
@ -168,8 +211,11 @@ static const ASMInstr asm_instrs[] = {
|
||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 1, { op0 }},
|
||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) { TOK_ASM_ ## name, opcode, (instr_type | group << OPC_GROUP_SHIFT), 2, { op0, op1 }},
|
||||
#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 }},
|
||||
#include "i386-asm.h"
|
||||
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
# include "x86_64-asm.h"
|
||||
#else
|
||||
# include "i386-asm.h"
|
||||
#endif
|
||||
/* last operation */
|
||||
{ 0, },
|
||||
};
|
||||
@ -181,17 +227,20 @@ static const uint16_t op0_codes[] = {
|
||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
|
||||
#include "i386-asm.h"
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
# include "x86_64-asm.h"
|
||||
#else
|
||||
# include "i386-asm.h"
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline int get_reg_shift(TCCState *s1)
|
||||
{
|
||||
int shift, v;
|
||||
|
||||
if (s1->seg_size == 16) {
|
||||
#ifdef I386_ASM_16
|
||||
if (s1->seg_size == 16)
|
||||
error("invalid effective address");
|
||||
}
|
||||
|
||||
#endif
|
||||
v = asm_int_expr(s1);
|
||||
switch(v) {
|
||||
case 1:
|
||||
@ -216,23 +265,26 @@ static inline int get_reg_shift(TCCState *s1)
|
||||
|
||||
static int asm_parse_reg(void)
|
||||
{
|
||||
int reg;
|
||||
int reg = 0;
|
||||
if (tok != '%')
|
||||
goto error_32;
|
||||
next();
|
||||
if (tok >= TOK_ASM_eax && tok <= TOK_ASM_edi) {
|
||||
reg = tok - TOK_ASM_eax;
|
||||
next();
|
||||
return reg;
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
} else if (tok >= TOK_ASM_rax && tok <= TOK_ASM_rdi) {
|
||||
reg = tok - TOK_ASM_rax;
|
||||
#endif
|
||||
#ifdef I386_ASM_16
|
||||
} else if (tok >= TOK_ASM_ax && tok <= TOK_ASM_di) {
|
||||
reg = tok - TOK_ASM_ax;
|
||||
next();
|
||||
return reg;
|
||||
#endif
|
||||
} else {
|
||||
error_32:
|
||||
expect("register");
|
||||
return 0;
|
||||
}
|
||||
next();
|
||||
return reg;
|
||||
}
|
||||
|
||||
static void parse_operand(TCCState *s1, Operand *op)
|
||||
@ -253,11 +305,11 @@ static void parse_operand(TCCState *s1, Operand *op)
|
||||
reg = tok - TOK_ASM_al;
|
||||
op->type = 1 << (reg >> 3); /* WARNING: do not change constant order */
|
||||
op->reg = reg & 7;
|
||||
if ((op->type & OP_REG) && op->reg == TREG_EAX)
|
||||
if ((op->type & OP_REG) && op->reg == TREG_XAX)
|
||||
op->type |= OP_EAX;
|
||||
else if (op->type == OP_REG8 && op->reg == TREG_ECX)
|
||||
else if (op->type == OP_REG8 && op->reg == TREG_XCX)
|
||||
op->type |= OP_CL;
|
||||
else if (op->type == OP_REG16 && op->reg == TREG_EDX)
|
||||
else if (op->type == OP_REG16 && op->reg == TREG_XDX)
|
||||
op->type |= OP_DX;
|
||||
} else if (tok >= TOK_ASM_dr0 && tok <= TOK_ASM_dr7) {
|
||||
op->type = OP_DB;
|
||||
@ -294,7 +346,7 @@ static void parse_operand(TCCState *s1, Operand *op)
|
||||
/* constant value */
|
||||
next();
|
||||
asm_expr(s1, &e);
|
||||
op->type = OP_IM32;
|
||||
op->type = OP_IM;
|
||||
op->e.v = e.v;
|
||||
op->e.sym = e.sym;
|
||||
if (!op->e.sym) {
|
||||
@ -304,6 +356,10 @@ static void parse_operand(TCCState *s1, Operand *op)
|
||||
op->type |= OP_IM8S;
|
||||
if (op->e.v == (uint16_t)op->e.v)
|
||||
op->type |= OP_IM16;
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
if (op->e.v == (uint32_t)op->e.v)
|
||||
op->type |= OP_IM32;
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
/* address(reg,reg2,shift) with all variants */
|
||||
@ -342,51 +398,40 @@ static void parse_operand(TCCState *s1, Operand *op)
|
||||
op->type |= indir;
|
||||
}
|
||||
|
||||
static void gen_le16(int v)
|
||||
{
|
||||
g(v);
|
||||
g(v >> 8);
|
||||
}
|
||||
|
||||
/* XXX: unify with C code output ? */
|
||||
static void gen_expr32(ExprValue *pe)
|
||||
{
|
||||
if (pe->sym)
|
||||
greloc(cur_text_section, pe->sym, ind, R_386_32);
|
||||
gen_le32(pe->v);
|
||||
gen_addr32(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
|
||||
}
|
||||
|
||||
static void gen_expr16(ExprValue *pe)
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
static void gen_expr64(ExprValue *pe)
|
||||
{
|
||||
if (pe->sym)
|
||||
greloc(cur_text_section, pe->sym, ind, R_386_16);
|
||||
gen_le16(pe->v);
|
||||
gen_addr64(pe->sym ? VT_SYM : 0, pe->sym, pe->v);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* XXX: unify with C code output ? */
|
||||
static void gen_disp32(ExprValue *pe)
|
||||
{
|
||||
Sym *sym;
|
||||
sym = pe->sym;
|
||||
if (sym) {
|
||||
if (sym->r == cur_text_section->sh_num) {
|
||||
Sym *sym = pe->sym;
|
||||
if (sym && sym->r == cur_text_section->sh_num) {
|
||||
/* same section: we can output an absolute value. Note
|
||||
that the TCC compiler behaves differently here because
|
||||
it always outputs a relocation to ease (future) code
|
||||
elimination in the linker */
|
||||
gen_le32(pe->v + sym->jnext - ind - 4);
|
||||
} else {
|
||||
greloc(cur_text_section, sym, ind, R_386_PC32);
|
||||
gen_le32(pe->v - 4);
|
||||
}
|
||||
} else {
|
||||
/* put an empty PC32 relocation */
|
||||
put_elf_reloc(symtab_section, cur_text_section,
|
||||
ind, R_386_PC32, 0);
|
||||
gen_le32(pe->v - 4);
|
||||
gen_addrpc32(VT_SYM, sym, pe->v);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef I386_ASM_16
|
||||
static void gen_expr16(ExprValue *pe)
|
||||
{
|
||||
if (pe->sym)
|
||||
greloc(cur_text_section, pe->sym, ind, R_386_16);
|
||||
gen_le16(pe->v);
|
||||
}
|
||||
static void gen_disp16(ExprValue *pe)
|
||||
{
|
||||
Sym *sym;
|
||||
@ -409,6 +454,7 @@ static void gen_disp16(ExprValue *pe)
|
||||
gen_le16(pe->v - 2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* generate the modrm operand */
|
||||
static inline void asm_modrm(int reg, Operand *op)
|
||||
@ -419,10 +465,13 @@ static inline void asm_modrm(int reg, Operand *op)
|
||||
g(0xc0 + (reg << 3) + op->reg);
|
||||
} else if (op->reg == -1 && op->reg2 == -1) {
|
||||
/* displacement only */
|
||||
#ifdef I386_ASM_16
|
||||
if (tcc_state->seg_size == 16) {
|
||||
g(0x06 + (reg << 3));
|
||||
gen_expr16(&op->e);
|
||||
} else if (tcc_state->seg_size == 32) {
|
||||
} else if (tcc_state->seg_size == 32)
|
||||
#endif
|
||||
{
|
||||
g(0x05 + (reg << 3));
|
||||
gen_expr32(&op->e);
|
||||
}
|
||||
@ -443,7 +492,9 @@ static inline void asm_modrm(int reg, Operand *op)
|
||||
reg1 = op->reg;
|
||||
if (op->reg2 != -1)
|
||||
reg1 = 4;
|
||||
#ifdef I386_ASM_16
|
||||
if (tcc_state->seg_size == 32) {
|
||||
#endif
|
||||
g(mod + (reg << 3) + reg1);
|
||||
if (reg1 == 4) {
|
||||
/* add sib byte */
|
||||
@ -452,6 +503,7 @@ static inline void asm_modrm(int reg, Operand *op)
|
||||
reg2 = 4; /* indicate no index */
|
||||
g((op->shift << 6) + (reg2 << 3) + sib_reg1);
|
||||
}
|
||||
#ifdef I386_ASM_16
|
||||
} else if (tcc_state->seg_size == 16) {
|
||||
/* edi = 7, esi = 6 --> di = 5, si = 4 */
|
||||
if ((reg1 == 6) || (reg1 == 7)) {
|
||||
@ -487,14 +539,16 @@ static inline void asm_modrm(int reg, Operand *op)
|
||||
}
|
||||
g(mod + (reg << 3) + reg1);
|
||||
}
|
||||
|
||||
#endif
|
||||
/* add offset */
|
||||
if (mod == 0x40) {
|
||||
g(op->e.v);
|
||||
} else if (mod == 0x80 || op->reg == -1) {
|
||||
#ifdef I386_ASM_16
|
||||
if (tcc_state->seg_size == 16)
|
||||
gen_expr16(&op->e);
|
||||
else if (tcc_state->seg_size == 32)
|
||||
#endif
|
||||
gen_expr32(&op->e);
|
||||
}
|
||||
}
|
||||
@ -507,9 +561,9 @@ static void asm_opcode(TCCState *s1, int opcode)
|
||||
int nb_ops, s;
|
||||
Operand ops[MAX_OPERANDS], *pop;
|
||||
int op_type[3]; /* decoded op type */
|
||||
|
||||
int a32, o32;
|
||||
static int addr32 = 0, data32 = 0;
|
||||
#ifdef I386_ASM_16
|
||||
static int a32 = 0, o32 = 0, addr32 = 0, data32 = 0;
|
||||
#endif
|
||||
|
||||
/* get operands */
|
||||
pop = ops;
|
||||
@ -523,14 +577,12 @@ static void asm_opcode(TCCState *s1, int opcode)
|
||||
}
|
||||
parse_operand(s1, pop);
|
||||
if (tok == ':') {
|
||||
if (pop->type != OP_SEG || seg_prefix) {
|
||||
bad_prefix:
|
||||
if (pop->type != OP_SEG || seg_prefix)
|
||||
error("incorrect prefix");
|
||||
}
|
||||
seg_prefix = segment_prefixes[pop->reg];
|
||||
next();
|
||||
parse_operand(s1, pop);
|
||||
#if 0
|
||||
#ifndef I386_ASM_16
|
||||
if (!(pop->type & OP_EA)) {
|
||||
error("segment prefix must be followed by memory reference");
|
||||
}
|
||||
@ -555,23 +607,22 @@ static void asm_opcode(TCCState *s1, int opcode)
|
||||
if (!((unsigned)v < 8 * 6 && (v % 6) == 0))
|
||||
continue;
|
||||
} else if (pa->instr_type & OPC_ARITH) {
|
||||
if (!(opcode >= pa->sym && opcode < pa->sym + 8 * 4))
|
||||
if (!(opcode >= pa->sym && opcode < pa->sym + 8*NBWLX))
|
||||
continue;
|
||||
goto compute_size;
|
||||
s = (opcode - pa->sym) % NBWLX;
|
||||
} else if (pa->instr_type & OPC_SHIFT) {
|
||||
if (!(opcode >= pa->sym && opcode < pa->sym + 7 * 4))
|
||||
if (!(opcode >= pa->sym && opcode < pa->sym + 7*NBWLX))
|
||||
continue;
|
||||
goto compute_size;
|
||||
s = (opcode - pa->sym) % NBWLX;
|
||||
} else if (pa->instr_type & OPC_TEST) {
|
||||
if (!(opcode >= pa->sym && opcode < pa->sym + NB_TEST_OPCODES))
|
||||
continue;
|
||||
} else if (pa->instr_type & OPC_B) {
|
||||
if (!(opcode >= pa->sym && opcode <= pa->sym + 3))
|
||||
if (!(opcode >= pa->sym && opcode < pa->sym + NBWLX))
|
||||
continue;
|
||||
compute_size:
|
||||
s = (opcode - pa->sym) & 3;
|
||||
} else if (pa->instr_type & OPC_WL) {
|
||||
if (!(opcode >= pa->sym && opcode <= pa->sym + 2))
|
||||
s = opcode - pa->sym;
|
||||
} else if (pa->instr_type & OPC_WLX) {
|
||||
if (!(opcode >= pa->sym && opcode < pa->sym + NBWLX-1))
|
||||
continue;
|
||||
s = opcode - pa->sym + 1;
|
||||
} else {
|
||||
@ -587,17 +638,22 @@ static void asm_opcode(TCCState *s1, int opcode)
|
||||
op2 = op1 & 0x1f;
|
||||
switch(op2) {
|
||||
case OPT_IM:
|
||||
v = OP_IM8 | OP_IM16 | OP_IM32;
|
||||
v = OP_IM8 | OP_IM16 | OP_IM32 | OP_IM64;
|
||||
break;
|
||||
case OPT_REG:
|
||||
v = OP_REG8 | OP_REG16 | OP_REG32;
|
||||
v = OP_REG8 | OP_REG16 | OP_REG32 | OP_REG64;
|
||||
break;
|
||||
case OPT_REGW:
|
||||
v = OP_REG16 | OP_REG32;
|
||||
v = OP_REG16 | OP_REG32 | OP_REG64;
|
||||
break;
|
||||
case OPT_IMW:
|
||||
v = OP_IM16 | OP_IM32 | OP_IM64;
|
||||
break;
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
case OPT_IMNO64:
|
||||
v = OP_IM16 | OP_IM32;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
v = 1 << op2;
|
||||
break;
|
||||
@ -613,20 +669,22 @@ static void asm_opcode(TCCState *s1, int opcode)
|
||||
next: ;
|
||||
}
|
||||
if (pa->sym == 0) {
|
||||
if (opcode >= TOK_ASM_pusha && opcode <= TOK_ASM_emms) {
|
||||
if (opcode >= TOK_ASM_first && opcode <= TOK_ASM_last) {
|
||||
int b;
|
||||
b = op0_codes[opcode - TOK_ASM_pusha];
|
||||
b = op0_codes[opcode - TOK_ASM_first];
|
||||
#ifdef I386_ASM_16
|
||||
if (opcode == TOK_ASM_o32) {
|
||||
if (s1->seg_size == 32)
|
||||
goto bad_prefix;
|
||||
error("incorrect prefix");
|
||||
else
|
||||
data32 = 1;
|
||||
o32 = data32 = 1;
|
||||
} else if (opcode == TOK_ASM_a32) {
|
||||
if (s1->seg_size == 32)
|
||||
goto bad_prefix;
|
||||
error("incorrect prefix");
|
||||
else
|
||||
addr32 = 1;
|
||||
a32 = addr32 = 1;
|
||||
}
|
||||
#endif
|
||||
if (b & 0xff00)
|
||||
g(b >> 8);
|
||||
g(b);
|
||||
@ -637,28 +695,41 @@ static void asm_opcode(TCCState *s1, int opcode)
|
||||
}
|
||||
}
|
||||
/* if the size is unknown, then evaluate it (OPC_B or OPC_WL case) */
|
||||
if (s == 3) {
|
||||
for(i = 0; s == 3 && i < nb_ops; i++) {
|
||||
if (s == NBWLX-1) {
|
||||
for(i = 0; s == NBWLX-1 && i < nb_ops; i++) {
|
||||
if ((ops[i].type & OP_REG) && !(op_type[i] & (OP_CL | OP_DX)))
|
||||
s = reg_to_size[ops[i].type & OP_REG];
|
||||
}
|
||||
if (s == 3) {
|
||||
if (s == NBWLX-1) {
|
||||
if ((opcode == TOK_ASM_push || opcode == TOK_ASM_pop) &&
|
||||
(ops[0].type & (OP_SEG | OP_IM8S | OP_IM32)))
|
||||
(ops[0].type & (OP_SEG | OP_IM8S | OP_IM32 | OP_IM64)))
|
||||
s = 2;
|
||||
else
|
||||
error("cannot infer opcode suffix");
|
||||
}
|
||||
}
|
||||
|
||||
a32 = o32 = 0;
|
||||
#ifdef I386_ASM_16
|
||||
for(i = 0; i < nb_ops; i++) {
|
||||
if (ops[i].type & OP_REG32) {
|
||||
if (s1->seg_size == 16)
|
||||
o32 = 1;
|
||||
} else if (!(ops[i].type & OP_REG32)) {
|
||||
if (s1->seg_size == 32)
|
||||
o32 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (s == 1 || (pa->instr_type & OPC_D16)) {
|
||||
if (s1->seg_size == 32)
|
||||
o32 = 1;
|
||||
} else if (s == 2 && !(pa->instr_type & OPC_D16)) {
|
||||
if (s1->seg_size == 16)
|
||||
} else if (s == 2) {
|
||||
if (s1->seg_size == 16) {
|
||||
if (!(pa->instr_type & OPC_D16))
|
||||
o32 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* generate a16/a32 prefix if needed */
|
||||
if ((a32 == 1) && (addr32 == 0))
|
||||
@ -668,6 +739,19 @@ static void asm_opcode(TCCState *s1, int opcode)
|
||||
g(0x66);
|
||||
|
||||
addr32 = data32 = 0;
|
||||
#else
|
||||
/* generate data16 prefix if needed */
|
||||
if (s == 1 || (pa->instr_type & OPC_D16))
|
||||
g(0x66);
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
else if (s == 3) {
|
||||
/* generate REX prefix */
|
||||
if ((opcode != TOK_ASM_push && opcode != TOK_ASM_pop)
|
||||
|| !(ops[0].type & OP_REG64))
|
||||
g(0x48);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* now generates the operation */
|
||||
if (pa->instr_type & OPC_FWAIT)
|
||||
@ -694,7 +778,7 @@ static void asm_opcode(TCCState *s1, int opcode)
|
||||
nb_ops = 0;
|
||||
} else if (v <= 0x05) {
|
||||
/* arith case */
|
||||
v += ((opcode - TOK_ASM_addb) >> 2) << 3;
|
||||
v += ((opcode - TOK_ASM_addb) / NBWLX) << 3;
|
||||
} else if ((pa->instr_type & (OPC_FARITH | OPC_MODRM)) == OPC_FARITH) {
|
||||
/* fpu arith case */
|
||||
v += ((opcode - pa->sym) / 6) << 3;
|
||||
@ -751,11 +835,11 @@ static void asm_opcode(TCCState *s1, int opcode)
|
||||
/* search which operand will used for modrm */
|
||||
modrm_index = 0;
|
||||
if (pa->instr_type & OPC_SHIFT) {
|
||||
reg = (opcode - pa->sym) >> 2;
|
||||
reg = (opcode - pa->sym) / NBWLX;
|
||||
if (reg == 6)
|
||||
reg = 7;
|
||||
} else if (pa->instr_type & OPC_ARITH) {
|
||||
reg = (opcode - pa->sym) >> 2;
|
||||
reg = (opcode - pa->sym) / NBWLX;
|
||||
} else if (pa->instr_type & OPC_FARITH) {
|
||||
reg = (opcode - pa->sym) / 6;
|
||||
} else {
|
||||
@ -792,79 +876,94 @@ static void asm_opcode(TCCState *s1, int opcode)
|
||||
}
|
||||
|
||||
/* emit constants */
|
||||
#ifndef TCC_TARGET_X86_64
|
||||
if (pa->opcode == 0x9a || pa->opcode == 0xea) {
|
||||
/* ljmp or lcall kludge */
|
||||
if (s1->seg_size == 16) {
|
||||
if (o32 == 0)
|
||||
#ifdef I386_ASM_16
|
||||
if (s1->seg_size == 16 && o32 == 0)
|
||||
gen_expr16(&ops[1].e);
|
||||
else if (o32 == 1)
|
||||
else
|
||||
#endif
|
||||
gen_expr32(&ops[1].e);
|
||||
} else
|
||||
gen_expr32(&ops[1].e);
|
||||
if (ops[0].e.sym) {
|
||||
error_relocate:
|
||||
if (ops[0].e.sym)
|
||||
error("cannot relocate");
|
||||
}
|
||||
gen_le16(ops[0].e.v);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
for(i = 0;i < nb_ops; i++) {
|
||||
v = op_type[i];
|
||||
if (v & (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM8S | OP_ADDR)) {
|
||||
if (v & (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM64 | OP_IM8S | OP_ADDR)) {
|
||||
/* if multiple sizes are given it means we must look
|
||||
at the op size */
|
||||
if (v == (OP_IM8 | OP_IM16 | OP_IM32) ||
|
||||
v == (OP_IM16 | OP_IM32)) {
|
||||
if ((v | OP_IM8 | OP_IM64) == (OP_IM8 | OP_IM16 | OP_IM32 | OP_IM64)) {
|
||||
if (s == 0)
|
||||
v = OP_IM8;
|
||||
else if (s == 1)
|
||||
v = OP_IM16;
|
||||
else
|
||||
else if (s == 2 || (v & OP_IM64) == 0)
|
||||
v = OP_IM32;
|
||||
else
|
||||
v = OP_IM64;
|
||||
}
|
||||
if (v & (OP_IM8 | OP_IM8S)) {
|
||||
if (ops[i].e.sym)
|
||||
goto error_relocate;
|
||||
g(ops[i].e.v);
|
||||
} else if (v & OP_IM16) {
|
||||
#ifdef I386_ASM_16
|
||||
if (s1->seg_size == 16)
|
||||
gen_expr16(&ops[i].e);
|
||||
else {
|
||||
else
|
||||
#endif
|
||||
if (ops[i].e.sym)
|
||||
goto error_relocate;
|
||||
error_relocate:
|
||||
error("cannot relocate");
|
||||
else
|
||||
gen_le16(ops[i].e.v);
|
||||
}
|
||||
} else {
|
||||
if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) {
|
||||
if (is_short_jmp)
|
||||
g(ops[i].e.v);
|
||||
else {
|
||||
if (s1->seg_size == 16)
|
||||
#ifdef I386_ASM_16
|
||||
else if (s1->seg_size == 16)
|
||||
gen_disp16(&ops[i].e);
|
||||
#endif
|
||||
else
|
||||
gen_disp32(&ops[i].e);
|
||||
}
|
||||
} else {
|
||||
if (s1->seg_size == 16) {
|
||||
if ((o32 == 1) && (v & OP_IM32))
|
||||
gen_expr32(&ops[i].e);
|
||||
else
|
||||
gen_expr16(&ops[i].e);
|
||||
} else if (s1->seg_size == 32) {
|
||||
if (o32 == 1)
|
||||
#ifdef I386_ASM_16
|
||||
if (s1->seg_size == 16 && !((o32 == 1) && (v & OP_IM32)))
|
||||
gen_expr16(&ops[i].e);
|
||||
else
|
||||
#endif
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
if (v & OP_IM64)
|
||||
gen_expr64(&ops[i].e);
|
||||
else
|
||||
#endif
|
||||
gen_expr32(&ops[i].e);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef I386_ASM_16
|
||||
} else if (v & (OP_REG16 | OP_REG32)) {
|
||||
if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) {
|
||||
/* jmp $r */
|
||||
g(0xE0 + ops[i].reg);
|
||||
}
|
||||
#endif
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
} else if (v & (OP_REG32 | OP_REG64)) {
|
||||
if (pa->instr_type & (OPC_JMP | OPC_SHORTJMP)) {
|
||||
/* jmp $r */
|
||||
g(0xE0 + ops[i].reg);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef I386_ASM_16
|
||||
a32 = o32 = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define NB_SAVED_REGS 3
|
||||
@ -1030,25 +1129,25 @@ static void asm_compute_constraints(ASMOperand *operands,
|
||||
goto try_next;
|
||||
case 'A':
|
||||
/* allocate both eax and edx */
|
||||
if (is_reg_allocated(TREG_EAX) ||
|
||||
is_reg_allocated(TREG_EDX))
|
||||
if (is_reg_allocated(TREG_XAX) ||
|
||||
is_reg_allocated(TREG_XDX))
|
||||
goto try_next;
|
||||
op->is_llong = 1;
|
||||
op->reg = TREG_EAX;
|
||||
regs_allocated[TREG_EAX] |= reg_mask;
|
||||
regs_allocated[TREG_EDX] |= reg_mask;
|
||||
op->reg = TREG_XAX;
|
||||
regs_allocated[TREG_XAX] |= reg_mask;
|
||||
regs_allocated[TREG_XDX] |= reg_mask;
|
||||
break;
|
||||
case 'a':
|
||||
reg = TREG_EAX;
|
||||
reg = TREG_XAX;
|
||||
goto alloc_reg;
|
||||
case 'b':
|
||||
reg = 3;
|
||||
goto alloc_reg;
|
||||
case 'c':
|
||||
reg = TREG_ECX;
|
||||
reg = TREG_XCX;
|
||||
goto alloc_reg;
|
||||
case 'd':
|
||||
reg = TREG_EDX;
|
||||
reg = TREG_XDX;
|
||||
goto alloc_reg;
|
||||
case 'S':
|
||||
reg = 6;
|
||||
@ -1207,6 +1306,10 @@ static void subst_asm_operand(CString *add_str,
|
||||
size = 1;
|
||||
else if ((sv->type.t & VT_BTYPE) == VT_SHORT)
|
||||
size = 2;
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
else if ((sv->type.t & VT_BTYPE) == VT_LLONG)
|
||||
size = 8;
|
||||
#endif
|
||||
else
|
||||
size = 4;
|
||||
if (size == 1 && reg >= 4)
|
||||
@ -1222,6 +1325,10 @@ static void subst_asm_operand(CString *add_str,
|
||||
size = -1;
|
||||
} else if (modifier == 'w') {
|
||||
size = 2;
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
} else if (modifier == 'q') {
|
||||
size = 8;
|
||||
#endif
|
||||
}
|
||||
|
||||
switch(size) {
|
||||
@ -1237,6 +1344,11 @@ static void subst_asm_operand(CString *add_str,
|
||||
default:
|
||||
reg = TOK_ASM_eax + reg;
|
||||
break;
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
case 8:
|
||||
reg = TOK_ASM_rax + reg;
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%%%s", get_tok_str(reg, NULL));
|
||||
cstr_cat(add_str, buf);
|
||||
@ -1266,8 +1378,10 @@ static void asm_gen_code(ASMOperand *operands, int nb_operands,
|
||||
for(i = 0; i < NB_SAVED_REGS; i++) {
|
||||
reg = reg_saved[i];
|
||||
if (regs_allocated[reg]) {
|
||||
#ifdef I386_ASM_16
|
||||
if (tcc_state->seg_size == 16)
|
||||
g(0x66);
|
||||
#endif
|
||||
g(0x50 + reg);
|
||||
}
|
||||
}
|
||||
@ -1291,7 +1405,7 @@ static void asm_gen_code(ASMOperand *operands, int nb_operands,
|
||||
SValue sv;
|
||||
sv = *op->vt;
|
||||
sv.c.ul += 4;
|
||||
load(TREG_EDX, &sv);
|
||||
load(TREG_XDX, &sv);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1317,7 +1431,7 @@ static void asm_gen_code(ASMOperand *operands, int nb_operands,
|
||||
SValue sv;
|
||||
sv = *op->vt;
|
||||
sv.c.ul += 4;
|
||||
store(TREG_EDX, &sv);
|
||||
store(TREG_XDX, &sv);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1326,8 +1440,10 @@ static void asm_gen_code(ASMOperand *operands, int nb_operands,
|
||||
for(i = NB_SAVED_REGS - 1; i >= 0; i--) {
|
||||
reg = reg_saved[i];
|
||||
if (regs_allocated[reg]) {
|
||||
#ifdef I386_ASM_16
|
||||
if (tcc_state->seg_size == 16)
|
||||
g(0x66);
|
||||
#endif
|
||||
g(0x58 + reg);
|
||||
}
|
||||
}
|
||||
@ -1348,6 +1464,10 @@ static void asm_clobber(uint8_t *clobber_regs, const char *str)
|
||||
reg -= TOK_ASM_eax;
|
||||
} else if (reg >= TOK_ASM_ax && reg <= TOK_ASM_di) {
|
||||
reg -= TOK_ASM_ax;
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
} else if (reg >= TOK_ASM_rax && reg <= TOK_ASM_rdi) {
|
||||
reg -= TOK_ASM_rax;
|
||||
#endif
|
||||
} else {
|
||||
error("invalid clobber register '%s'", str);
|
||||
}
|
||||
|
29
i386-asm.h
29
i386-asm.h
@ -1,12 +1,12 @@
|
||||
DEF_ASM_OP0(pusha, 0x60) /* must be first OP0 */
|
||||
DEF_ASM_OP0(popa, 0x61)
|
||||
DEF_ASM_OP0(clc, 0xf8)
|
||||
DEF_ASM_OP0(clc, 0xf8) /* must be first OP0 */
|
||||
DEF_ASM_OP0(cld, 0xfc)
|
||||
DEF_ASM_OP0(cli, 0xfa)
|
||||
DEF_ASM_OP0(clts, 0x0f06)
|
||||
DEF_ASM_OP0(cmc, 0xf5)
|
||||
DEF_ASM_OP0(lahf, 0x9f)
|
||||
DEF_ASM_OP0(sahf, 0x9e)
|
||||
DEF_ASM_OP0(pusha, 0x60)
|
||||
DEF_ASM_OP0(popa, 0x61)
|
||||
DEF_ASM_OP0(pushfl, 0x9c)
|
||||
DEF_ASM_OP0(popfl, 0x9d)
|
||||
DEF_ASM_OP0(pushf, 0x9c)
|
||||
@ -74,12 +74,15 @@ ALT(DEF_ASM_OP2(btcw, 0x0fbb, 0, OPC_MODRM | OPC_WL, OPT_REGW, OPT_REGW | OPT_EA
|
||||
ALT(DEF_ASM_OP2(btcw, 0x0fba, 7, OPC_MODRM | OPC_WL, OPT_IM8, OPT_REGW | OPT_EA))
|
||||
|
||||
/* prefixes */
|
||||
DEF_ASM_OP0(addr16, 0x67)
|
||||
#ifdef I386_ASM_16
|
||||
DEF_ASM_OP0(a32, 0x67)
|
||||
|
||||
DEF_ASM_OP0(data16, 0x66)
|
||||
DEF_ASM_OP0(o32, 0x66)
|
||||
|
||||
#else
|
||||
DEF_ASM_OP0(aword, 0x67)
|
||||
DEF_ASM_OP0(addr16, 0x67)
|
||||
ALT(DEF_ASM_OP0(word, 0x66))
|
||||
DEF_ASM_OP0(data16, 0x66)
|
||||
#endif
|
||||
DEF_ASM_OP0(lock, 0xf0)
|
||||
DEF_ASM_OP0(rep, 0xf3)
|
||||
DEF_ASM_OP0(repe, 0xf3)
|
||||
@ -122,9 +125,9 @@ ALT(DEF_ASM_OP2(movzwl, 0x0fb7, 0, OPC_MODRM, OPT_REG16 | OPT_EA, OPT_REG32))
|
||||
|
||||
ALT(DEF_ASM_OP1(pushw, 0x50, 0, OPC_REG | OPC_WL, OPT_REGW))
|
||||
ALT(DEF_ASM_OP1(pushw, 0xff, 6, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
|
||||
ALT(DEF_ASM_OP1(pushw, 0x6a, 0, OPC_WL, OPT_IM8S))
|
||||
ALT(DEF_ASM_OP1(pushw, 0x68, 0, OPC_WL, OPT_IM32))
|
||||
ALT(DEF_ASM_OP1(pushw, 0x06, 0, OPC_WL, OPT_SEG))
|
||||
DEF_ASM_OP1(pushb, 0x6a, 0, OPC_B, OPT_IM8S)
|
||||
|
||||
ALT(DEF_ASM_OP1(popw, 0x58, 0, OPC_REG | OPC_WL, OPT_REGW))
|
||||
ALT(DEF_ASM_OP1(popw, 0x8f, 0, OPC_MODRM | OPC_WL, OPT_REGW | OPT_EA))
|
||||
@ -203,7 +206,9 @@ ALT(DEF_ASM_OP1(call, 0xff, 2, OPC_MODRM, OPT_INDIR))
|
||||
ALT(DEF_ASM_OP1(call, 0xe8, 0, OPC_JMP, OPT_ADDR))
|
||||
ALT(DEF_ASM_OP1(jmp, 0xff, 4, OPC_MODRM, OPT_INDIR))
|
||||
ALT(DEF_ASM_OP1(jmp, 0xeb, 0, OPC_SHORTJMP | OPC_JMP, OPT_ADDR))
|
||||
#ifdef I386_ASM_16
|
||||
ALT(DEF_ASM_OP1(jmp, 0xff, 0, OPC_JMP | OPC_WL, OPT_REGW))
|
||||
#endif
|
||||
|
||||
ALT(DEF_ASM_OP2(lcall, 0x9a, 0, 0, OPT_IM16, OPT_IM32))
|
||||
ALT(DEF_ASM_OP1(lcall, 0xff, 3, 0, OPT_EA))
|
||||
@ -353,8 +358,10 @@ ALT(DEF_ASM_OP2(lslw, 0x0f03, 0, OPC_MODRM | OPC_WL, OPT_EA | OPT_REG, OPT_REG))
|
||||
DEF_ASM_OP1(verr, 0x0f00, 4, OPC_MODRM, OPT_REG | OPT_EA)
|
||||
DEF_ASM_OP1(verw, 0x0f00, 5, OPC_MODRM, OPT_REG | OPT_EA)
|
||||
|
||||
#ifdef I386_ASM_16
|
||||
/* 386 */
|
||||
DEF_ASM_OP0(loadall386, 0x0f07)
|
||||
#endif
|
||||
|
||||
/* 486 */
|
||||
DEF_ASM_OP1(bswap, 0x0fc8, 0, OPC_REG, OPT_REG32 )
|
||||
@ -369,7 +376,8 @@ ALT(DEF_ASM_OP2(cmpxchgb, 0x0fb0, 0, OPC_MODRM | OPC_BWL, OPT_REG, OPT_REG | OPT
|
||||
DEF_ASM_OP1(cmpxchg8b, 0x0fc7, 1, OPC_MODRM, OPT_EA )
|
||||
|
||||
/* pentium pro */
|
||||
ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(cmovo, 0x0f40, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
|
||||
#ifdef I386_ASM_16
|
||||
ALT(DEF_ASM_OP2(cmovno, 0x0f41, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(cmovc, 0x0f42, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(cmovnc, 0x0f43, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
|
||||
@ -377,7 +385,7 @@ ALT(DEF_ASM_OP2(cmovz, 0x0f44, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_
|
||||
ALT(DEF_ASM_OP2(cmovnz, 0x0f45, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(cmovna, 0x0f46, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
|
||||
ALT(DEF_ASM_OP2(cmova, 0x0f47, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_REG32))
|
||||
|
||||
#endif
|
||||
DEF_ASM_OP2(fcmovb, 0xdac0, 0, OPC_REG, OPT_ST, OPT_ST0 )
|
||||
DEF_ASM_OP2(fcmove, 0xdac8, 0, OPC_REG, OPT_ST, OPT_ST0 )
|
||||
DEF_ASM_OP2(fcmovbe, 0xdad0, 0, OPC_REG, OPT_ST, OPT_ST0 )
|
||||
@ -394,6 +402,7 @@ ALT(DEF_ASM_OP2(cmova, 0x0f47, 0, OPC_MODRM | OPC_TEST, OPT_REG32 | OPT_EA, OPT_
|
||||
|
||||
/* mmx */
|
||||
DEF_ASM_OP0(emms, 0x0f77) /* must be last OP0 */
|
||||
|
||||
DEF_ASM_OP2(movd, 0x0f6e, 0, OPC_MODRM, OPT_EA | OPT_REG32, OPT_MMX )
|
||||
ALT(DEF_ASM_OP2(movd, 0x0f7e, 0, OPC_MODRM, OPT_MMX, OPT_EA | OPT_REG32 ))
|
||||
DEF_ASM_OP2(movq, 0x0f6f, 0, OPC_MODRM, OPT_EA | OPT_MMX, OPT_MMX )
|
||||
|
13
i386-gen.c
13
i386-gen.c
@ -109,6 +109,12 @@ void o(unsigned int c)
|
||||
}
|
||||
}
|
||||
|
||||
void gen_le16(int v)
|
||||
{
|
||||
g(v);
|
||||
g(v >> 8);
|
||||
}
|
||||
|
||||
void gen_le32(int c)
|
||||
{
|
||||
g(c);
|
||||
@ -161,6 +167,13 @@ static void gen_addr32(int r, Sym *sym, int c)
|
||||
gen_le32(c);
|
||||
}
|
||||
|
||||
static void gen_addrpc32(int r, Sym *sym, int c)
|
||||
{
|
||||
if (r & VT_SYM)
|
||||
greloc(cur_text_section, sym, ind, R_386_PC32);
|
||||
gen_le32(c - 4);
|
||||
}
|
||||
|
||||
/* generate a modrm reference. 'op_reg' contains the addtionnal 3
|
||||
opcode bits */
|
||||
static void gen_modrm(int op_reg, int r, Sym *sym, int c)
|
||||
|
133
i386-tok.h
133
i386-tok.h
@ -1,5 +1,7 @@
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* WARNING: relative order of tokens is important. */
|
||||
|
||||
/* register */
|
||||
DEF_ASM(al)
|
||||
DEF_ASM(cl)
|
||||
DEF_ASM(dl)
|
||||
@ -24,6 +26,16 @@
|
||||
DEF_ASM(ebp)
|
||||
DEF_ASM(esi)
|
||||
DEF_ASM(edi)
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
DEF_ASM(rax)
|
||||
DEF_ASM(rcx)
|
||||
DEF_ASM(rdx)
|
||||
DEF_ASM(rbx)
|
||||
DEF_ASM(rsp)
|
||||
DEF_ASM(rbp)
|
||||
DEF_ASM(rsi)
|
||||
DEF_ASM(rdi)
|
||||
#endif
|
||||
DEF_ASM(mm0)
|
||||
DEF_ASM(mm1)
|
||||
DEF_ASM(mm2)
|
||||
@ -80,39 +92,39 @@
|
||||
DEF_ASM(gs)
|
||||
DEF_ASM(st)
|
||||
|
||||
DEF_BWL(mov)
|
||||
|
||||
/* generic two operands */
|
||||
DEF_BWL(add)
|
||||
DEF_BWL(or)
|
||||
DEF_BWL(adc)
|
||||
DEF_BWL(sbb)
|
||||
DEF_BWL(and)
|
||||
DEF_BWL(sub)
|
||||
DEF_BWL(xor)
|
||||
DEF_BWL(cmp)
|
||||
DEF_BWLX(mov)
|
||||
|
||||
DEF_BWLX(add)
|
||||
DEF_BWLX(or)
|
||||
DEF_BWLX(adc)
|
||||
DEF_BWLX(sbb)
|
||||
DEF_BWLX(and)
|
||||
DEF_BWLX(sub)
|
||||
DEF_BWLX(xor)
|
||||
DEF_BWLX(cmp)
|
||||
|
||||
/* unary ops */
|
||||
DEF_BWL(inc)
|
||||
DEF_BWL(dec)
|
||||
DEF_BWL(not)
|
||||
DEF_BWL(neg)
|
||||
DEF_BWL(mul)
|
||||
DEF_BWL(imul)
|
||||
DEF_BWL(div)
|
||||
DEF_BWL(idiv)
|
||||
DEF_BWLX(inc)
|
||||
DEF_BWLX(dec)
|
||||
DEF_BWLX(not)
|
||||
DEF_BWLX(neg)
|
||||
DEF_BWLX(mul)
|
||||
DEF_BWLX(imul)
|
||||
DEF_BWLX(div)
|
||||
DEF_BWLX(idiv)
|
||||
|
||||
DEF_BWL(xchg)
|
||||
DEF_BWL(test)
|
||||
DEF_BWLX(xchg)
|
||||
DEF_BWLX(test)
|
||||
|
||||
/* shifts */
|
||||
DEF_BWL(rol)
|
||||
DEF_BWL(ror)
|
||||
DEF_BWL(rcl)
|
||||
DEF_BWL(rcr)
|
||||
DEF_BWL(shl)
|
||||
DEF_BWL(shr)
|
||||
DEF_BWL(sar)
|
||||
DEF_BWLX(rol)
|
||||
DEF_BWLX(ror)
|
||||
DEF_BWLX(rcl)
|
||||
DEF_BWLX(rcr)
|
||||
DEF_BWLX(shl)
|
||||
DEF_BWLX(shr)
|
||||
DEF_BWLX(sar)
|
||||
|
||||
DEF_ASM(shldw)
|
||||
DEF_ASM(shldl)
|
||||
@ -123,21 +135,31 @@
|
||||
|
||||
DEF_ASM(pushw)
|
||||
DEF_ASM(pushl)
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
DEF_ASM(pushq)
|
||||
#endif
|
||||
DEF_ASM(push)
|
||||
|
||||
DEF_ASM(popw)
|
||||
DEF_ASM(popl)
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
DEF_ASM(popq)
|
||||
#endif
|
||||
DEF_ASM(pop)
|
||||
|
||||
DEF_BWL(in)
|
||||
DEF_BWL(out)
|
||||
|
||||
DEF_WL(movzb)
|
||||
|
||||
DEF_ASM(movzwl)
|
||||
DEF_ASM(movsbw)
|
||||
DEF_ASM(movsbl)
|
||||
DEF_ASM(movswl)
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
DEF_ASM(movslq)
|
||||
#endif
|
||||
|
||||
DEF_WL(lea)
|
||||
DEF_WLX(lea)
|
||||
|
||||
DEF_ASM(les)
|
||||
DEF_ASM(lds)
|
||||
@ -155,14 +177,14 @@
|
||||
DEF_ASMTEST(set)
|
||||
DEF_ASMTEST(cmov)
|
||||
|
||||
DEF_WL(bsf)
|
||||
DEF_WL(bsr)
|
||||
DEF_WL(bt)
|
||||
DEF_WL(bts)
|
||||
DEF_WL(btr)
|
||||
DEF_WL(btc)
|
||||
DEF_WLX(bsf)
|
||||
DEF_WLX(bsr)
|
||||
DEF_WLX(bt)
|
||||
DEF_WLX(bts)
|
||||
DEF_WLX(btr)
|
||||
DEF_WLX(btc)
|
||||
|
||||
DEF_WL(lsl)
|
||||
DEF_WLX(lsl)
|
||||
|
||||
/* generic FP ops */
|
||||
DEF_FP(add)
|
||||
@ -178,32 +200,35 @@
|
||||
DEF_FP(div)
|
||||
DEF_FP(divr)
|
||||
|
||||
DEF_BWL(xadd)
|
||||
DEF_BWL(cmpxchg)
|
||||
DEF_BWLX(xadd)
|
||||
DEF_BWLX(cmpxchg)
|
||||
|
||||
/* string ops */
|
||||
DEF_BWL(cmps)
|
||||
DEF_BWL(scmp)
|
||||
DEF_BWLX(cmps)
|
||||
DEF_BWLX(scmp)
|
||||
DEF_BWL(ins)
|
||||
DEF_BWL(outs)
|
||||
DEF_BWL(lods)
|
||||
DEF_BWL(slod)
|
||||
DEF_BWL(movs)
|
||||
DEF_BWL(smov)
|
||||
DEF_BWL(scas)
|
||||
DEF_BWL(ssca)
|
||||
DEF_BWL(stos)
|
||||
DEF_BWL(ssto)
|
||||
DEF_BWLX(lods)
|
||||
DEF_BWLX(slod)
|
||||
DEF_BWLX(movs)
|
||||
DEF_BWLX(smov)
|
||||
DEF_BWLX(scas)
|
||||
DEF_BWLX(ssca)
|
||||
DEF_BWLX(stos)
|
||||
DEF_BWLX(ssto)
|
||||
|
||||
/* generic asm ops */
|
||||
|
||||
#define ALT(x)
|
||||
#define DEF_ASM_OP0(name, opcode) DEF_ASM(name)
|
||||
#define DEF_ASM_OP0L(name, opcode, group, instr_type)
|
||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
|
||||
#include "i386-asm.h"
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
# include "x86_64-asm.h"
|
||||
#else
|
||||
# include "i386-asm.h"
|
||||
#endif
|
||||
|
||||
#define ALT(x)
|
||||
#define DEF_ASM_OP0(name, opcode)
|
||||
@ -211,4 +236,8 @@
|
||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
|
||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
|
||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
|
||||
#include "i386-asm.h"
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
# include "x86_64-asm.h"
|
||||
#else
|
||||
# include "i386-asm.h"
|
||||
#endif
|
||||
|
14
libtcc.c
14
libtcc.c
@ -325,14 +325,10 @@ static inline int toup(int c)
|
||||
|
||||
#ifdef CONFIG_TCC_ASM
|
||||
|
||||
#ifdef TCC_TARGET_I386
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
#include "i386-asm.c"
|
||||
#endif
|
||||
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
#include "x86_64-asm.c"
|
||||
#endif
|
||||
|
||||
#include "tccasm.c"
|
||||
#else
|
||||
static void asm_instr(void)
|
||||
@ -854,10 +850,14 @@ static void put_extern_sym(Sym *sym, Section *section,
|
||||
/* add a new relocation entry to symbol 'sym' in section 's' */
|
||||
static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
|
||||
{
|
||||
if (!sym->c)
|
||||
int c = 0;
|
||||
if (sym) {
|
||||
if (0 == sym->c)
|
||||
put_extern_sym(sym, NULL, 0, 0);
|
||||
c = sym->c;
|
||||
}
|
||||
/* now we can add ELF relocation info */
|
||||
put_elf_reloc(symtab_section, s, offset, type, sym->c);
|
||||
put_elf_reloc(symtab_section, s, offset, type, c);
|
||||
}
|
||||
|
||||
static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
|
||||
|
24
tcc.h
24
tcc.h
@ -660,35 +660,41 @@ struct TCCState {
|
||||
/* all identificators and strings have token above that */
|
||||
#define TOK_IDENT 256
|
||||
|
||||
/* only used for i386 asm opcodes definitions */
|
||||
#define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
|
||||
#define TOK_ASM_int TOK_INT
|
||||
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
/* only used for i386 asm opcodes definitions */
|
||||
#define DEF_BWL(x) \
|
||||
DEF(TOK_ASM_ ## x ## b, #x "b") \
|
||||
DEF(TOK_ASM_ ## x ## w, #x "w") \
|
||||
DEF(TOK_ASM_ ## x ## l, #x "l") \
|
||||
DEF(TOK_ASM_ ## x, #x)
|
||||
|
||||
#define DEF_WL(x) \
|
||||
DEF(TOK_ASM_ ## x ## w, #x "w") \
|
||||
DEF(TOK_ASM_ ## x ## l, #x "l") \
|
||||
DEF(TOK_ASM_ ## x, #x)
|
||||
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
|
||||
#define DEF_BWLQ(x) \
|
||||
# define DEF_BWLQ(x) \
|
||||
DEF(TOK_ASM_ ## x ## b, #x "b") \
|
||||
DEF(TOK_ASM_ ## x ## w, #x "w") \
|
||||
DEF(TOK_ASM_ ## x ## l, #x "l") \
|
||||
DEF(TOK_ASM_ ## x ## q, #x "q") \
|
||||
DEF(TOK_ASM_ ## x, #x)
|
||||
|
||||
#define DEF_WLQ(x) \
|
||||
# define DEF_WLQ(x) \
|
||||
DEF(TOK_ASM_ ## x ## w, #x "w") \
|
||||
DEF(TOK_ASM_ ## x ## l, #x "l") \
|
||||
DEF(TOK_ASM_ ## x ## q, #x "q") \
|
||||
DEF(TOK_ASM_ ## x, #x)
|
||||
|
||||
# define DEF_BWLX DEF_BWLQ
|
||||
# define DEF_WLX DEF_WLQ
|
||||
/* number of sizes + 1 */
|
||||
# define NBWLX 5
|
||||
#else
|
||||
# define DEF_BWLX DEF_BWL
|
||||
# define DEF_WLX DEF_WL
|
||||
/* number of sizes + 1 */
|
||||
# define NBWLX 4
|
||||
#endif
|
||||
|
||||
#define DEF_FP1(x) \
|
||||
@ -734,7 +740,7 @@ struct TCCState {
|
||||
DEF_ASM(x ## nle) \
|
||||
DEF_ASM(x ## g)
|
||||
|
||||
#define TOK_ASM_int TOK_INT
|
||||
#endif // defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
|
||||
enum tcc_token {
|
||||
TOK_LAST = TOK_IDENT - 1,
|
||||
|
6
tcctok.h
6
tcctok.h
@ -233,7 +233,6 @@
|
||||
#endif
|
||||
|
||||
/* Tiny Assembler */
|
||||
|
||||
DEF_ASM(byte)
|
||||
DEF_ASM(word)
|
||||
DEF_ASM(align)
|
||||
@ -258,9 +257,6 @@
|
||||
DEF_ASM(code64)
|
||||
#endif
|
||||
|
||||
#ifdef TCC_TARGET_I386
|
||||
#if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
|
||||
#include "i386-tok.h"
|
||||
#elif TCC_TARGET_X86_64
|
||||
#include "x86_64-tok.h"
|
||||
#endif
|
||||
|
||||
|
@ -3,8 +3,6 @@
|
||||
@rem ----------------------------------------------------
|
||||
@set PROMPT=$G$S
|
||||
|
||||
copy ..\include\*.h include
|
||||
|
||||
echo>..\config.h #define TCC_VERSION "0.9.25"
|
||||
echo>>..\config.h #define TCC_TARGET_PE 1
|
||||
echo>>..\config.h #define CONFIG_TCCDIR "."
|
||||
@ -27,7 +25,6 @@ echo>>..\config.h #define TCC_TARGET_X86_64 1
|
||||
:libtcc
|
||||
if not exist libtcc\nul mkdir libtcc
|
||||
copy ..\libtcc.h libtcc\libtcc.h
|
||||
|
||||
%P%gcc -Os -fno-strict-aliasing ../libtcc.c -c -o libtcc.o
|
||||
%P%ar rcs libtcc/libtcc.a libtcc.o
|
||||
|
||||
@ -35,24 +32,13 @@ copy ..\libtcc.h libtcc\libtcc.h
|
||||
%P%gcc -Os -fno-strict-aliasing ../tcc.c -o tcc.exe -s -DTCC_USE_LIBTCC -ltcc -Llibtcc
|
||||
|
||||
:libtcc1.a
|
||||
copy ..\include\*.h include
|
||||
.\tcc -c lib/crt1.c
|
||||
.\tcc -c lib/wincrt1.c
|
||||
.\tcc -c lib/dllcrt1.c
|
||||
.\tcc -c lib/dllmain.c
|
||||
.\tcc -c ../lib/libtcc1.c
|
||||
@rem if not x%P%==x goto use_yasm
|
||||
.\tcc -c lib/chkstk.S
|
||||
.\tcc -c ../lib/alloca86%S%.S
|
||||
tiny_libmaker lib/libtcc1.a crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o libtcc1.o alloca86%S%.o
|
||||
@goto cleanup
|
||||
|
||||
:use_yasm
|
||||
.\tcc -o tmp.s -E lib/chkstk.S
|
||||
yasm -p gnu -f elf64 -o chkstk.o tmp.s
|
||||
.\tcc -o tmp.s -E ../lib/alloca86_64.S
|
||||
yasm -p gnu -f elf64 -o alloca86_64.o tmp.s
|
||||
del tmp.s
|
||||
tiny_libmaker lib/libtcc1.a crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o libtcc1.o alloca86_64.o
|
||||
|
||||
:cleanup
|
||||
del *.o
|
||||
|
1266
x86_64-asm.c
1266
x86_64-asm.c
File diff suppressed because it is too large
Load Diff
15
x86_64-gen.c
15
x86_64-gen.c
@ -123,6 +123,12 @@ void o(unsigned int c)
|
||||
}
|
||||
}
|
||||
|
||||
void gen_le16(int v)
|
||||
{
|
||||
g(v);
|
||||
g(v >> 8);
|
||||
}
|
||||
|
||||
void gen_le32(int c)
|
||||
{
|
||||
g(c);
|
||||
@ -192,7 +198,13 @@ static int oad(int c, int s)
|
||||
return s;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void gen_addr32(int r, Sym *sym, int c)
|
||||
{
|
||||
if (r & VT_SYM)
|
||||
greloc(cur_text_section, sym, ind, R_X86_64_32);
|
||||
gen_le32(c);
|
||||
}
|
||||
|
||||
/* output constant with relocation if 'r & VT_SYM' is true */
|
||||
static void gen_addr64(int r, Sym *sym, int64_t c)
|
||||
{
|
||||
@ -200,7 +212,6 @@ static void gen_addr64(int r, Sym *sym, int64_t c)
|
||||
greloc(cur_text_section, sym, ind, R_X86_64_64);
|
||||
gen_le64(c);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* output constant with relocation if 'r & VT_SYM' is true */
|
||||
static void gen_addrpc32(int r, Sym *sym, int c)
|
||||
|
225
x86_64-tok.h
225
x86_64-tok.h
@ -1,225 +0,0 @@
|
||||
|
||||
/* WARNING: relative order of tokens is important. */
|
||||
DEF_ASM(al)
|
||||
DEF_ASM(cl)
|
||||
DEF_ASM(dl)
|
||||
DEF_ASM(bl)
|
||||
DEF_ASM(ah)
|
||||
DEF_ASM(ch)
|
||||
DEF_ASM(dh)
|
||||
DEF_ASM(bh)
|
||||
DEF_ASM(ax)
|
||||
DEF_ASM(cx)
|
||||
DEF_ASM(dx)
|
||||
DEF_ASM(bx)
|
||||
DEF_ASM(sp)
|
||||
DEF_ASM(bp)
|
||||
DEF_ASM(si)
|
||||
DEF_ASM(di)
|
||||
DEF_ASM(eax)
|
||||
DEF_ASM(ecx)
|
||||
DEF_ASM(edx)
|
||||
DEF_ASM(ebx)
|
||||
DEF_ASM(esp)
|
||||
DEF_ASM(ebp)
|
||||
DEF_ASM(esi)
|
||||
DEF_ASM(edi)
|
||||
DEF_ASM(rax)
|
||||
DEF_ASM(rcx)
|
||||
DEF_ASM(rdx)
|
||||
DEF_ASM(rbx)
|
||||
DEF_ASM(rsp)
|
||||
DEF_ASM(rbp)
|
||||
DEF_ASM(rsi)
|
||||
DEF_ASM(rdi)
|
||||
DEF_ASM(mm0)
|
||||
DEF_ASM(mm1)
|
||||
DEF_ASM(mm2)
|
||||
DEF_ASM(mm3)
|
||||
DEF_ASM(mm4)
|
||||
DEF_ASM(mm5)
|
||||
DEF_ASM(mm6)
|
||||
DEF_ASM(mm7)
|
||||
DEF_ASM(xmm0)
|
||||
DEF_ASM(xmm1)
|
||||
DEF_ASM(xmm2)
|
||||
DEF_ASM(xmm3)
|
||||
DEF_ASM(xmm4)
|
||||
DEF_ASM(xmm5)
|
||||
DEF_ASM(xmm6)
|
||||
DEF_ASM(xmm7)
|
||||
DEF_ASM(cr0)
|
||||
DEF_ASM(cr1)
|
||||
DEF_ASM(cr2)
|
||||
DEF_ASM(cr3)
|
||||
DEF_ASM(cr4)
|
||||
DEF_ASM(cr5)
|
||||
DEF_ASM(cr6)
|
||||
DEF_ASM(cr7)
|
||||
DEF_ASM(tr0)
|
||||
DEF_ASM(tr1)
|
||||
DEF_ASM(tr2)
|
||||
DEF_ASM(tr3)
|
||||
DEF_ASM(tr4)
|
||||
DEF_ASM(tr5)
|
||||
DEF_ASM(tr6)
|
||||
DEF_ASM(tr7)
|
||||
DEF_ASM(db0)
|
||||
DEF_ASM(db1)
|
||||
DEF_ASM(db2)
|
||||
DEF_ASM(db3)
|
||||
DEF_ASM(db4)
|
||||
DEF_ASM(db5)
|
||||
DEF_ASM(db6)
|
||||
DEF_ASM(db7)
|
||||
DEF_ASM(dr0)
|
||||
DEF_ASM(dr1)
|
||||
DEF_ASM(dr2)
|
||||
DEF_ASM(dr3)
|
||||
DEF_ASM(dr4)
|
||||
DEF_ASM(dr5)
|
||||
DEF_ASM(dr6)
|
||||
DEF_ASM(dr7)
|
||||
DEF_ASM(es)
|
||||
DEF_ASM(cs)
|
||||
DEF_ASM(ss)
|
||||
DEF_ASM(ds)
|
||||
DEF_ASM(fs)
|
||||
DEF_ASM(gs)
|
||||
DEF_ASM(st)
|
||||
|
||||
DEF_BWLQ(mov)
|
||||
|
||||
/* generic two operands */
|
||||
DEF_BWLQ(add)
|
||||
DEF_BWLQ(or)
|
||||
DEF_BWLQ(adc)
|
||||
DEF_BWLQ(sbb)
|
||||
DEF_BWLQ(and)
|
||||
DEF_BWLQ(sub)
|
||||
DEF_BWLQ(xor)
|
||||
DEF_BWLQ(cmp)
|
||||
|
||||
/* unary ops */
|
||||
DEF_BWLQ(inc)
|
||||
DEF_BWLQ(dec)
|
||||
DEF_BWLQ(not)
|
||||
DEF_BWLQ(neg)
|
||||
DEF_BWLQ(mul)
|
||||
DEF_BWLQ(imul)
|
||||
DEF_BWLQ(div)
|
||||
DEF_BWLQ(idiv)
|
||||
|
||||
DEF_BWLQ(xchg)
|
||||
DEF_BWLQ(test)
|
||||
|
||||
/* shifts */
|
||||
DEF_BWLQ(rol)
|
||||
DEF_BWLQ(ror)
|
||||
DEF_BWLQ(rcl)
|
||||
DEF_BWLQ(rcr)
|
||||
DEF_BWLQ(shl)
|
||||
DEF_BWLQ(shr)
|
||||
DEF_BWLQ(sar)
|
||||
|
||||
DEF_ASM(shldw)
|
||||
DEF_ASM(shldl)
|
||||
DEF_ASM(shld)
|
||||
DEF_ASM(shrdw)
|
||||
DEF_ASM(shrdl)
|
||||
DEF_ASM(shrd)
|
||||
|
||||
DEF_ASM(pushw)
|
||||
DEF_ASM(pushl)
|
||||
DEF_ASM(pushq)
|
||||
DEF_ASM(push)
|
||||
DEF_ASM(popw)
|
||||
DEF_ASM(popl)
|
||||
DEF_ASM(popq)
|
||||
DEF_ASM(pop)
|
||||
DEF_BWL(in)
|
||||
DEF_BWL(out)
|
||||
|
||||
DEF_WL(movzb)
|
||||
|
||||
DEF_ASM(movzwl)
|
||||
DEF_ASM(movsbw)
|
||||
DEF_ASM(movsbl)
|
||||
DEF_ASM(movswl)
|
||||
DEF_ASM(movslq)
|
||||
|
||||
DEF_WLQ(lea)
|
||||
|
||||
DEF_ASM(les)
|
||||
DEF_ASM(lds)
|
||||
DEF_ASM(lss)
|
||||
DEF_ASM(lfs)
|
||||
DEF_ASM(lgs)
|
||||
|
||||
DEF_ASM(call)
|
||||
DEF_ASM(jmp)
|
||||
DEF_ASM(lcall)
|
||||
DEF_ASM(ljmp)
|
||||
|
||||
DEF_ASMTEST(j)
|
||||
|
||||
DEF_ASMTEST(set)
|
||||
DEF_ASMTEST(cmov)
|
||||
|
||||
DEF_WLQ(bsf)
|
||||
DEF_WLQ(bsr)
|
||||
DEF_WLQ(bt)
|
||||
DEF_WLQ(bts)
|
||||
DEF_WLQ(btr)
|
||||
DEF_WLQ(btc)
|
||||
|
||||
DEF_WLQ(lsl)
|
||||
|
||||
/* generic FP ops */
|
||||
DEF_FP(add)
|
||||
DEF_FP(mul)
|
||||
|
||||
DEF_ASM(fcom)
|
||||
DEF_ASM(fcom_1) /* non existant op, just to have a regular table */
|
||||
DEF_FP1(com)
|
||||
|
||||
DEF_FP(comp)
|
||||
DEF_FP(sub)
|
||||
DEF_FP(subr)
|
||||
DEF_FP(div)
|
||||
DEF_FP(divr)
|
||||
|
||||
DEF_BWLQ(xadd)
|
||||
DEF_BWLQ(cmpxchg)
|
||||
|
||||
/* string ops */
|
||||
DEF_BWLQ(cmps)
|
||||
DEF_BWLQ(scmp)
|
||||
DEF_BWL(ins)
|
||||
DEF_BWL(outs)
|
||||
DEF_BWLQ(lods)
|
||||
DEF_BWLQ(slod)
|
||||
DEF_BWLQ(movs)
|
||||
DEF_BWLQ(smov)
|
||||
DEF_BWLQ(scas)
|
||||
DEF_BWLQ(ssca)
|
||||
DEF_BWLQ(stos)
|
||||
DEF_BWLQ(ssto)
|
||||
|
||||
/* generic asm ops */
|
||||
|
||||
#define ALT(x)
|
||||
#define DEF_ASM_OP0(name, opcode) DEF_ASM(name)
|
||||
#define DEF_ASM_OP0L(name, opcode, group, instr_type)
|
||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0)
|
||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1)
|
||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2)
|
||||
#include "x86_64-asm.h"
|
||||
|
||||
#define ALT(x)
|
||||
#define DEF_ASM_OP0(name, opcode)
|
||||
#define DEF_ASM_OP0L(name, opcode, group, instr_type) DEF_ASM(name)
|
||||
#define DEF_ASM_OP1(name, opcode, group, instr_type, op0) DEF_ASM(name)
|
||||
#define DEF_ASM_OP2(name, opcode, group, instr_type, op0, op1) DEF_ASM(name)
|
||||
#define DEF_ASM_OP3(name, opcode, group, instr_type, op0, op1, op2) DEF_ASM(name)
|
||||
#include "x86_64-asm.h"
|
Loading…
Reference in New Issue
Block a user