Yasm Assembler mainline development tree (ffmpeg 依赖)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

228 lines
7.3 KiB

/* $IdPath$
* x86 Architecture header file
*
* Copyright (C) 2001 Peter Johnson
*
* This file is part of YASM.
*
* YASM is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* YASM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef YASM_X86ARCH_H
#define YASM_X86ARCH_H
typedef enum {
X86_BC_INSN = BYTECODE_TYPE_BASE,
X86_BC_JMPREL
} x86_bytecode_type;
#define X86_BYTECODE_TYPE_MAX X86_BC_JMPREL+1
/* 0-7 (low 3 bits) used for register number, stored in same data area */
typedef enum {
X86_REG8 = 0x8,
X86_REG16 = 0x10,
X86_REG32 = 0x20,
X86_MMXREG = 0x40,
X86_XMMREG = 0x80,
X86_CRREG = 0xC0,
X86_DRREG = 0xC8,
X86_TRREG = 0xF0,
X86_FPUREG = 0xF8
} x86_expritem_reg_size;
typedef enum {
X86_LOCKREP = 1,
X86_ADDRSIZE,
X86_OPERSIZE
} x86_parse_insn_prefix;
typedef enum {
X86_NEAR = 1,
X86_SHORT,
X86_FAR,
X86_TO
} x86_parse_targetmod;
typedef enum {
JR_NONE,
JR_SHORT,
JR_NEAR,
JR_SHORT_FORCED,
JR_NEAR_FORCED
} x86_jmprel_opcode_sel;
void x86_ea_set_segment(/*@null@*/ effaddr *ea, unsigned char segment);
effaddr *x86_ea_new_reg(unsigned char reg);
effaddr *x86_ea_new_imm(/*@keep@*/expr *imm, unsigned char im_len);
effaddr *x86_ea_new_expr(/*@keep@*/ expr *e);
/*@observer@*/ /*@null@*/ effaddr *x86_bc_insn_get_ea(/*@null@*/ bytecode *bc);
void x86_bc_insn_opersize_override(bytecode *bc, unsigned char opersize);
void x86_bc_insn_addrsize_override(bytecode *bc, unsigned char addrsize);
void x86_bc_insn_set_lockrep_prefix(bytecode *bc, unsigned char prefix);
void x86_set_jmprel_opcode_sel(x86_jmprel_opcode_sel *old_sel,
x86_jmprel_opcode_sel new_sel);
/* Structure with *all* inputs passed to x86_bytecode_new_insn().
* IMPORTANT: ea_ptr and im_ptr cannot be reused or freed after calling the
* function (it doesn't make a copy).
*/
typedef struct x86_new_insn_data {
/*@keep@*/ /*@null@*/ effaddr *ea;
/*@keep@*/ /*@null@*/ expr *imm;
unsigned char opersize;
unsigned char op_len;
unsigned char op[3];
unsigned char spare; /* bits to go in 'spare' field of ModRM */
unsigned char im_len;
unsigned char im_sign;
unsigned char shift_op;
unsigned char signext_imm8_op;
} x86_new_insn_data;
bytecode *x86_bc_new_insn(x86_new_insn_data *d);
/* Structure with *all* inputs passed to x86_bytecode_new_jmprel().
* Pass 0 for the opcode_len if that version of the opcode doesn't exist.
*/
typedef struct x86_new_jmprel_data {
/*@keep@*/ expr *target;
x86_jmprel_opcode_sel op_sel;
unsigned char short_op_len;
unsigned char short_op[3];
unsigned char near_op_len;
unsigned char near_op[3];
unsigned char addrsize;
unsigned char opersize;
} x86_new_jmprel_data;
bytecode *x86_bc_new_jmprel(x86_new_jmprel_data *d);
extern unsigned char x86_mode_bits;
typedef struct x86_effaddr_data {
unsigned char segment; /* segment override, 0 if none */
/* How the spare (register) bits in Mod/RM are handled:
* Even if valid_modrm=0, the spare bits are still valid (don't overwrite!)
* They're set in bytecode_new_insn().
*/
unsigned char modrm;
unsigned char valid_modrm; /* 1 if Mod/RM byte currently valid, 0 if not */
unsigned char need_modrm; /* 1 if Mod/RM byte needed, 0 if not */
unsigned char sib;
unsigned char valid_sib; /* 1 if SIB byte currently valid, 0 if not */
unsigned char need_sib; /* 1 if SIB byte needed, 0 if not,
0xff if unknown */
} x86_effaddr_data;
typedef struct x86_insn {
/*@null@*/ effaddr *ea; /* effective address */
/*@null@*/ immval *imm; /* immediate or relative value */
unsigned char opcode[3]; /* opcode */
unsigned char opcode_len;
unsigned char addrsize; /* 0 or =mode_bits => no override */
unsigned char opersize; /* 0 indicates no override */
unsigned char lockrep_pre; /* 0 indicates no prefix */
/* HACK, but a space-saving one: shift opcodes have an immediate
* form and a ,1 form (with no immediate). In the parser, we
* set this and opcode_len=1, but store the ,1 version in the
* second byte of the opcode array. We then choose between the
* two versions once we know the actual value of imm (because we
* don't know it in the parser module).
*
* A override to force the imm version should just leave this at
* 0. Then later code won't know the ,1 version even exists.
* TODO: Figure out how this affects CPU flags processing.
*
* Call x86_SetInsnShiftFlag() to set this flag to 1.
*/
unsigned char shift_op;
/* HACK, similar to that for shift_op above, for optimizing instructions
* that take a sign-extended imm8 as well as imm values (eg, the arith
* instructions and a subset of the imul instructions).
*/
unsigned char signext_imm8_op;
unsigned char mode_bits;
} x86_insn;
typedef struct x86_jmprel {
expr *target; /* target location */
struct {
unsigned char opcode[3];
unsigned char opcode_len; /* 0 = no opc for this version */
} shortop, nearop;
/* which opcode are we using? */
/* The *FORCED forms are specified in the source as such */
x86_jmprel_opcode_sel op_sel;
unsigned char addrsize; /* 0 or =mode_bits => no override */
unsigned char opersize; /* 0 indicates no override */
unsigned char lockrep_pre; /* 0 indicates no prefix */
unsigned char mode_bits;
} x86_jmprel;
void x86_bc_delete(bytecode *bc);
void x86_bc_print(FILE *f, const bytecode *bc);
bc_resolve_flags x86_bc_resolve(bytecode *bc, int save, const section *sect,
resolve_label_func resolve_label);
int x86_bc_tobytes(bytecode *bc, unsigned char **bufp, const section *sect,
void *d, output_expr_func output_expr);
int x86_expr_checkea(expr **ep, unsigned char *addrsize, unsigned char bits,
unsigned char nosplit, unsigned char *displen,
unsigned char *modrm, unsigned char *v_modrm,
unsigned char *n_modrm, unsigned char *sib,
unsigned char *v_sib, unsigned char *n_sib);
void x86_switch_cpu(const char *cpuid);
arch_check_id_retval x86_check_identifier(unsigned long data[2],
const char *id);
int x86_directive(const char *name, valparamhead *valparams,
/*@null@*/ valparamhead *objext_valparams,
sectionhead *headp);
/*@null@*/ bytecode *x86_new_insn(const unsigned long data[2],
int num_operands,
/*@null@*/ insn_operandhead *operands);
void x86_handle_prefix(bytecode *bc, const unsigned long data[4]);
void x86_handle_seg_prefix(bytecode *bc, unsigned long segreg);
void x86_handle_seg_override(effaddr *ea, unsigned long segreg);
unsigned int x86_get_reg_size(unsigned long reg);
void x86_reg_print(FILE *f, unsigned long reg);
void x86_segreg_print(FILE *f, unsigned long segreg);
void x86_ea_data_print(FILE *f, const effaddr *ea);
#endif