Home | History | Annotate | Line # | Download | only in config
      1  1.1  christos /* tc-i386-ginsn.c -- Ginsn generation for the x86-64 ISA
      2  1.1  christos 
      3  1.1  christos    Copyright (C) 2024-2025 Free Software Foundation, Inc.
      4  1.1  christos 
      5  1.1  christos    This file is part of GAS.
      6  1.1  christos 
      7  1.1  christos    GAS is free software; you can redistribute it and/or modify
      8  1.1  christos    it under the terms of the GNU General Public License as published by
      9  1.1  christos    the Free Software Foundation; either version 3 of the license, or
     10  1.1  christos    (at your option) any later version.
     11  1.1  christos 
     12  1.1  christos    GAS is distributed in the hope that it will be useful,
     13  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15  1.1  christos    GNU General Public License for more details.
     16  1.1  christos 
     17  1.1  christos    You should have received a copy of the GNU General Public License
     18  1.1  christos    along with this program; see the file COPYING3. If not,
     19  1.1  christos    see <http://www.gnu.org/licenses/>.  */
     20  1.1  christos 
     21  1.1  christos /* This file contains the implementation of the ginsn creation for x86-64
     22  1.1  christos    instructions.  */
     23  1.1  christos 
     24  1.1  christos /* DWARF register number for EFLAGS.  Used for pushf/popf insns.  */
     25  1.1  christos #define GINSN_DW2_REGNUM_EFLAGS     49
     26  1.1  christos /* DWARF register number for RSI.  Used as dummy value when RegIP/RegIZ.  */
     27  1.1  christos #define GINSN_DW2_REGNUM_RSI_DUMMY  4
     28  1.1  christos 
     29  1.1  christos /* Identify the callee-saved registers in System V AMD64 ABI.  */
     30  1.1  christos 
     31  1.1  christos bool
     32  1.1  christos x86_scfi_callee_saved_p (unsigned int dw2reg_num)
     33  1.1  christos {
     34  1.1  christos   if (dw2reg_num == 3 /* rbx.  */
     35  1.1  christos       || dw2reg_num == REG_FP /* rbp.  */
     36  1.1  christos       || dw2reg_num == REG_SP /* rsp.  */
     37  1.1  christos       || (dw2reg_num >= 12 && dw2reg_num <= 15) /* r12 - r15.  */)
     38  1.1  christos     return true;
     39  1.1  christos 
     40  1.1  christos   return false;
     41  1.1  christos }
     42  1.1  christos 
     43  1.1  christos /* Check whether an instruction prefix which affects operation size
     44  1.1  christos    accompanies.  For insns in the legacy space, setting REX.W takes precedence
     45  1.1  christos    over the operand-size prefix (66H) when both are used.
     46  1.1  christos 
     47  1.1  christos    The current users of this API are in the handlers for PUSH, POP or other
     48  1.1  christos    instructions which affect the stack pointer implicitly:  the operation size
     49  1.1  christos    (16, 32, or 64 bits) determines the amount by which the stack pointer is
     50  1.1  christos    incremented / decremented (2, 4 or 8).  */
     51  1.1  christos 
     52  1.1  christos static bool
     53  1.1  christos ginsn_opsize_prefix_p (void)
     54  1.1  christos {
     55  1.1  christos   return (!(i.prefix[REX_PREFIX] & REX_W) && i.prefix[DATA_PREFIX]);
     56  1.1  christos }
     57  1.1  christos 
     58  1.1  christos /* Get the DWARF register number for the given register entry.
     59  1.1  christos    For specific byte/word/dword register accesses like al, cl, ah, ch, r8d,
     60  1.1  christos    r20w etc., we need to identify the DWARF register number for the
     61  1.1  christos    corresponding 8-byte GPR.
     62  1.1  christos 
     63  1.1  christos    This function is a hack - it relies on relative ordering of reg entries in
     64  1.1  christos    the i386_regtab.  FIXME - it will be good to allow a more direct way to get
     65  1.1  christos    this information.  */
     66  1.1  christos 
     67  1.1  christos static unsigned int
     68  1.1  christos ginsn_dw2_regnum (const reg_entry *ireg)
     69  1.1  christos {
     70  1.1  christos   const reg_entry *temp = ireg;
     71  1.1  christos   unsigned int dwarf_reg = Dw2Inval, idx = 0;
     72  1.1  christos 
     73  1.1  christos   /* ginsn creation is available for AMD64 abi only ATM.  Other flag_code
     74  1.1  christos      are not expected.  */
     75  1.1  christos   gas_assert (ireg && flag_code == CODE_64BIT);
     76  1.1  christos 
     77  1.1  christos   /* Watch out for RegIP, RegIZ.  These are expected to appear only with
     78  1.1  christos      base/index addressing modes.  Although creating inaccurate data
     79  1.1  christos      dependencies, using a dummy value (lets say volatile register rsi) will
     80  1.1  christos      not hurt SCFI.  TBD_GINSN_GEN_NOT_SCFI.  */
     81  1.1  christos   if (ireg->reg_num == RegIP || ireg->reg_num == RegIZ)
     82  1.1  christos     return GINSN_DW2_REGNUM_RSI_DUMMY;
     83  1.1  christos 
     84  1.1  christos   dwarf_reg = ireg->dw2_regnum[object_64bit];
     85  1.1  christos 
     86  1.1  christos   if (dwarf_reg == Dw2Inval)
     87  1.1  christos     {
     88  1.1  christos       if (ireg <= &i386_regtab[3])
     89  1.1  christos 	/* For al, cl, dl, bl, bump over to axl, cxl, dxl, bxl respectively by
     90  1.1  christos 	   adding 8.  */
     91  1.1  christos 	temp = ireg + 8;
     92  1.1  christos       else if (ireg <= &i386_regtab[7])
     93  1.1  christos 	/* For ah, ch, dh, bh, bump over to axl, cxl, dxl, bxl respectively by
     94  1.1  christos 	   adding 4.  */
     95  1.1  christos 	temp = ireg + 4;
     96  1.1  christos       else
     97  1.1  christos 	{
     98  1.1  christos 	  /* The code relies on the relative ordering of the reg entries in
     99  1.1  christos 	     i386_regtab.  There are 32 register entries between axl-r31b,
    100  1.1  christos 	     ax-r31w etc.  The assertions here ensures the code does not
    101  1.1  christos 	     recurse indefinitely.  */
    102  1.1  christos 	  gas_assert ((temp - &i386_regtab[0]) >= 0);
    103  1.1  christos 	  idx = temp - &i386_regtab[0];
    104  1.1  christos 	  gas_assert (idx + 32 < i386_regtab_size - 1);
    105  1.1  christos 
    106  1.1  christos 	  temp = temp + 32;
    107  1.1  christos 	}
    108  1.1  christos 
    109  1.1  christos       dwarf_reg = ginsn_dw2_regnum (temp);
    110  1.1  christos     }
    111  1.1  christos 
    112  1.1  christos   /* Sanity check - failure may indicate state corruption, bad ginsn or
    113  1.1  christos      perhaps the i386-reg table and the current function got out of sync.  */
    114  1.1  christos   gas_assert (dwarf_reg < Dw2Inval);
    115  1.1  christos 
    116  1.1  christos   return dwarf_reg;
    117  1.1  christos }
    118  1.1  christos 
    119  1.1  christos static ginsnS *
    120  1.1  christos x86_ginsn_addsub_reg_mem (const symbolS *insn_end_sym)
    121  1.1  christos {
    122  1.1  christos   unsigned int dw2_regnum;
    123  1.1  christos   unsigned int src1_dw2_regnum;
    124  1.1  christos   ginsnS *ginsn = NULL;
    125  1.1  christos   ginsnS * (*ginsn_func) (const symbolS *, bool,
    126  1.1  christos 			  enum ginsn_src_type, unsigned int, offsetT,
    127  1.1  christos 			  enum ginsn_src_type, unsigned int, offsetT,
    128  1.1  christos 			  enum ginsn_dst_type, unsigned int, offsetT);
    129  1.1  christos   uint16_t opcode = i.tm.base_opcode;
    130  1.1  christos 
    131  1.1  christos   gas_assert (i.tm.opcode_space == SPACE_BASE
    132  1.1  christos 	      && (opcode == 0x1 || opcode == 0x29));
    133  1.1  christos   ginsn_func = (opcode == 0x1) ? ginsn_new_add : ginsn_new_sub;
    134  1.1  christos 
    135  1.1  christos   /* op %reg, symbol or even other cases where destination involves indirect
    136  1.1  christos      access are unnecessary for SCFI correctness.  TBD_GINSN_GEN_NOT_SCFI.  */
    137  1.1  christos   if (i.mem_operands)
    138  1.1  christos     return ginsn;
    139  1.1  christos 
    140  1.1  christos   /* Skip detection of 8/16/32-bit op size; 'add/sub reg, reg/mem' ops always
    141  1.1  christos      make the dest reg untraceable for SCFI.  */
    142  1.1  christos 
    143  1.1  christos   /* op reg, reg/mem.  */
    144  1.1  christos   src1_dw2_regnum = ginsn_dw2_regnum (i.op[0].regs);
    145  1.1  christos   /* Of interest only when second opnd is not memory.  */
    146  1.1  christos   if (i.reg_operands == 2)
    147  1.1  christos     {
    148  1.1  christos       dw2_regnum = ginsn_dw2_regnum (i.op[1].regs);
    149  1.1  christos       ginsn = ginsn_func (insn_end_sym, true,
    150  1.1  christos 			  GINSN_SRC_REG, src1_dw2_regnum, 0,
    151  1.1  christos 			  GINSN_SRC_REG, dw2_regnum, 0,
    152  1.1  christos 			  GINSN_DST_REG, dw2_regnum, 0);
    153  1.1  christos       ginsn_set_where (ginsn);
    154  1.1  christos     }
    155  1.1  christos 
    156  1.1  christos   return ginsn;
    157  1.1  christos }
    158  1.1  christos 
    159  1.1  christos static ginsnS *
    160  1.1  christos x86_ginsn_addsub_mem_reg (const symbolS *insn_end_sym)
    161  1.1  christos {
    162  1.1  christos   unsigned int dw2_regnum;
    163  1.1  christos   unsigned int src1_dw2_regnum;
    164  1.1  christos   const reg_entry *mem_reg;
    165  1.1  christos   int32_t gdisp = 0;
    166  1.1  christos   ginsnS *ginsn = NULL;
    167  1.1  christos   ginsnS * (*ginsn_func) (const symbolS *, bool,
    168  1.1  christos 			  enum ginsn_src_type, unsigned int, offsetT,
    169  1.1  christos 			  enum ginsn_src_type, unsigned int, offsetT,
    170  1.1  christos 			  enum ginsn_dst_type, unsigned int, offsetT);
    171  1.1  christos   uint16_t opcode = i.tm.base_opcode;
    172  1.1  christos 
    173  1.1  christos   gas_assert (i.tm.opcode_space == SPACE_BASE
    174  1.1  christos 	      && (opcode == 0x3 || opcode == 0x2b));
    175  1.1  christos   ginsn_func = (opcode == 0x3) ? ginsn_new_add : ginsn_new_sub;
    176  1.1  christos 
    177  1.1  christos   /* op symbol, %reg.  */
    178  1.1  christos   if (i.mem_operands && !i.base_reg && !i.index_reg)
    179  1.1  christos     return ginsn;
    180  1.1  christos 
    181  1.1  christos   /* Skip detection of 8/16/32-bit op size; 'add/sub reg/mem, reg' ops always
    182  1.1  christos      make the dest reg untraceable for SCFI.  */
    183  1.1  christos 
    184  1.1  christos   /* op reg/mem, %reg.  */
    185  1.1  christos   dw2_regnum = ginsn_dw2_regnum (i.op[1].regs);
    186  1.1  christos 
    187  1.1  christos   if (i.reg_operands == 2)
    188  1.1  christos     {
    189  1.1  christos       src1_dw2_regnum = ginsn_dw2_regnum (i.op[0].regs);
    190  1.1  christos       ginsn = ginsn_func (insn_end_sym, true,
    191  1.1  christos 			  GINSN_SRC_REG, src1_dw2_regnum, 0,
    192  1.1  christos 			  GINSN_SRC_REG, dw2_regnum, 0,
    193  1.1  christos 			  GINSN_DST_REG, dw2_regnum, 0);
    194  1.1  christos       ginsn_set_where (ginsn);
    195  1.1  christos     }
    196  1.1  christos   else if (i.mem_operands)
    197  1.1  christos     {
    198  1.1  christos       mem_reg = (i.base_reg) ? i.base_reg : i.index_reg;
    199  1.1  christos       src1_dw2_regnum = ginsn_dw2_regnum (mem_reg);
    200  1.1  christos       if (i.disp_operands == 1)
    201  1.1  christos 	gdisp = i.op[0].disps->X_add_number;
    202  1.1  christos       ginsn = ginsn_func (insn_end_sym, true,
    203  1.1  christos 			  GINSN_SRC_INDIRECT, src1_dw2_regnum, gdisp,
    204  1.1  christos 			  GINSN_SRC_REG, dw2_regnum, 0,
    205  1.1  christos 			  GINSN_DST_REG, dw2_regnum, 0);
    206  1.1  christos       ginsn_set_where (ginsn);
    207  1.1  christos     }
    208  1.1  christos 
    209  1.1  christos   return ginsn;
    210  1.1  christos }
    211  1.1  christos 
    212  1.1  christos static ginsnS *
    213  1.1  christos x86_ginsn_alu_imm (const symbolS *insn_end_sym)
    214  1.1  christos {
    215  1.1  christos   offsetT src_imm;
    216  1.1  christos   unsigned int dw2_regnum;
    217  1.1  christos   ginsnS *ginsn = NULL;
    218  1.1  christos   enum ginsn_src_type src_type = GINSN_SRC_REG;
    219  1.1  christos   enum ginsn_dst_type dst_type = GINSN_DST_REG;
    220  1.1  christos 
    221  1.1  christos   ginsnS * (*ginsn_func) (const symbolS *, bool,
    222  1.1  christos 			  enum ginsn_src_type, unsigned int, offsetT,
    223  1.1  christos 			  enum ginsn_src_type, unsigned int, offsetT,
    224  1.1  christos 			  enum ginsn_dst_type, unsigned int, offsetT);
    225  1.1  christos 
    226  1.1  christos   /* FIXME - create ginsn where dest is REG_SP / REG_FP only ? */
    227  1.1  christos   /* Map for insn.tm.extension_opcode
    228  1.1  christos      000 ADD    100 AND
    229  1.1  christos      001 OR     101 SUB
    230  1.1  christos      010 ADC    110 XOR
    231  1.1  christos      011 SBB    111 CMP  */
    232  1.1  christos 
    233  1.1  christos   /* add/sub/and imm, %reg only at this time for SCFI.
    234  1.1  christos      Although all three ('and', 'or' , 'xor') make the destination reg
    235  1.1  christos      untraceable, 'and' op is handled but not 'or' / 'xor' because we will look
    236  1.1  christos      into supporting the DRAP pattern at some point.  Other opcodes ('adc',
    237  1.1  christos      'sbb' and 'cmp') are not generated here either.  The ginsn representation
    238  1.1  christos      does not have support for the latter three opcodes;  GINSN_TYPE_OTHER may
    239  1.1  christos      be added for these after x86_ginsn_unhandled () invocation if the
    240  1.1  christos      destination register is REG_SP or REG_FP.  */
    241  1.1  christos   if (i.tm.extension_opcode == 5)
    242  1.1  christos     ginsn_func = ginsn_new_sub;
    243  1.1  christos   else if (i.tm.extension_opcode == 4)
    244  1.1  christos     ginsn_func = ginsn_new_and;
    245  1.1  christos   else if (i.tm.extension_opcode == 0)
    246  1.1  christos     ginsn_func = ginsn_new_add;
    247  1.1  christos   else
    248  1.1  christos     return ginsn;
    249  1.1  christos 
    250  1.1  christos   /* TBD_GINSN_REPRESENTATION_LIMIT: There is no representation for when a
    251  1.1  christos      symbol is used as an operand, like so:
    252  1.1  christos 	  addq    $simd_cmp_op+8, %rdx
    253  1.1  christos      Skip generating any ginsn for this.  */
    254  1.1  christos   if (i.imm_operands == 1
    255  1.1  christos       && i.op[0].imms->X_op != O_constant)
    256  1.1  christos     return ginsn;
    257  1.1  christos 
    258  1.1  christos   /* addq    $1, symbol
    259  1.1  christos      addq    $1, -16(%rbp)
    260  1.1  christos      These are not of interest for SCFI.  Also, TBD_GINSN_GEN_NOT_SCFI.  */
    261  1.1  christos   if (i.mem_operands == 1)
    262  1.1  christos     return ginsn;
    263  1.1  christos 
    264  1.1  christos   /* 8/16/32-bit op size makes the destination reg untraceable for SCFI.
    265  1.1  christos      Deal with this via the x86_ginsn_unhandled () code path.  */
    266  1.1  christos   if (i.suffix != QWORD_MNEM_SUFFIX)
    267  1.1  christos     return ginsn;
    268  1.1  christos 
    269  1.1  christos   gas_assert (i.imm_operands == 1);
    270  1.1  christos   src_imm = i.op[0].imms->X_add_number;
    271  1.1  christos   /* The second operand may be a register or indirect access.  For SCFI, only
    272  1.1  christos      the case when the second opnd is a register is interesting.  Revisit this
    273  1.1  christos      if generating ginsns for a different gen mode TBD_GINSN_GEN_NOT_SCFI.  */
    274  1.1  christos   if (i.reg_operands == 1)
    275  1.1  christos     {
    276  1.1  christos       dw2_regnum = ginsn_dw2_regnum (i.op[1].regs);
    277  1.1  christos       /* For ginsn, keep the imm as second src operand.  */
    278  1.1  christos       ginsn = ginsn_func (insn_end_sym, true,
    279  1.1  christos 			  src_type, dw2_regnum, 0,
    280  1.1  christos 			  GINSN_SRC_IMM, 0, src_imm,
    281  1.1  christos 			  dst_type, dw2_regnum, 0);
    282  1.1  christos 
    283  1.1  christos       ginsn_set_where (ginsn);
    284  1.1  christos     }
    285  1.1  christos 
    286  1.1  christos   return ginsn;
    287  1.1  christos }
    288  1.1  christos 
    289  1.1  christos /* Create ginsn(s) for MOV operations.
    290  1.1  christos 
    291  1.1  christos    The generated ginsns corresponding to mov with indirect access to memory
    292  1.1  christos    (src or dest) suffer with loss of information: when both index and base
    293  1.1  christos    registers are at play, only base register gets conveyed in ginsn.  Note
    294  1.1  christos    this TBD_GINSN_GEN_NOT_SCFI.  */
    295  1.1  christos 
    296  1.1  christos static ginsnS *
    297  1.1  christos x86_ginsn_move (const symbolS *insn_end_sym)
    298  1.1  christos {
    299  1.1  christos   ginsnS *ginsn = NULL;
    300  1.1  christos   unsigned int dst_reg;
    301  1.1  christos   unsigned int src_reg;
    302  1.1  christos   offsetT src_disp = 0;
    303  1.1  christos   offsetT dst_disp = 0;
    304  1.1  christos   const reg_entry *dst = NULL;
    305  1.1  christos   const reg_entry *src = NULL;
    306  1.1  christos   uint16_t opcode = i.tm.base_opcode;
    307  1.1  christos   enum ginsn_src_type src_type = GINSN_SRC_REG;
    308  1.1  christos   enum ginsn_dst_type dst_type = GINSN_DST_REG;
    309  1.1  christos 
    310  1.1  christos   /* mov %reg, symbol or mov symbol, %reg.
    311  1.1  christos      Not of interest for SCFI.  Also, TBD_GINSN_GEN_NOT_SCFI.  */
    312  1.1  christos   if (i.mem_operands == 1 && !i.base_reg && !i.index_reg)
    313  1.1  christos     return ginsn;
    314  1.1  christos 
    315  1.1  christos   /* 8/16/32-bit op size makes the destination reg untraceable for SCFI.
    316  1.1  christos      Handle mov reg, reg only.  mov to or from a memory operand will make
    317  1.1  christos      dest reg, when present, untraceable, irrespective of the op size.  */
    318  1.1  christos   if (i.reg_operands == 2 && i.suffix != QWORD_MNEM_SUFFIX)
    319  1.1  christos     return ginsn;
    320  1.1  christos 
    321  1.1  christos   gas_assert (i.tm.opcode_space == SPACE_BASE);
    322  1.1  christos   if (opcode == 0x8b || opcode == 0x8a)
    323  1.1  christos     {
    324  1.1  christos       /* mov  disp(%reg), %reg.  */
    325  1.1  christos       if (i.mem_operands)
    326  1.1  christos 	{
    327  1.1  christos 	  src = (i.base_reg) ? i.base_reg : i.index_reg;
    328  1.1  christos 	  if (i.disp_operands == 1)
    329  1.1  christos 	    src_disp = i.op[0].disps->X_add_number;
    330  1.1  christos 	  src_type = GINSN_SRC_INDIRECT;
    331  1.1  christos 	}
    332  1.1  christos       else
    333  1.1  christos 	src = i.op[0].regs;
    334  1.1  christos 
    335  1.1  christos       dst = i.op[1].regs;
    336  1.1  christos     }
    337  1.1  christos   else if (opcode == 0x89 || opcode == 0x88)
    338  1.1  christos     {
    339  1.1  christos       /* mov %reg, disp(%reg).  */
    340  1.1  christos       src = i.op[0].regs;
    341  1.1  christos       if (i.mem_operands)
    342  1.1  christos 	{
    343  1.1  christos 	  dst = (i.base_reg) ? i.base_reg : i.index_reg;
    344  1.1  christos 	  if (i.disp_operands == 1)
    345  1.1  christos 	    dst_disp = i.op[1].disps->X_add_number;
    346  1.1  christos 	  dst_type = GINSN_DST_INDIRECT;
    347  1.1  christos 	}
    348  1.1  christos       else
    349  1.1  christos 	dst = i.op[1].regs;
    350  1.1  christos     }
    351  1.1  christos 
    352  1.1  christos   src_reg = ginsn_dw2_regnum (src);
    353  1.1  christos   dst_reg = ginsn_dw2_regnum (dst);
    354  1.1  christos 
    355  1.1  christos   ginsn = ginsn_new_mov (insn_end_sym, true,
    356  1.1  christos 			 src_type, src_reg, src_disp,
    357  1.1  christos 			 dst_type, dst_reg, dst_disp);
    358  1.1  christos   ginsn_set_where (ginsn);
    359  1.1  christos 
    360  1.1  christos   return ginsn;
    361  1.1  christos }
    362  1.1  christos 
    363  1.1  christos /* Generate appropriate ginsn for lea.
    364  1.1  christos 
    365  1.1  christos    Unhandled sub-cases (marked with TBD_GINSN_GEN_NOT_SCFI) also suffer with
    366  1.1  christos    some loss of information in the final ginsn chosen eventually (type
    367  1.1  christos    GINSN_TYPE_OTHER).  But this is fine for now for GINSN_GEN_SCFI generation
    368  1.1  christos    mode.  */
    369  1.1  christos 
    370  1.1  christos static ginsnS *
    371  1.1  christos x86_ginsn_lea (const symbolS *insn_end_sym)
    372  1.1  christos {
    373  1.1  christos   offsetT src_disp = 0;
    374  1.1  christos   ginsnS *ginsn = NULL;
    375  1.1  christos   unsigned int src1_reg;
    376  1.1  christos   const reg_entry *src1;
    377  1.1  christos   offsetT index_scale;
    378  1.1  christos   unsigned int dst_reg;
    379  1.1  christos   bool index_regiz_p;
    380  1.1  christos 
    381  1.1  christos   if ((!i.base_reg) != (!i.index_reg || i.index_reg->reg_num == RegIZ))
    382  1.1  christos     {
    383  1.1  christos       /* lea disp(%base), %dst    or    lea disp(,%index,imm), %dst.
    384  1.1  christos 	 Either index_reg or base_reg exists, but not both.  Further, as per
    385  1.1  christos 	 above, the case when just %index exists but is equal to RegIZ is
    386  1.1  christos 	 excluded.  If not excluded, a GINSN_TYPE_MOV of %rsi
    387  1.1  christos 	 (GINSN_DW2_REGNUM_RSI_DUMMY) to %dst will be generated by this block.
    388  1.1  christos 	 Such a mov ginsn is imprecise; so, exclude now and generate
    389  1.1  christos 	 GINSN_TYPE_OTHER instead later via the x86_ginsn_unhandled ().
    390  1.1  christos 	 Excluding other cases is required due to
    391  1.1  christos 	 TBD_GINSN_REPRESENTATION_LIMIT.  */
    392  1.1  christos 
    393  1.1  christos       index_scale = i.log2_scale_factor;
    394  1.1  christos       index_regiz_p = i.index_reg && i.index_reg->reg_num == RegIZ;
    395  1.1  christos       src1 = i.base_reg ? i.base_reg : i.index_reg;
    396  1.1  christos       src1_reg = ginsn_dw2_regnum (src1);
    397  1.1  christos       dst_reg = ginsn_dw2_regnum (i.op[1].regs);
    398  1.1  christos       /* It makes sense to represent a scale factor of 1 precisely here
    399  1.1  christos 	 (i.e., not using GINSN_TYPE_OTHER, but rather similar to the
    400  1.1  christos 	 base-without-index case).  A non-zero scale factor is still OK if
    401  1.1  christos 	 the index reg is zero reg.
    402  1.1  christos 	 However, skip from here the case when disp has a symbol instead.
    403  1.1  christos 	 TBD_GINSN_REPRESENTATION_LIMIT.  */
    404  1.1  christos       if ((!index_scale || index_regiz_p)
    405  1.1  christos 	  && (!i.disp_operands || i.op[0].disps->X_op == O_constant))
    406  1.1  christos 	{
    407  1.1  christos 	  if (i.disp_operands)
    408  1.1  christos 	    src_disp = i.op[0].disps->X_add_number;
    409  1.1  christos 
    410  1.1  christos 	  if (src_disp)
    411  1.1  christos 	    /* Generate an ADD ginsn.  */
    412  1.1  christos 	    ginsn = ginsn_new_add (insn_end_sym, true,
    413  1.1  christos 				   GINSN_SRC_REG, src1_reg, 0,
    414  1.1  christos 				   GINSN_SRC_IMM, 0, src_disp,
    415  1.1  christos 				   GINSN_DST_REG, dst_reg, 0);
    416  1.1  christos 	  else
    417  1.1  christos 	    /* Generate a MOV ginsn.  */
    418  1.1  christos 	    ginsn = ginsn_new_mov (insn_end_sym, true,
    419  1.1  christos 				   GINSN_SRC_REG, src1_reg, 0,
    420  1.1  christos 				   GINSN_DST_REG, dst_reg, 0);
    421  1.1  christos 
    422  1.1  christos 	  ginsn_set_where (ginsn);
    423  1.1  christos 	}
    424  1.1  christos     }
    425  1.1  christos   /* Skip handling other cases here,
    426  1.1  christos      - when (i.index_reg && i.base_reg) is true,
    427  1.1  christos        e.g., lea disp(%base,%index,imm), %dst
    428  1.1  christos        We do not have a ginsn representation for multiply.
    429  1.1  christos      - or, when (!i.index_reg && !i.base_reg) is true,
    430  1.1  christos        e.g., lea symbol, %dst
    431  1.1  christos        Not a frequent pattern.  If %dst is a register of interest, the user is
    432  1.1  christos        likely to use a MOV op anyway.
    433  1.1  christos      Deal with these via the x86_ginsn_unhandled () code path to generate
    434  1.1  christos      GINSN_TYPE_OTHER when necessary.  TBD_GINSN_GEN_NOT_SCFI.  */
    435  1.1  christos 
    436  1.1  christos   return ginsn;
    437  1.1  christos }
    438  1.1  christos 
    439  1.1  christos static ginsnS *
    440  1.1  christos x86_ginsn_jump (const symbolS *insn_end_sym, bool cond_p)
    441  1.1  christos {
    442  1.1  christos   ginsnS *ginsn = NULL;
    443  1.1  christos   const symbolS *src_symbol;
    444  1.1  christos   ginsnS * (*ginsn_func) (const symbolS *sym, bool real_p,
    445  1.1  christos 			  enum ginsn_src_type src_type, unsigned int src_reg,
    446  1.1  christos 			  const symbolS *src_ginsn_sym);
    447  1.1  christos 
    448  1.1  christos   gas_assert (i.disp_operands == 1);
    449  1.1  christos 
    450  1.1  christos   ginsn_func = cond_p ? ginsn_new_jump_cond : ginsn_new_jump;
    451  1.1  christos   if (i.op[0].disps->X_op == O_symbol && !i.op[0].disps->X_add_number)
    452  1.1  christos     {
    453  1.1  christos       src_symbol = i.op[0].disps->X_add_symbol;
    454  1.1  christos       ginsn = ginsn_func (insn_end_sym, true,
    455  1.1  christos 			  GINSN_SRC_SYMBOL, 0, src_symbol);
    456  1.1  christos 
    457  1.1  christos       ginsn_set_where (ginsn);
    458  1.1  christos     }
    459  1.1  christos   else
    460  1.1  christos     {
    461  1.1  christos       /* A non-zero addend in jump/JCC target makes control-flow tracking
    462  1.1  christos 	 difficult.  Skip SCFI for now.  */
    463  1.1  christos       as_bad (_("SCFI: `%s' insn with non-zero addend to sym not supported"),
    464  1.1  christos 	      cond_p ? "JCC" : "jmp");
    465  1.1  christos       return ginsn;
    466  1.1  christos     }
    467  1.1  christos 
    468  1.1  christos   return ginsn;
    469  1.1  christos }
    470  1.1  christos 
    471  1.1  christos static ginsnS *
    472  1.1  christos x86_ginsn_indirect_branch (const symbolS *insn_end_sym)
    473  1.1  christos {
    474  1.1  christos   ginsnS *ginsn = NULL;
    475  1.1  christos   const reg_entry *mem_reg;
    476  1.1  christos   unsigned int dw2_regnum;
    477  1.1  christos 
    478  1.1  christos   ginsnS * (*ginsn_func) (const symbolS *sym, bool real_p,
    479  1.1  christos 			  enum ginsn_src_type src_type, unsigned int src_reg,
    480  1.1  christos 			  const symbolS *src_ginsn_sym);
    481  1.1  christos 
    482  1.1  christos   /* Other cases are not expected.  */
    483  1.1  christos   gas_assert (i.tm.extension_opcode == 4 || i.tm.extension_opcode == 2);
    484  1.1  christos 
    485  1.1  christos   if (i.tm.extension_opcode == 4)
    486  1.1  christos     /* 0xFF /4 (jmp r/m).  */
    487  1.1  christos     ginsn_func = ginsn_new_jump;
    488  1.1  christos   else if (i.tm.extension_opcode == 2)
    489  1.1  christos     /* 0xFF /2 (call r/m).  */
    490  1.1  christos     ginsn_func = ginsn_new_call;
    491  1.1  christos   else
    492  1.1  christos     return ginsn;
    493  1.1  christos 
    494  1.1  christos   if (i.reg_operands)
    495  1.1  christos     {
    496  1.1  christos       dw2_regnum = ginsn_dw2_regnum (i.op[0].regs);
    497  1.1  christos       ginsn = ginsn_func (insn_end_sym, true,
    498  1.1  christos 			  GINSN_SRC_REG, dw2_regnum, NULL);
    499  1.1  christos       ginsn_set_where (ginsn);
    500  1.1  christos     }
    501  1.1  christos   else if (i.mem_operands)
    502  1.1  christos     {
    503  1.1  christos       /* Handle jump/call near, absolute indirect, address.
    504  1.1  christos 	 E.g., jmp/call *imm(%rN),  jmp/call *sym(,%rN,imm)
    505  1.1  christos 	 or  jmp/call *sym(%rN) etc.  */
    506  1.1  christos       mem_reg = i.base_reg ? i.base_reg : i.index_reg;
    507  1.1  christos       /* Generate a ginsn, even if it is with TBD_GINSN_INFO_LOSS.  Otherwise,
    508  1.1  christos 	 the user gets the impression of missing functionality due to this
    509  1.1  christos 	 being a COFI and alerted for via the x86_ginsn_unhandled () workflow
    510  1.1  christos 	 as unhandled operation (which can be misleading for users).
    511  1.1  christos 
    512  1.1  christos 	 Indirect branches make the code block ineligible for SCFI; Hence, an
    513  1.1  christos 	 approximate ginsn will not affect SCFI correctness:
    514  1.1  christos 	   - Use dummy register if no base or index
    515  1.1  christos 	   - Skip symbol information, if any.
    516  1.1  christos 	 Note this case of TBD_GINSN_GEN_NOT_SCFI.  */
    517  1.1  christos       dw2_regnum = (mem_reg
    518  1.1  christos 		    ? ginsn_dw2_regnum (mem_reg)
    519  1.1  christos 		    : GINSN_DW2_REGNUM_RSI_DUMMY);
    520  1.1  christos       ginsn = ginsn_func (insn_end_sym, true,
    521  1.1  christos 			  GINSN_SRC_REG, dw2_regnum, NULL);
    522  1.1  christos       ginsn_set_where (ginsn);
    523  1.1  christos     }
    524  1.1  christos 
    525  1.1  christos   return ginsn;
    526  1.1  christos }
    527  1.1  christos 
    528  1.1  christos static ginsnS *
    529  1.1  christos x86_ginsn_enter (const symbolS *insn_end_sym)
    530  1.1  christos {
    531  1.1  christos   ginsnS *ginsn = NULL;
    532  1.1  christos   ginsnS *ginsn_next = NULL;
    533  1.1  christos   ginsnS *ginsn_last = NULL;
    534  1.1  christos   /* In 64-bit mode, the default stack update size is 8 bytes.  */
    535  1.1  christos   int stack_opnd_size = 8;
    536  1.1  christos 
    537  1.1  christos   gas_assert (i.imm_operands == 2);
    538  1.1  christos 
    539  1.1  christos   /* For non-zero size operands, bail out as untraceable for SCFI.  */
    540  1.1  christos   if (i.op[0].imms->X_op != O_constant || i.op[0].imms->X_add_symbol != 0
    541  1.1  christos       || i.op[1].imms->X_op != O_constant || i.op[1].imms->X_add_symbol != 0)
    542  1.1  christos     {
    543  1.1  christos       as_bad ("SCFI: enter insn with non-zero operand not supported");
    544  1.1  christos       return ginsn;
    545  1.1  christos     }
    546  1.1  christos 
    547  1.1  christos   /* Check if this is a 16-bit op.  */
    548  1.1  christos   if (ginsn_opsize_prefix_p ())
    549  1.1  christos     stack_opnd_size = 2;
    550  1.1  christos 
    551  1.1  christos   /* If the nesting level is 0, the processor pushes the frame pointer from
    552  1.1  christos      the BP/EBP/RBP register onto the stack, copies the current stack
    553  1.1  christos      pointer from the SP/ESP/RSP register into the BP/EBP/RBP register, and
    554  1.1  christos      loads the SP/ESP/RSP register with the current stack-pointer value
    555  1.1  christos      minus the value in the size operand.  */
    556  1.1  christos   ginsn = ginsn_new_sub (insn_end_sym, false,
    557  1.1  christos 			 GINSN_SRC_REG, REG_SP, 0,
    558  1.1  christos 			 GINSN_SRC_IMM, 0, stack_opnd_size,
    559  1.1  christos 			 GINSN_DST_REG, REG_SP, 0);
    560  1.1  christos   ginsn_set_where (ginsn);
    561  1.1  christos   ginsn_next = ginsn_new_store (insn_end_sym, false,
    562  1.1  christos 				GINSN_SRC_REG, REG_FP,
    563  1.1  christos 				GINSN_DST_INDIRECT, REG_SP, 0);
    564  1.1  christos   ginsn_set_where (ginsn_next);
    565  1.1  christos   gas_assert (!ginsn_link_next (ginsn, ginsn_next));
    566  1.1  christos   ginsn_last = ginsn_new_mov (insn_end_sym, false,
    567  1.1  christos 			      GINSN_SRC_REG, REG_SP, 0,
    568  1.1  christos 			      GINSN_DST_REG, REG_FP, 0);
    569  1.1  christos   ginsn_set_where (ginsn_last);
    570  1.1  christos   gas_assert (!ginsn_link_next (ginsn_next, ginsn_last));
    571  1.1  christos 
    572  1.1  christos   return ginsn;
    573  1.1  christos }
    574  1.1  christos 
    575  1.1  christos static ginsnS *
    576  1.1  christos x86_ginsn_leave (const symbolS *insn_end_sym)
    577  1.1  christos {
    578  1.1  christos   ginsnS *ginsn = NULL;
    579  1.1  christos   ginsnS *ginsn_next = NULL;
    580  1.1  christos   ginsnS *ginsn_last = NULL;
    581  1.1  christos   /* In 64-bit mode, the default stack update size is 8 bytes.  */
    582  1.1  christos   int stack_opnd_size = 8;
    583  1.1  christos 
    584  1.1  christos   /* Check if this is a 16-bit op.  */
    585  1.1  christos   if (ginsn_opsize_prefix_p ())
    586  1.1  christos     stack_opnd_size = 2;
    587  1.1  christos 
    588  1.1  christos   /* The 'leave' instruction copies the contents of the RBP register
    589  1.1  christos      into the RSP register to release all stack space allocated to the
    590  1.1  christos      procedure.  */
    591  1.1  christos   ginsn = ginsn_new_mov (insn_end_sym, false,
    592  1.1  christos 			 GINSN_SRC_REG, REG_FP, 0,
    593  1.1  christos 			 GINSN_DST_REG, REG_SP, 0);
    594  1.1  christos   ginsn_set_where (ginsn);
    595  1.1  christos   /* Then it restores the old value of the RBP register from the stack.  */
    596  1.1  christos   ginsn_next = ginsn_new_load (insn_end_sym, false,
    597  1.1  christos 			       GINSN_SRC_INDIRECT, REG_SP, 0,
    598  1.1  christos 			       GINSN_DST_REG, REG_FP);
    599  1.1  christos   ginsn_set_where (ginsn_next);
    600  1.1  christos   gas_assert (!ginsn_link_next (ginsn, ginsn_next));
    601  1.1  christos   ginsn_last = ginsn_new_add (insn_end_sym, false,
    602  1.1  christos 			      GINSN_SRC_REG, REG_SP, 0,
    603  1.1  christos 			      GINSN_SRC_IMM, 0, stack_opnd_size,
    604  1.1  christos 			      GINSN_DST_REG, REG_SP, 0);
    605  1.1  christos   ginsn_set_where (ginsn_next);
    606  1.1  christos   gas_assert (!ginsn_link_next (ginsn_next, ginsn_last));
    607  1.1  christos 
    608  1.1  christos   return ginsn;
    609  1.1  christos }
    610  1.1  christos 
    611  1.1  christos /* Check if an instruction is whitelisted.
    612  1.1  christos 
    613  1.1  christos    Some instructions may appear with REG_SP or REG_FP as destination, because
    614  1.1  christos    which they are deemed 'interesting' for SCFI.  Whitelist them here if they
    615  1.1  christos    do not affect SCFI correctness.  */
    616  1.1  christos 
    617  1.1  christos static bool
    618  1.1  christos x86_ginsn_safe_to_skip_p (void)
    619  1.1  christos {
    620  1.1  christos   bool skip_p = false;
    621  1.1  christos   uint16_t opcode = i.tm.base_opcode;
    622  1.1  christos 
    623  1.1  christos   switch (opcode)
    624  1.1  christos     {
    625  1.1  christos     case 0x80:
    626  1.1  christos     case 0x81:
    627  1.1  christos     case 0x83:
    628  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
    629  1.1  christos 	break;
    630  1.1  christos       /* cmp imm, reg/rem.  */
    631  1.1  christos       if (i.tm.extension_opcode == 7)
    632  1.1  christos 	skip_p = true;
    633  1.1  christos       break;
    634  1.1  christos 
    635  1.1  christos     case 0x38:
    636  1.1  christos     case 0x39:
    637  1.1  christos     case 0x3a:
    638  1.1  christos     case 0x3b:
    639  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
    640  1.1  christos 	break;
    641  1.1  christos       /* cmp imm/reg/mem, reg/rem.  */
    642  1.1  christos       skip_p = true;
    643  1.1  christos       break;
    644  1.1  christos 
    645  1.1  christos     case 0xf6:
    646  1.1  christos     case 0xf7:
    647  1.1  christos     case 0x84:
    648  1.1  christos     case 0x85:
    649  1.1  christos       /* test imm/reg/mem, reg/mem.  */
    650  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
    651  1.1  christos 	break;
    652  1.1  christos       skip_p = true;
    653  1.1  christos       break;
    654  1.1  christos 
    655  1.1  christos     default:
    656  1.1  christos       break;
    657  1.1  christos     }
    658  1.1  christos 
    659  1.1  christos   return skip_p;
    660  1.1  christos }
    661  1.1  christos 
    662  1.1  christos #define X86_GINSN_UNHANDLED_NONE        0
    663  1.1  christos #define X86_GINSN_UNHANDLED_DEST_REG    1
    664  1.1  christos #define X86_GINSN_UNHANDLED_CFG         2
    665  1.1  christos #define X86_GINSN_UNHANDLED_STACKOP     3
    666  1.1  christos #define X86_GINSN_UNHANDLED_UNEXPECTED  4
    667  1.1  christos 
    668  1.1  christos /* Check the input insn for its impact on the correctness of the synthesized
    669  1.1  christos    CFI.  Returns an error code to the caller.  */
    670  1.1  christos 
    671  1.1  christos static int
    672  1.1  christos x86_ginsn_unhandled (void)
    673  1.1  christos {
    674  1.1  christos   int err = X86_GINSN_UNHANDLED_NONE;
    675  1.1  christos   const reg_entry *reg_op;
    676  1.1  christos   unsigned int dw2_regnum;
    677  1.1  christos 
    678  1.1  christos   /* Keep an eye out for instructions affecting control flow.  */
    679  1.1  christos   if (i.tm.opcode_modifier.jump)
    680  1.1  christos     err = X86_GINSN_UNHANDLED_CFG;
    681  1.1  christos   /* Also, for any instructions involving an implicit update to the stack
    682  1.1  christos      pointer.  */
    683  1.1  christos   else if (i.tm.opcode_modifier.operandconstraint == IMPLICIT_STACK_OP)
    684  1.1  christos     err = X86_GINSN_UNHANDLED_STACKOP;
    685  1.1  christos   /* Finally, also check if the missed instructions are affecting REG_SP or
    686  1.1  christos      REG_FP.  The destination operand is the last at all stages of assembly
    687  1.1  christos      (due to following AT&T syntax layout in the internal representation).  In
    688  1.1  christos      case of Intel syntax input, this still remains true as swap_operands ()
    689  1.1  christos      is done by now.
    690  1.1  christos      PS: These checks do not involve index / base reg, as indirect memory
    691  1.1  christos      accesses via REG_SP or REG_FP do not affect SCFI correctness.
    692  1.1  christos      (Also note these instructions are candidates for other ginsn generation
    693  1.1  christos      modes in future.  TBD_GINSN_GEN_NOT_SCFI.)  */
    694  1.1  christos   else if (i.operands && i.reg_operands
    695  1.1  christos 	   && !(i.flags[i.operands - 1] & Operand_Mem))
    696  1.1  christos     {
    697  1.1  christos       reg_op = i.op[i.operands - 1].regs;
    698  1.1  christos       if (reg_op)
    699  1.1  christos 	{
    700  1.1  christos 	  dw2_regnum = ginsn_dw2_regnum (reg_op);
    701  1.1  christos 	  if (dw2_regnum == REG_SP || dw2_regnum == REG_FP)
    702  1.1  christos 	    err = X86_GINSN_UNHANDLED_DEST_REG;
    703  1.1  christos 	}
    704  1.1  christos       else
    705  1.1  christos 	/* Something unexpected.  Indicate to caller.  */
    706  1.1  christos 	err = X86_GINSN_UNHANDLED_UNEXPECTED;
    707  1.1  christos     }
    708  1.1  christos 
    709  1.1  christos   return err;
    710  1.1  christos }
    711  1.1  christos 
    712  1.1  christos /* Generate one or more generic GAS instructions, a.k.a, ginsns for the current
    713  1.1  christos    machine instruction.
    714  1.1  christos 
    715  1.1  christos    Returns the head of linked list of ginsn(s) added, if success; Returns NULL
    716  1.1  christos    if failure.
    717  1.1  christos 
    718  1.1  christos    The input ginsn_gen_mode GMODE determines the set of minimal necessary
    719  1.1  christos    ginsns necessary for correctness of any passes applicable for that mode.
    720  1.1  christos    For supporting the GINSN_GEN_SCFI generation mode, following is the list of
    721  1.1  christos    machine instructions that must be translated into the corresponding ginsns
    722  1.1  christos    to ensure correctness of SCFI:
    723  1.1  christos      - All instructions affecting the two registers that could potentially
    724  1.1  christos        be used as the base register for CFA tracking.  For SCFI, the base
    725  1.1  christos        register for CFA tracking is limited to REG_SP and REG_FP only for
    726  1.1  christos        now.
    727  1.1  christos      - All change of flow instructions: conditional and unconditional branches,
    728  1.1  christos        call and return from functions.
    729  1.1  christos      - All instructions that can potentially be a register save / restore
    730  1.1  christos        operation.
    731  1.1  christos      - All instructions that perform stack manipulation implicitly: the CALL,
    732  1.1  christos        RET, PUSH, POP, ENTER, and LEAVE instructions.
    733  1.1  christos 
    734  1.1  christos    The function currently supports GINSN_GEN_SCFI ginsn generation mode only.
    735  1.1  christos    To support other generation modes will require work on this target-specific
    736  1.1  christos    process of creation of ginsns:
    737  1.1  christos      - Some of such places are tagged with TBD_GINSN_GEN_NOT_SCFI to serve as
    738  1.1  christos        possible starting points.
    739  1.1  christos      - Also note that ginsn representation may need enhancements.  Specifically,
    740  1.1  christos        note some TBD_GINSN_INFO_LOSS and TBD_GINSN_REPRESENTATION_LIMIT markers.
    741  1.1  christos    */
    742  1.1  christos 
    743  1.1  christos static ginsnS *
    744  1.1  christos x86_ginsn_new (const symbolS *insn_end_sym, enum ginsn_gen_mode gmode)
    745  1.1  christos {
    746  1.1  christos   int err = 0;
    747  1.1  christos   uint16_t opcode;
    748  1.1  christos   unsigned int dw2_regnum;
    749  1.1  christos   const reg_entry *mem_reg;
    750  1.1  christos   ginsnS *ginsn = NULL;
    751  1.1  christos   ginsnS *ginsn_next = NULL;
    752  1.1  christos   /* In 64-bit mode, the default stack update size is 8 bytes.  */
    753  1.1  christos   int stack_opnd_size = 8;
    754  1.1  christos 
    755  1.1  christos   /* Currently supports generation of selected ginsns, sufficient for
    756  1.1  christos      the use-case of SCFI only.  */
    757  1.1  christos   if (gmode != GINSN_GEN_SCFI)
    758  1.1  christos     return ginsn;
    759  1.1  christos 
    760  1.1  christos   opcode = i.tm.base_opcode;
    761  1.1  christos 
    762  1.1  christos   /* Until it is clear how to handle APX NDD and other new opcodes, disallow
    763  1.1  christos      them from SCFI.  */
    764  1.1  christos   if (is_apx_rex2_encoding ()
    765  1.1  christos       || (i.tm.opcode_modifier.evex && is_apx_evex_encoding ()))
    766  1.1  christos     {
    767  1.1  christos       as_bad (_("SCFI: unsupported APX op %#x may cause incorrect CFI"),
    768  1.1  christos 	      opcode);
    769  1.1  christos       return ginsn;
    770  1.1  christos     }
    771  1.1  christos 
    772  1.1  christos   switch (opcode)
    773  1.1  christos     {
    774  1.1  christos 
    775  1.1  christos     /* Add opcodes 0x0/0x2 and sub opcodes 0x28/0x2a (with opcode_space
    776  1.1  christos        SPACE_BASE) are 8-bit ops.  While they are relevant for SCFI
    777  1.1  christos        correctness,  skip handling them here and use the x86_ginsn_unhandled
    778  1.1  christos        code path to generate GINSN_TYPE_OTHER when necessary.  */
    779  1.1  christos 
    780  1.1  christos     case 0x1:  /* add reg, reg/mem.  */
    781  1.1  christos     case 0x29: /* sub reg, reg/mem.  */
    782  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
    783  1.1  christos 	break;
    784  1.1  christos       ginsn = x86_ginsn_addsub_reg_mem (insn_end_sym);
    785  1.1  christos       break;
    786  1.1  christos 
    787  1.1  christos     case 0x3:  /* add reg/mem, reg.  */
    788  1.1  christos     case 0x2b: /* sub reg/mem, reg.  */
    789  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
    790  1.1  christos 	break;
    791  1.1  christos       ginsn = x86_ginsn_addsub_mem_reg (insn_end_sym);
    792  1.1  christos       break;
    793  1.1  christos 
    794  1.1  christos     case 0xa0: /* push fs.  */
    795  1.1  christos     case 0xa8: /* push gs.  */
    796  1.1  christos       /* push fs / push gs have opcode_space == SPACE_0F.  */
    797  1.1  christos       if (i.tm.opcode_space != SPACE_0F)
    798  1.1  christos 	break;
    799  1.1  christos       dw2_regnum = ginsn_dw2_regnum (i.op[0].regs);
    800  1.1  christos       /* Check if operation size is 16-bit.  */
    801  1.1  christos       if (ginsn_opsize_prefix_p ())
    802  1.1  christos 	stack_opnd_size = 2;
    803  1.1  christos       ginsn = ginsn_new_sub (insn_end_sym, false,
    804  1.1  christos 			     GINSN_SRC_REG, REG_SP, 0,
    805  1.1  christos 			     GINSN_SRC_IMM, 0, stack_opnd_size,
    806  1.1  christos 			     GINSN_DST_REG, REG_SP, 0);
    807  1.1  christos       ginsn_set_where (ginsn);
    808  1.1  christos       ginsn_next = ginsn_new_store (insn_end_sym, false,
    809  1.1  christos 				    GINSN_SRC_REG, dw2_regnum,
    810  1.1  christos 				    GINSN_DST_INDIRECT, REG_SP, 0);
    811  1.1  christos       ginsn_set_where (ginsn_next);
    812  1.1  christos       gas_assert (!ginsn_link_next (ginsn, ginsn_next));
    813  1.1  christos       break;
    814  1.1  christos 
    815  1.1  christos     case 0xa1: /* pop fs.  */
    816  1.1  christos     case 0xa9: /* pop gs.  */
    817  1.1  christos       /* pop fs / pop gs have opcode_space == SPACE_0F.  */
    818  1.1  christos       if (i.tm.opcode_space != SPACE_0F)
    819  1.1  christos 	break;
    820  1.1  christos       dw2_regnum = ginsn_dw2_regnum (i.op[0].regs);
    821  1.1  christos       /* Check if operation size is 16-bit.  */
    822  1.1  christos       if (ginsn_opsize_prefix_p ())
    823  1.1  christos 	stack_opnd_size = 2;
    824  1.1  christos       ginsn = ginsn_new_load (insn_end_sym, false,
    825  1.1  christos 			      GINSN_SRC_INDIRECT, REG_SP, 0,
    826  1.1  christos 			      GINSN_DST_REG, dw2_regnum);
    827  1.1  christos       ginsn_set_where (ginsn);
    828  1.1  christos       ginsn_next = ginsn_new_add (insn_end_sym, false,
    829  1.1  christos 				  GINSN_SRC_REG, REG_SP, 0,
    830  1.1  christos 				  GINSN_SRC_IMM, 0, stack_opnd_size,
    831  1.1  christos 				  GINSN_DST_REG, REG_SP, 0);
    832  1.1  christos       ginsn_set_where (ginsn_next);
    833  1.1  christos       gas_assert (!ginsn_link_next (ginsn, ginsn_next));
    834  1.1  christos       break;
    835  1.1  christos 
    836  1.1  christos     case 0x50 ... 0x57:
    837  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
    838  1.1  christos 	break;
    839  1.1  christos       /* push reg.  */
    840  1.1  christos       dw2_regnum = ginsn_dw2_regnum (i.op[0].regs);
    841  1.1  christos       /* Check if operation size is 16-bit.  */
    842  1.1  christos       if (ginsn_opsize_prefix_p ())
    843  1.1  christos 	stack_opnd_size = 2;
    844  1.1  christos       ginsn = ginsn_new_sub (insn_end_sym, false,
    845  1.1  christos 			     GINSN_SRC_REG, REG_SP, 0,
    846  1.1  christos 			     GINSN_SRC_IMM, 0, stack_opnd_size,
    847  1.1  christos 			     GINSN_DST_REG, REG_SP, 0);
    848  1.1  christos       ginsn_set_where (ginsn);
    849  1.1  christos       ginsn_next = ginsn_new_store (insn_end_sym, false,
    850  1.1  christos 				    GINSN_SRC_REG, dw2_regnum,
    851  1.1  christos 				    GINSN_DST_INDIRECT, REG_SP, 0);
    852  1.1  christos       ginsn_set_where (ginsn_next);
    853  1.1  christos       gas_assert (!ginsn_link_next (ginsn, ginsn_next));
    854  1.1  christos       break;
    855  1.1  christos 
    856  1.1  christos     case 0x58 ... 0x5f:
    857  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
    858  1.1  christos 	break;
    859  1.1  christos       /* pop reg.  */
    860  1.1  christos       dw2_regnum = ginsn_dw2_regnum (i.op[0].regs);
    861  1.1  christos       ginsn = ginsn_new_load (insn_end_sym, false,
    862  1.1  christos 			      GINSN_SRC_INDIRECT, REG_SP, 0,
    863  1.1  christos 			      GINSN_DST_REG, dw2_regnum);
    864  1.1  christos       ginsn_set_where (ginsn);
    865  1.1  christos       /* Check if operation size is 16-bit.  */
    866  1.1  christos       if (ginsn_opsize_prefix_p ())
    867  1.1  christos 	stack_opnd_size = 2;
    868  1.1  christos       ginsn_next = ginsn_new_add (insn_end_sym, false,
    869  1.1  christos 				  GINSN_SRC_REG, REG_SP, 0,
    870  1.1  christos 				  GINSN_SRC_IMM, 0, stack_opnd_size,
    871  1.1  christos 				  GINSN_DST_REG, REG_SP, 0);
    872  1.1  christos       ginsn_set_where (ginsn_next);
    873  1.1  christos       gas_assert (!ginsn_link_next (ginsn, ginsn_next));
    874  1.1  christos       break;
    875  1.1  christos 
    876  1.1  christos     case 0x6a: /* push imm8.  */
    877  1.1  christos     case 0x68: /* push imm16/imm32.  */
    878  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
    879  1.1  christos 	break;
    880  1.1  christos       /* Check if operation size is 16-bit.  */
    881  1.1  christos       if (ginsn_opsize_prefix_p ())
    882  1.1  christos 	stack_opnd_size = 2;
    883  1.1  christos       /* Skip getting the value of imm from machine instruction
    884  1.1  christos 	 because this is not important for SCFI.  */
    885  1.1  christos       ginsn = ginsn_new_sub (insn_end_sym, false,
    886  1.1  christos 			     GINSN_SRC_REG, REG_SP, 0,
    887  1.1  christos 			     GINSN_SRC_IMM, 0, stack_opnd_size,
    888  1.1  christos 			     GINSN_DST_REG, REG_SP, 0);
    889  1.1  christos       ginsn_set_where (ginsn);
    890  1.1  christos       ginsn_next = ginsn_new_store (insn_end_sym, false,
    891  1.1  christos 				    GINSN_SRC_IMM, 0,
    892  1.1  christos 				    GINSN_DST_INDIRECT, REG_SP, 0);
    893  1.1  christos       ginsn_set_where (ginsn_next);
    894  1.1  christos       gas_assert (!ginsn_link_next (ginsn, ginsn_next));
    895  1.1  christos       break;
    896  1.1  christos 
    897  1.1  christos     /* PS: Opcodes 0x80 ... 0x8f with opcode_space SPACE_0F are present
    898  1.1  christos        only after relaxation.  They do not need to be handled for ginsn
    899  1.1  christos        creation.  */
    900  1.1  christos     case 0x70 ... 0x7f:
    901  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
    902  1.1  christos 	break;
    903  1.1  christos       ginsn = x86_ginsn_jump (insn_end_sym, true);
    904  1.1  christos       break;
    905  1.1  christos 
    906  1.1  christos     case 0x80:
    907  1.1  christos     case 0x81:
    908  1.1  christos     case 0x83:
    909  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
    910  1.1  christos 	break;
    911  1.1  christos       ginsn = x86_ginsn_alu_imm (insn_end_sym);
    912  1.1  christos       break;
    913  1.1  christos 
    914  1.1  christos     case 0x8a: /* mov r/m8, r8.  */
    915  1.1  christos     case 0x8b: /* mov r/m(16/32/64), r(16/32/64).  */
    916  1.1  christos     case 0x88: /* mov r8, r/m8.  */
    917  1.1  christos     case 0x89: /* mov r(16/32/64), r/m(16/32/64).  */
    918  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
    919  1.1  christos 	break;
    920  1.1  christos       ginsn = x86_ginsn_move (insn_end_sym);
    921  1.1  christos       break;
    922  1.1  christos 
    923  1.1  christos     case 0x8d:
    924  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
    925  1.1  christos 	break;
    926  1.1  christos       /* lea disp(%base,%index,imm), %dst.  */
    927  1.1  christos       ginsn = x86_ginsn_lea (insn_end_sym);
    928  1.1  christos       break;
    929  1.1  christos 
    930  1.1  christos     case 0x8f:
    931  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
    932  1.1  christos 	break;
    933  1.1  christos       /* pop to reg/mem.  */
    934  1.1  christos       if (i.mem_operands)
    935  1.1  christos 	{
    936  1.1  christos 	  mem_reg = (i.base_reg) ? i.base_reg : i.index_reg;
    937  1.1  christos 	  /* Use dummy register if no base or index.  Unlike other opcodes,
    938  1.1  christos 	     ginsns must be generated as this affect stack pointer.  */
    939  1.1  christos 	  dw2_regnum = (mem_reg
    940  1.1  christos 			? ginsn_dw2_regnum (mem_reg)
    941  1.1  christos 			: GINSN_DW2_REGNUM_RSI_DUMMY);
    942  1.1  christos 	}
    943  1.1  christos       else
    944  1.1  christos 	dw2_regnum = ginsn_dw2_regnum (i.op[0].regs);
    945  1.1  christos       ginsn = ginsn_new_load (insn_end_sym, false,
    946  1.1  christos 			      GINSN_SRC_INDIRECT, REG_SP, 0,
    947  1.1  christos 			      GINSN_DST_INDIRECT, dw2_regnum);
    948  1.1  christos       ginsn_set_where (ginsn);
    949  1.1  christos       /* Check if operation size is 16-bit.  */
    950  1.1  christos       if (ginsn_opsize_prefix_p ())
    951  1.1  christos 	stack_opnd_size = 2;
    952  1.1  christos       ginsn_next = ginsn_new_add (insn_end_sym, false,
    953  1.1  christos 				  GINSN_SRC_REG, REG_SP, 0,
    954  1.1  christos 				  GINSN_SRC_IMM, 0, stack_opnd_size,
    955  1.1  christos 				  GINSN_DST_REG, REG_SP, 0);
    956  1.1  christos       ginsn_set_where (ginsn_next);
    957  1.1  christos       gas_assert (!ginsn_link_next (ginsn, ginsn_next));
    958  1.1  christos       break;
    959  1.1  christos 
    960  1.1  christos     case 0x9c:
    961  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
    962  1.1  christos 	break;
    963  1.1  christos       /* pushf / pushfq.  */
    964  1.1  christos       /* Check if operation size is 16-bit.  */
    965  1.1  christos       if (ginsn_opsize_prefix_p ())
    966  1.1  christos 	stack_opnd_size = 2;
    967  1.1  christos       ginsn = ginsn_new_sub (insn_end_sym, false,
    968  1.1  christos 			     GINSN_SRC_REG, REG_SP, 0,
    969  1.1  christos 			     GINSN_SRC_IMM, 0, stack_opnd_size,
    970  1.1  christos 			     GINSN_DST_REG, REG_SP, 0);
    971  1.1  christos       ginsn_set_where (ginsn);
    972  1.1  christos       /* FIXME - hardcode the actual DWARF reg number value.  As for SCFI
    973  1.1  christos 	 correctness, although this behaves simply a placeholder value; its
    974  1.1  christos 	 just clearer if the value is correct.  */
    975  1.1  christos       dw2_regnum = GINSN_DW2_REGNUM_EFLAGS;
    976  1.1  christos       ginsn_next = ginsn_new_store (insn_end_sym, false,
    977  1.1  christos 				    GINSN_SRC_REG, dw2_regnum,
    978  1.1  christos 				    GINSN_DST_INDIRECT, REG_SP, 0);
    979  1.1  christos       ginsn_set_where (ginsn_next);
    980  1.1  christos       gas_assert (!ginsn_link_next (ginsn, ginsn_next));
    981  1.1  christos       break;
    982  1.1  christos 
    983  1.1  christos     case 0x9d:
    984  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
    985  1.1  christos 	break;
    986  1.1  christos       /* popf / popfq.  */
    987  1.1  christos       /* Check if operation size is 16-bit.  */
    988  1.1  christos       if (ginsn_opsize_prefix_p ())
    989  1.1  christos 	stack_opnd_size = 2;
    990  1.1  christos       /* FIXME - hardcode the actual DWARF reg number value.  As for SCFI
    991  1.1  christos 	 correctness, although this behaves simply a placeholder value; its
    992  1.1  christos 	 just clearer if the value is correct.  */
    993  1.1  christos       dw2_regnum = GINSN_DW2_REGNUM_EFLAGS;
    994  1.1  christos       ginsn = ginsn_new_load (insn_end_sym, false,
    995  1.1  christos 			      GINSN_SRC_INDIRECT, REG_SP, 0,
    996  1.1  christos 			      GINSN_DST_REG, dw2_regnum);
    997  1.1  christos       ginsn_set_where (ginsn);
    998  1.1  christos       ginsn_next = ginsn_new_add (insn_end_sym, false,
    999  1.1  christos 				  GINSN_SRC_REG, REG_SP, 0,
   1000  1.1  christos 				  GINSN_SRC_IMM, 0, stack_opnd_size,
   1001  1.1  christos 				  GINSN_DST_REG, REG_SP, 0);
   1002  1.1  christos       ginsn_set_where (ginsn_next);
   1003  1.1  christos       gas_assert (!ginsn_link_next (ginsn, ginsn_next));
   1004  1.1  christos       break;
   1005  1.1  christos 
   1006  1.1  christos     case 0xff:
   1007  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
   1008  1.1  christos 	break;
   1009  1.1  christos       /* push from reg/mem.  */
   1010  1.1  christos       if (i.tm.extension_opcode == 6)
   1011  1.1  christos 	{
   1012  1.1  christos 	  /* Check if operation size is 16-bit.  */
   1013  1.1  christos 	  if (ginsn_opsize_prefix_p ())
   1014  1.1  christos 	    stack_opnd_size = 2;
   1015  1.1  christos 	  ginsn = ginsn_new_sub (insn_end_sym, false,
   1016  1.1  christos 				 GINSN_SRC_REG, REG_SP, 0,
   1017  1.1  christos 				 GINSN_SRC_IMM, 0, stack_opnd_size,
   1018  1.1  christos 				 GINSN_DST_REG, REG_SP, 0);
   1019  1.1  christos 	  ginsn_set_where (ginsn);
   1020  1.1  christos 	  if (i.mem_operands)
   1021  1.1  christos 	    {
   1022  1.1  christos 	      mem_reg = (i.base_reg) ? i.base_reg : i.index_reg;
   1023  1.1  christos 	      /* Use dummy register if no base or index.  Unlike other opcodes,
   1024  1.1  christos 		 ginsns must be generated as this affect stack pointer.  */
   1025  1.1  christos 	      dw2_regnum = (mem_reg
   1026  1.1  christos 			    ? ginsn_dw2_regnum (mem_reg)
   1027  1.1  christos 			    : GINSN_DW2_REGNUM_RSI_DUMMY);
   1028  1.1  christos 	    }
   1029  1.1  christos 	  else
   1030  1.1  christos 	    dw2_regnum = ginsn_dw2_regnum (i.op[0].regs);
   1031  1.1  christos 	  ginsn_next = ginsn_new_store (insn_end_sym, false,
   1032  1.1  christos 					GINSN_SRC_INDIRECT, dw2_regnum,
   1033  1.1  christos 					GINSN_DST_INDIRECT, REG_SP, 0);
   1034  1.1  christos 	  ginsn_set_where (ginsn_next);
   1035  1.1  christos 	  gas_assert (!ginsn_link_next (ginsn, ginsn_next));
   1036  1.1  christos 	}
   1037  1.1  christos       else if (i.tm.extension_opcode == 4 || i.tm.extension_opcode == 2)
   1038  1.1  christos 	ginsn = x86_ginsn_indirect_branch (insn_end_sym);
   1039  1.1  christos       break;
   1040  1.1  christos 
   1041  1.1  christos     case 0xc2: /* ret imm16.  */
   1042  1.1  christos     case 0xc3: /* ret.  */
   1043  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
   1044  1.1  christos 	break;
   1045  1.1  christos       /* Near ret.  */
   1046  1.1  christos       ginsn = ginsn_new_return (insn_end_sym, true);
   1047  1.1  christos       ginsn_set_where (ginsn);
   1048  1.1  christos       break;
   1049  1.1  christos 
   1050  1.1  christos     case 0xc8:
   1051  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
   1052  1.1  christos 	break;
   1053  1.1  christos       /* enter.  */
   1054  1.1  christos       ginsn = x86_ginsn_enter (insn_end_sym);
   1055  1.1  christos       break;
   1056  1.1  christos 
   1057  1.1  christos     case 0xc9:
   1058  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
   1059  1.1  christos 	break;
   1060  1.1  christos       /* leave.  */
   1061  1.1  christos       ginsn = x86_ginsn_leave (insn_end_sym);
   1062  1.1  christos       break;
   1063  1.1  christos 
   1064  1.1  christos     case 0xe0 ... 0xe2: /* loop / loope / loopne.  */
   1065  1.1  christos     case 0xe3:          /* jecxz / jrcxz.  */
   1066  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
   1067  1.1  christos 	break;
   1068  1.1  christos       ginsn = x86_ginsn_jump (insn_end_sym, true);
   1069  1.1  christos       ginsn_set_where (ginsn);
   1070  1.1  christos       break;
   1071  1.1  christos 
   1072  1.1  christos     case 0xe8:
   1073  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
   1074  1.1  christos 	break;
   1075  1.1  christos       /* PS: SCFI machinery does not care about which func is being
   1076  1.1  christos 	 called.  OK to skip that info.  */
   1077  1.1  christos       ginsn = ginsn_new_call (insn_end_sym, true,
   1078  1.1  christos 			      GINSN_SRC_SYMBOL, 0, NULL);
   1079  1.1  christos       ginsn_set_where (ginsn);
   1080  1.1  christos       break;
   1081  1.1  christos 
   1082  1.1  christos     /* PS: opcode 0xe9 appears only after relaxation.  Skip here.  */
   1083  1.1  christos     case 0xeb:
   1084  1.1  christos       /* If opcode_space != SPACE_BASE, this is not a jmp insn.  Skip it
   1085  1.1  christos 	 for GINSN_GEN_SCFI.  */
   1086  1.1  christos       if (i.tm.opcode_space != SPACE_BASE)
   1087  1.1  christos 	break;
   1088  1.1  christos       /* Unconditional jmp.  */
   1089  1.1  christos       ginsn = x86_ginsn_jump (insn_end_sym, false);
   1090  1.1  christos       ginsn_set_where (ginsn);
   1091  1.1  christos       break;
   1092  1.1  christos 
   1093  1.1  christos     default:
   1094  1.1  christos       /* TBD_GINSN_GEN_NOT_SCFI: Skip all other opcodes uninteresting for
   1095  1.1  christos 	 GINSN_GEN_SCFI mode.  */
   1096  1.1  christos       break;
   1097  1.1  christos     }
   1098  1.1  christos 
   1099  1.1  christos   if (!ginsn && !x86_ginsn_safe_to_skip_p ())
   1100  1.1  christos     {
   1101  1.1  christos       /* For all unhandled insns that are not whitelisted, check that they do
   1102  1.1  christos 	 not impact SCFI correctness.  */
   1103  1.1  christos       err = x86_ginsn_unhandled ();
   1104  1.1  christos       switch (err)
   1105  1.1  christos 	{
   1106  1.1  christos 	case X86_GINSN_UNHANDLED_NONE:
   1107  1.1  christos 	  break;
   1108  1.1  christos 	case X86_GINSN_UNHANDLED_DEST_REG:
   1109  1.1  christos 	  /* Not all writes to REG_FP are harmful in context of SCFI.  Simply
   1110  1.1  christos 	     generate a GINSN_TYPE_OTHER with destination set to the
   1111  1.1  christos 	     appropriate register.  The SCFI machinery will bail out if this
   1112  1.1  christos 	     ginsn affects SCFI correctness.  */
   1113  1.1  christos 	  dw2_regnum = ginsn_dw2_regnum (i.op[i.operands - 1].regs);
   1114  1.1  christos 	  ginsn = ginsn_new_other (insn_end_sym, true,
   1115  1.1  christos 				   GINSN_SRC_IMM, 0,
   1116  1.1  christos 				   GINSN_SRC_IMM, 0,
   1117  1.1  christos 				   GINSN_DST_REG, dw2_regnum);
   1118  1.1  christos 	  ginsn_set_where (ginsn);
   1119  1.1  christos 	  break;
   1120  1.1  christos 	case X86_GINSN_UNHANDLED_CFG:
   1121  1.1  christos 	case X86_GINSN_UNHANDLED_STACKOP:
   1122  1.1  christos 	  as_bad (_("SCFI: unhandled op %#x may cause incorrect CFI"), opcode);
   1123  1.1  christos 	  break;
   1124  1.1  christos 	case X86_GINSN_UNHANDLED_UNEXPECTED:
   1125  1.1  christos 	  as_bad (_("SCFI: unexpected op %#x may cause incorrect CFI"),
   1126  1.1  christos 		  opcode);
   1127  1.1  christos 	  break;
   1128  1.1  christos 	default:
   1129  1.1  christos 	  abort ();
   1130  1.1  christos 	  break;
   1131  1.1  christos 	}
   1132  1.1  christos     }
   1133  1.1  christos 
   1134  1.1  christos   return ginsn;
   1135  1.1  christos }
   1136