概述
AS汇编器源码剖析-Armoprand操作数
aarch64_operands全集定义
操作数oprand在指令手册中都有说明,在代码里全部定义在aarch64_operands[]。
const struct aarch64_operandaarch64_operands[] =
{
{AARCH64_OPND_CLASS_NIL, "", 0,{0}, "<none>"},
{AARCH64_OPND_CLASS_INT_REG,"Rd", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rd}, "aninteger register"},
{AARCH64_OPND_CLASS_INT_REG,"Rn", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "aninteger register"},
{AARCH64_OPND_CLASS_INT_REG,"Rm", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rm}, "aninteger register"},
{AARCH64_OPND_CLASS_INT_REG,"Rt", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rt}, "aninteger register"},
{AARCH64_OPND_CLASS_INT_REG,"Rt2", OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rt2}, "aninteger register"
…},
struct aarch64_operand定义如下:
struct aarch64_operand
{
enum aarch64_operand_class op_class; //操作数的类class
const char *name; //手册里通用的名称
unsigned int flags;
/*The associated instruction bit-fields; no operand has more than 4
bit-fields */
enum aarch64_field_kind fields[4];
/*Brief description */
const char *desc;
};
AARCH64_OPND_CLASS_INT_REG | 操作数的类class |
"Rd" | 手册里通用的名称 |
OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR | 操作数flags |
{FLD_Rd} | 域定义的枚举 |
"an integer register" | 说明 |
汇编器将arm操作数的情况做了归纳总结,这个和aarch64_operands[]的顺序是一一对应的,也作为aarch64_operands[]的索引使用。
/* Operand code that helps both parsing andcoding.
Keep AARCH64_OPERANDS synced. */
enum aarch64_opnd
{
AARCH64_OPND_NIL, /* nooperand---MUST BE FIRST!*/
AARCH64_OPND_Rd, /* Integerregister as destination. */
AARCH64_OPND_Rn, /* Integerregister as source. */
AARCH64_OPND_Rm, /* Integer register as source. */
AARCH64_OPND_Rt, /* Integerregister used in ld/st instructions. */
AARCH64_OPND_Rt2, /* Integerregister used in ld/st pair instructions. */
AARCH64_OPND_Rs, /* Integerregister used in ld/st exclusive. */
AARCH64_OPND_Ra, /* Integerregister used in ddp_3src instructions. */
AARCH64_OPND_Rt_SYS, /* Integerregister used in system instructions. */
AARCH64_OPND_Rd_SP, /* Integer Rdor SP. */
…
};
Rd, Rn, Rm是最为常见的oprand,在代码里的处理会在encoding流程里详细讲解。
操作数class定义
操作数class定义都在enum aarch64_operand_class,不是很多。
这个是方便归纳处理的,比如AARCH64_OPND_CLASS_INT_REG,实际上Rd,Rn,Rm等操作数,在填充到指令encoding的方式是类似的。
enum aarch64_operand_class
{
AARCH64_OPND_CLASS_NIL,
AARCH64_OPND_CLASS_INT_REG,
AARCH64_OPND_CLASS_MODIFIED_REG,
AARCH64_OPND_CLASS_FP_REG,
AARCH64_OPND_CLASS_SIMD_REG,
AARCH64_OPND_CLASS_SIMD_ELEMENT,
AARCH64_OPND_CLASS_SISD_REG,
AARCH64_OPND_CLASS_SIMD_REGLIST,
AARCH64_OPND_CLASS_CP_REG,
AARCH64_OPND_CLASS_ADDRESS,
AARCH64_OPND_CLASS_IMMEDIATE,
AARCH64_OPND_CLASS_SYSTEM,
AARCH64_OPND_CLASS_COND,
};
操作数flags定义
一共5种定义如下:
/* Operand flags. */
#define OPD_F_HAS_INSERTER 0x00000001
#define OPD_F_HAS_EXTRACTOR 0x00000002
#define OPD_F_SEXT 0x00000004 /*Require sign-extension. */
#define OPD_F_SHIFT_BY_2 0x00000008 /*Need to left shift the field
value by 2 to get the value
of an immediate operand. */
#define OPD_F_MAYBE_SP 0x00000010 /* May potentially be SP. */
OPD_F_HAS_INSERTER:需要在encoding的时候插入oprand的bit。在aarch64_operands里定义的绝大多数oprand都配置了这个flag,说明是需要在指令encoding里占用bit的。
OPD_F_HAS_EXTRACTOR:在aarch64_operands里和OPD_F_HAS_INSERTER成对出现的。在decode里才会用到,也就是说,AS汇编器不会使用这个。
OPD_F_SEXT:指令需要有符号位扩展,可以以ADDR_ADRP为例子看看。
{AARCH64_OPND_CLASS_ADDRESS, "ADDR_ADRP", OPD_F_SEXT |OPD_F_HAS_EXTRACTOR, {FLD_immhi, FLD_immlo}, "21-bit PC-relative addressof a 4KB page"},
OPD_F_MAYBE_SP:可能是stackpointer的寄存器,例子如下:
{AARCH64_OPND_CLASS_INT_REG, "Rd_SP", OPD_F_MAYBE_SP |OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rd}, "an integer or stackpointer register"},
{AARCH64_OPND_CLASS_INT_REG, "Rn_SP", OPD_F_MAYBE_SP |OPD_F_HAS_INSERTER | OPD_F_HAS_EXTRACTOR, {FLD_Rn}, "an integer or stackpointer register"},
操作码位域定义
操作数oprand在指令手册中都有定义好的bit,统一在aarch64_field fields[]数组里定义。
域的枚举,用来做field定义的索引。
enum aarch64_field_kind
{
FLD_NIL,
FLD_cond2,
FLD_nzcv,
FLD_defgh,
FLD_abc,
FLD_imm19,
FLD_immhi,
FLD_immlo,
FLD_size,
FLD_vldst_size,
FLD_op,
FLD_Q,
FLD_Rt,
FLD_Rd,
FLD_Rn,
FLD_Rt2,
FLD_Ra,
FLD_op2,
FLD_CRm,
FLD_CRn,
FLD_op1,
FLD_op0,
FLD_imm3,
FLD_cond,
FLD_opcode,
FLD_cmode,
FLD_asisdlso_opcode,
FLD_len,
FLD_Rm,
FLD_Rs,
FLD_option,
FLD_S,
FLD_hw,
FLD_opc,
FLD_opc1,
FLD_shift,
FLD_type,
FLD_ldst_size,
FLD_imm6,
FLD_imm4,
FLD_imm5,
FLD_imm7,
FLD_imm8,
FLD_imm9,
FLD_imm12,
FLD_imm14,
FLD_imm16,
FLD_imm26,
FLD_imms,
FLD_immr,
FLD_immb,
FLD_immh,
FLD_N,
FLD_index,
FLD_index2,
FLD_sf,
FLD_lse_sz,
FLD_H,
FLD_L,
FLD_M,
FLD_b5,
FLD_b40,
FLD_scale,
};
const aarch64_field fields[] =
{
{ 0, 0 }, /*NIL. */
{ 0, 4 }, /*cond2: condition in truly conditional-executed inst. */
{ 0, 4 }, /*nzcv: flag bit specifier, encoded in the "nzcv" field. */
{ 5, 5 }, /*defgh: d:e:f:g:h bits in AdvSIMD modified immediate. */
{16, 3 }, /*abc: a:b:c bits in AdvSIMD modified immediate. */
{ 5, 19 }, /* imm19: e.g. in CBZ. */
{ 5, 19 }, /* immhi: e.g. in ADRP. */
{29, 2 }, /*immlo: e.g. in ADRP. */
{22, 2 }, /*size: in most AdvSIMD and floating-point instructions. */
{ 10, 2}, /* vldst_size: size field in theAdvSIMD load/store inst. */
{29, 1 }, /*op: in AdvSIMD modified immediate instructions. */
{30, 1 }, /*Q: in most AdvSIMD instructions. */
{ 0, 5 }, /*Rt: in load/store instructions. */
{ 0, 5 }, /*Rd: in many integer instructions. */
{ 5, 5 }, /*Rn: in many integer instructions. */
{10, 5 }, /*Rt2: in load/store pair instructions. */
{10, 5 }, /*Ra: in fp instructions. */
{ 5, 3 }, /*op2: in the system instructions. */
{ 8, 4 }, /*CRm: in the system instructions. */
{12, 4 }, /*CRn: in the system instructions. */
{16, 3 }, /*op1: in the system instructions. */
{19, 2 }, /*op0: in the system instructions. */
{10, 3 }, /*imm3: in add/sub extended reg instructions. */
{12, 4 }, /*cond: condition flags as a source operand. */
{12, 4 }, /*opcode: in advsimd load/store instructions. */
{12, 4 }, /*cmode: in advsimd modified immediate instructions. */
{13, 3 }, /*asisdlso_opcode: opcode in advsimd ld/st single element. */
{13, 2 }, /*len: in advsimd tbl/tbx instructions. */
{16, 5 }, /*Rm: in ld/st reg offset and some integer inst. */
{16, 5 }, /*Rs: in load/store exclusive instructions. */
{13, 3 }, /*option: in ld/st reg offset + add/sub extended reg inst. */
{12, 1 }, /*S: in load/store reg offset instructions. */
{21, 2 }, /*hw: in move wide constant instructions. */
{22, 2 }, /*opc: in load/store reg offset instructions. */
{23, 1 }, /*opc1: in load/store reg offset instructions. */
{22, 2 }, /*shift: in add/sub reg/imm shifted instructions. */
{22, 2 }, /*type: floating point type field in fp data inst. */
{30, 2 }, /*ldst_size: size field in ld/st reg offset inst. */
{10, 6 }, /*imm6: in add/sub reg shifted instructions. */
{11, 4 }, /*imm4: in advsimd ext and advsimd ins instructions. */
{16, 5 }, /*imm5: in conditional compare (immediate) instructions. */
{15, 7 }, /*imm7: in load/store pair pre/post index instructions. */
{13, 8 }, /*imm8: in floating-point scalar move immediate inst. */
{12, 9 }, /*imm9: in load/store pre/post index instructions. */
{10, 12 }, /* imm12: in ld/stunsigned imm or add/sub shifted inst. */
{ 5, 14 }, /* imm14: in test bit and branch instructions. */
{ 5, 16 }, /* imm16: in exception instructions. */
{ 0, 26 }, /* imm26: in unconditional branch instructions. */
{10, 6 }, /*imms: in bitfield and logical immediate instructions. */
{16, 6 }, /*immr: in bitfield and logical immediate instructions. */
{16, 3 }, /*immb: in advsimd shift by immediate instructions. */
{19, 4 }, /*immh: in advsimd shift by immediate instructions. */
{22, 1 }, /*N: in logical (immediate) instructions. */
{11, 1 }, /*index: in ld/st inst deciding the pre/post-index. */
{24, 1 }, /*index2: in ld/st pair inst deciding the pre/post-index. */
{31, 1 }, /*sf: in integer data processing instructions. */
{30, 1 }, /*lse_size: in LSE extension atomic instructions. */
{11, 1 }, /*H: in advsimd scalar x indexed element instructions. */
{21, 1 }, /*L: in advsimd scalar x indexed element instructions. */
{20, 1 }, /*M: in advsimd scalar x indexed element instructions. */
{31, 1 }, /*b5: in the test bit and branch instructions. */
{19, 5 }, /*b40: in the test bit and branch instructions. */
{10, 6 }, /*scale: in the fixed-point scalar to fp converting inst. */
};
最后
以上就是粗暴河马为你收集整理的AS汇编器源码剖析-第2章-Armoprand操作数AS汇编器源码剖析-Armoprand操作数的全部内容,希望文章能够帮你解决AS汇编器源码剖析-第2章-Armoprand操作数AS汇编器源码剖析-Armoprand操作数所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复