Home | History | Annotate | Line # | Download | only in config
tc-aarch64-ginsn.c revision 1.1
      1 /* tc-aarch64-ginsn.c -- Ginsn generation for the AArch64 ISA
      2 
      3    Copyright (C) 2024-2025 Free Software Foundation, Inc.
      4 
      5    This file is part of GAS.
      6 
      7    GAS is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3 of the license, or
     10    (at your option) any later version.
     11 
     12    GAS is distributed in the hope that it will be useful,
     13    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15    GNU General Public License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this program; see the file COPYING3. If not,
     19    see <http://www.gnu.org/licenses/>.  */
     20 
     21 /* This file contains the implementation of the ginsn creation for aarch64
     22    instructions.  Most functions will read the aarch64_instruction inst
     23    object, but none should need to modify it.  */
     24 
     25 #ifdef OBJ_ELF
     26 
     27 /* Invalid DWARF register number.  Used when WZR / XZR is seen.  */
     28 #define GINSN_DW2_REGNUM_INVALID  (~0U)
     29 
     30 /* Return whether the given register number is a callee-saved register for
     31    SCFI purposes.
     32 
     33    Apart from the callee-saved GPRs, SCFI always tracks SP, FP and LR
     34    additionally.  As for the FP/Advanced SIMD registers, v8-v15 are
     35    callee-saved.  */
     36 
     37 bool
     38 aarch64_scfi_callee_saved_p (unsigned int dw2reg_num)
     39 {
     40   /* PS: Ensure SCFI_MAX_REG_ID is the max DWARF register number to cover
     41      all the registers here.  */
     42   if (dw2reg_num == REG_SP /* x31.  */
     43       || dw2reg_num == REG_FP /* x29.  */
     44       || dw2reg_num == REG_LR /* x30.  */
     45       || (dw2reg_num >= 19 && dw2reg_num <= 28) /* x19 - x28.  */
     46       || (dw2reg_num >= 72 && dw2reg_num <= 79) /* v8 - v15.  */)
     47     return true;
     48 
     49   return false;
     50 }
     51 
     52 /* Get the DWARF register number for the given OPND.  If OPND is an address,
     53    the returned register is the base register.  If OPND spans multiple
     54    registers, the returned register is the first of those registers.  */
     55 
     56 static unsigned int
     57 ginsn_dw2_regnum (aarch64_opnd_info *opnd)
     58 {
     59   enum aarch64_operand_class opnd_class;
     60   unsigned int dw2reg_num = 0;
     61 
     62   opnd_class = aarch64_get_operand_class (opnd->type);
     63 
     64   switch (opnd_class)
     65     {
     66     case AARCH64_OPND_CLASS_FP_REG:
     67       dw2reg_num = opnd->reg.regno + 64;
     68       break;
     69     case AARCH64_OPND_CLASS_SVE_REGLIST:
     70       dw2reg_num = opnd->reglist.first_regno + 64;
     71       break;
     72     case AARCH64_OPND_CLASS_ADDRESS:
     73       dw2reg_num = opnd->addr.base_regno;
     74       break;
     75     case AARCH64_OPND_CLASS_INT_REG:
     76     case AARCH64_OPND_CLASS_MODIFIED_REG:
     77       /* Use an invalid DWARF register value in case of WZR, else this will be an
     78 	 incorrect dependency on REG_SP.  */
     79       if (aarch64_zero_register_p (opnd))
     80 	dw2reg_num = GINSN_DW2_REGNUM_INVALID;
     81       else
     82 	/* For GPRs of our interest (callee-saved regs, SP, FP, LR),
     83 	   DWARF register number is the same as AArch64 register number.  */
     84 	dw2reg_num = opnd->reg.regno;
     85       break;
     86     default:
     87       as_bad ("Unexpected operand class in ginsn_dw2_regnum");
     88       break;
     89     }
     90 
     91   return dw2reg_num;
     92 }
     93 
     94 static bool
     95 ginsn_dw2_regnum_invalid_p (unsigned int opnd_reg)
     96 {
     97   return (opnd_reg == GINSN_DW2_REGNUM_INVALID);
     98 }
     99 
    100 /* Generate ginsn for addsub instructions with immediate opnd.  */
    101 
    102 static ginsnS *
    103 aarch64_ginsn_addsub_imm (const symbolS *insn_end_sym)
    104 {
    105   ginsnS *ginsn = NULL;
    106   bool add_p, sub_p;
    107   offsetT src_imm = 0;
    108   unsigned int dst_reg, opnd_reg;
    109   aarch64_opnd_info *dst, *opnd;
    110   ginsnS *(*ginsn_func) (const symbolS *, bool,
    111 			 enum ginsn_src_type, unsigned int, offsetT,
    112 			 enum ginsn_src_type, unsigned int, offsetT,
    113 			 enum ginsn_dst_type, unsigned int, offsetT);
    114 
    115   aarch64_inst *base = &inst.base;
    116   const aarch64_opcode *opcode = base->opcode;
    117 
    118   add_p = aarch64_opcode_subclass_p (opcode, F_ARITH_ADD);
    119   sub_p = aarch64_opcode_subclass_p (opcode, F_ARITH_SUB);
    120   gas_assert (add_p || sub_p);
    121   ginsn_func = add_p ? ginsn_new_add : ginsn_new_sub;
    122 
    123   gas_assert (aarch64_num_of_operands (opcode) == 3);
    124   dst = &base->operands[0];
    125   opnd = &base->operands[1];
    126 
    127   if (aarch64_gas_internal_fixup_p () && inst.reloc.exp.X_op == O_constant)
    128     src_imm = inst.reloc.exp.X_add_number;
    129   /* For any other relocation type, e.g., in add reg, reg, symbol, skip now
    130      and handle via aarch64_ginsn_unhandled () code path.  */
    131   else if (inst.reloc.type != BFD_RELOC_UNUSED)
    132     return ginsn;
    133   /* FIXME - verify the understanding and remove assert.  */
    134   else
    135     gas_assert (0);
    136 
    137   dst_reg = ginsn_dw2_regnum (dst);
    138   opnd_reg = ginsn_dw2_regnum (opnd);
    139 
    140   if (ginsn_dw2_regnum_invalid_p (dst_reg)
    141       || ginsn_dw2_regnum_invalid_p (opnd_reg))
    142     return ginsn;
    143 
    144   ginsn = ginsn_func (insn_end_sym, true,
    145 		      GINSN_SRC_REG, opnd_reg, 0,
    146 		      GINSN_SRC_IMM, 0, src_imm,
    147 		      GINSN_DST_REG, dst_reg, 0);
    148   ginsn_set_where (ginsn);
    149 
    150   return ginsn;
    151 }
    152 
    153 /* Generate ginsn for addsub instructions with reg opnd.  */
    154 
    155 static ginsnS *
    156 aarch64_ginsn_addsub_reg (const symbolS *insn_end_sym)
    157 {
    158   ginsnS *ginsn = NULL;
    159   bool add_p, sub_p;
    160   unsigned int dst_reg, src1_reg, src2_reg;
    161   aarch64_opnd_info *dst, *src1, *src2;
    162   ginsnS *(*ginsn_func) (const symbolS *, bool,
    163 			 enum ginsn_src_type, unsigned int, offsetT,
    164 			 enum ginsn_src_type, unsigned int, offsetT,
    165 			 enum ginsn_dst_type, unsigned int, offsetT);
    166 
    167   aarch64_inst *base = &inst.base;
    168   const aarch64_opcode *opcode = base->opcode;
    169 
    170   add_p = aarch64_opcode_subclass_p (opcode, F_ARITH_ADD);
    171   sub_p = aarch64_opcode_subclass_p (opcode, F_ARITH_SUB);
    172   gas_assert (add_p || sub_p);
    173   ginsn_func = add_p ? ginsn_new_add : ginsn_new_sub;
    174 
    175   gas_assert (aarch64_num_of_operands (opcode) == 3);
    176   dst = &base->operands[0];
    177   src1 = &base->operands[1];
    178   src2 = &base->operands[2];
    179 
    180   dst_reg = ginsn_dw2_regnum (dst);
    181   src1_reg = ginsn_dw2_regnum (src1);
    182   src2_reg = ginsn_dw2_regnum (src2);
    183 
    184   if (ginsn_dw2_regnum_invalid_p (dst_reg)
    185       || ginsn_dw2_regnum_invalid_p (src1_reg)
    186       || ginsn_dw2_regnum_invalid_p (src2_reg))
    187     return ginsn;
    188 
    189   /* ATM, shift amount, if any, cannot be represented in the GINSN_TYPE_ADD or
    190      GINSN_TYPE_SUB.  As the extra information does not impact SCFI
    191      correctness, skip generating ginsn for these cases.  Note
    192      TBD_GINSN_INFO_LOSS.  */
    193   if (src2->shifter.kind != AARCH64_MOD_NONE
    194       && (src2->shifter.kind != AARCH64_MOD_LSL || src2->shifter.amount != 0))
    195     return ginsn;
    196 
    197   ginsn = ginsn_func (insn_end_sym, true,
    198 		      GINSN_SRC_REG, src1_reg, 0,
    199 		      GINSN_SRC_REG, src2_reg, 0,
    200 		      GINSN_DST_REG, dst_reg, 0);
    201   ginsn_set_where (ginsn);
    202 
    203   return ginsn;
    204 }
    205 
    206 /* Generate ginsn for the load pair and store pair instructions.  */
    207 
    208 static ginsnS *
    209 aarch64_ginsn_ldstp (const symbolS *insn_end_sym)
    210 {
    211   ginsnS *ginsn = NULL;
    212   ginsnS *ginsn_ind = NULL;
    213   ginsnS *ginsn_mem1 = NULL;
    214   ginsnS *ginsn_mem2 = NULL;
    215   ginsnS *ginsn_mem = NULL;
    216   unsigned int opnd1_reg, opnd2_reg, addr_reg;
    217   offsetT offset, mem_offset;
    218   unsigned int width = 8;
    219   bool load_p = false;
    220   bool store_p = false;
    221   bool other_p = false;
    222 
    223   aarch64_opnd_info *opnd1, *opnd2, *addr;
    224   aarch64_inst *base = &inst.base;
    225   const aarch64_opcode *opcode = base->opcode;
    226 
    227   /* This function is for handling ldp / stp ops only.  */
    228   gas_assert (opcode->iclass == ldstpair_indexed
    229 	      || opcode->iclass == ldstnapair_offs
    230 	      || opcode->iclass == ldstpair_off);
    231   gas_assert (aarch64_num_of_operands (opcode) == 3);
    232 
    233   opnd1 = &base->operands[0];
    234   opnd2 = &base->operands[1];
    235   addr = &base->operands[2];
    236 
    237   load_p = aarch64_opcode_subclass_p (opcode, F_LDST_LOAD);
    238   store_p = aarch64_opcode_subclass_p (opcode, F_LDST_STORE);
    239   other_p = aarch64_opcode_subclass_p (opcode, F_SUBCLASS_OTHER);
    240   gas_assert (load_p || store_p || other_p);
    241 
    242   addr_reg = ginsn_dw2_regnum (addr);
    243   gas_assert (!addr->addr.offset.is_reg);
    244   mem_offset = addr->addr.offset.imm;
    245 
    246   offset = mem_offset;
    247   /* Handle address calculation.  */
    248   if ((addr->addr.preind || addr->addr.postind) && addr->addr.writeback)
    249     {
    250       /* Pre-indexed store, e.g., stp x29, x30, [sp, -128]!
    251 	 Pre-indexed addressing is like offset addressing, except that
    252 	 the base pointer is updated as a result of the instruction.
    253 
    254 	 Post-indexed store, e.g., stp     x29, x30, [sp],128
    255 	 Post-index addressing is useful for popping off the stack.  The
    256 	 instruction loads the value from the location pointed at by the stack
    257 	 pointer, and then moves the stack pointer on to the next full location
    258 	 in the stack.  */
    259       ginsn_ind = ginsn_new_add (insn_end_sym, false,
    260 				 GINSN_SRC_REG, addr_reg, 0,
    261 				 GINSN_SRC_IMM, 0, mem_offset,
    262 				 GINSN_DST_REG, addr_reg, 0);
    263       ginsn_set_where (ginsn_ind);
    264 
    265       /* With post-index addressing, the value is loaded from the address in
    266 	 the base pointer, and then the pointer is updated.  With pre-index
    267 	 addressing, the addr computation has already been explicitly done.  */
    268       offset = 0;
    269     }
    270 
    271   /* Insns like ldpsw (marked with subclass F_SUBCLASS_OTHER) do not need to
    272      generate any load or store for SCFI purposes.  Next, enforce that for CFI
    273      purposes, the width of save / restore operation has to be 8 bytes or more.
    274      However, the address processing component may have updated the stack
    275      pointer.  At least, emit that ginsn and return.  Also note,
    276      TBD_GINSN_GEN_NOT_SCFI.  */
    277   if (other_p || aarch64_get_qualifier_esize (opnd1->qualifier) < 8)
    278     return ginsn_ind;
    279 
    280   opnd1_reg = ginsn_dw2_regnum (opnd1);
    281   opnd2_reg = ginsn_dw2_regnum (opnd2);
    282   /* Save / restore of WZR is not of interest for SCFI.  Exit now if both
    283      registers are not of interest.  */
    284   if (ginsn_dw2_regnum_invalid_p (opnd1_reg)
    285       && ginsn_dw2_regnum_invalid_p (opnd2_reg))
    286     return ginsn_ind;
    287 
    288   if (opnd1->qualifier == AARCH64_OPND_QLF_S_Q)
    289     {
    290       width = 16;
    291       if (target_big_endian)
    292 	offset += 8;
    293     }
    294 
    295   /* Load store pair where only one of the opnd registers is a zero register
    296      is possible.  E.g., stp	xzr, x19, [sp, #16].  */
    297   if (!ginsn_dw2_regnum_invalid_p (opnd1_reg))
    298     {
    299       if (store_p)
    300 	{
    301 	  ginsn_mem1 = ginsn_new_store (insn_end_sym, false,
    302 					GINSN_SRC_REG, opnd1_reg,
    303 					GINSN_DST_INDIRECT, addr_reg, offset);
    304 	  ginsn_set_where (ginsn_mem1);
    305 	}
    306       else
    307 	{
    308 	  ginsn_mem1 = ginsn_new_load (insn_end_sym, false,
    309 				       GINSN_SRC_INDIRECT, addr_reg, offset,
    310 				       GINSN_DST_REG, opnd1_reg);
    311 	  ginsn_set_where (ginsn_mem1);
    312 	}
    313       /* Keep track of the last memory ginsn created so far.  */
    314       ginsn_mem = ginsn_mem1;
    315     }
    316   if (!ginsn_dw2_regnum_invalid_p (opnd2_reg))
    317     {
    318       if (store_p)
    319 	{
    320 	  ginsn_mem2 = ginsn_new_store (insn_end_sym, false,
    321 					GINSN_SRC_REG, opnd2_reg,
    322 					GINSN_DST_INDIRECT, addr_reg,
    323 					offset + width);
    324 	  ginsn_set_where (ginsn_mem2);
    325 	}
    326       else
    327 	{
    328 	  ginsn_mem2 = ginsn_new_load (insn_end_sym, false,
    329 				       GINSN_SRC_INDIRECT, addr_reg, offset + width,
    330 				       GINSN_DST_REG, opnd2_reg);
    331 	  ginsn_set_where (ginsn_mem2);
    332 	}
    333       /* Keep track of the last memory ginsn created so far.  */
    334       ginsn_mem = ginsn_mem2;
    335     }
    336 
    337   if (!ginsn_dw2_regnum_invalid_p (opnd1_reg)
    338       && !ginsn_dw2_regnum_invalid_p (opnd2_reg))
    339     goto link_two_ginsn_mem;
    340   else
    341     goto link_one_ginsn_mem;
    342 
    343 link_one_ginsn_mem:
    344   /* Link the list of ginsns created.  */
    345   if (addr->addr.preind && addr->addr.writeback)
    346     gas_assert (!ginsn_link_next (ginsn_ind, ginsn_mem));
    347 
    348   if (addr->addr.postind && addr->addr.writeback)
    349     gas_assert (!ginsn_link_next (ginsn_mem, ginsn_ind));
    350 
    351   /* Make note of the first instruction in the list.  */
    352   ginsn = (addr->addr.preind && addr->addr.writeback) ? ginsn_ind : ginsn_mem;
    353   return ginsn;
    354 
    355 link_two_ginsn_mem:
    356   /* Link the list of ginsns created.  */
    357   if (addr->addr.preind && addr->addr.writeback)
    358     gas_assert (!ginsn_link_next (ginsn_ind, ginsn_mem1));
    359 
    360   gas_assert (ginsn_mem1 && ginsn_mem2 && ginsn_mem1 != ginsn_mem2);
    361   gas_assert (!ginsn_link_next (ginsn_mem1, ginsn_mem2));
    362 
    363   if (addr->addr.postind && addr->addr.writeback)
    364     gas_assert (!ginsn_link_next (ginsn_mem2, ginsn_ind));
    365 
    366   /* Make note of the first instruction in the list.  */
    367   ginsn = (addr->addr.preind && addr->addr.writeback) ? ginsn_ind : ginsn_mem1;
    368   return ginsn;
    369 }
    370 
    371 /* Generate ginsn for load and store instructions.  */
    372 
    373 static ginsnS *
    374 aarch64_ginsn_ldstr (const symbolS *insn_end_sym)
    375 {
    376   ginsnS *ginsn = NULL;
    377   ginsnS *ginsn_ind = NULL;
    378   ginsnS *ginsn_mem = NULL;
    379   unsigned int opnd_reg, addr_reg;
    380   offsetT offset, mem_offset;
    381   bool load_p = false;
    382   bool store_p = false;
    383   bool other_p = false;
    384 
    385   aarch64_opnd_info *opnd1, *addr;
    386   aarch64_inst *base = &inst.base;
    387   const aarch64_opcode *opcode = base->opcode;
    388 
    389   /* This function is for handling ldr, str ops only.  */
    390   gas_assert (opcode->iclass == ldst_imm9 || opcode->iclass == ldst_pos);
    391   gas_assert (aarch64_num_of_operands (opcode) == 2);
    392 
    393   opnd1 = &base->operands[0];
    394   addr = &base->operands[1];
    395 
    396   load_p = aarch64_opcode_subclass_p (opcode, F_LDST_LOAD);
    397   store_p = aarch64_opcode_subclass_p (opcode, F_LDST_STORE);
    398   other_p = aarch64_opcode_subclass_p (opcode, F_SUBCLASS_OTHER);
    399   gas_assert (load_p || store_p || other_p);
    400 
    401   addr_reg = ginsn_dw2_regnum (addr);
    402 
    403   if (aarch64_gas_internal_fixup_p () && inst.reloc.exp.X_op == O_constant)
    404     mem_offset = inst.reloc.exp.X_add_number;
    405   else
    406     {
    407       gas_assert (!addr->addr.offset.is_reg);
    408       mem_offset = addr->addr.offset.imm;
    409     }
    410 
    411   offset = mem_offset;
    412   /* Handle address calculation.  */
    413   if ((addr->addr.preind || addr->addr.postind) && addr->addr.writeback)
    414     {
    415       ginsn_ind = ginsn_new_add (insn_end_sym, false,
    416 				 GINSN_SRC_REG, addr_reg, 0,
    417 				 GINSN_SRC_IMM, 0, mem_offset,
    418 				 GINSN_DST_REG, addr_reg, 0);
    419       ginsn_set_where (ginsn_ind);
    420 
    421       /* With post-index addressing, the value is loaded from the address in
    422 	 the base pointer, and then the pointer is updated.  With pre-index
    423 	 addressing, the addr computation has already been explicitly done.  */
    424       offset = 0;
    425     }
    426 
    427   /* Insns like stg, prfm, ldrsw etc. (marked with subclass F_SUBCLASS_OTHER)
    428      do not need to generate any load / store ginsns for SCFI purposes.  Next,
    429      enforce that for CFI purposes, the width of save / restore operation has
    430      to be 8 bytes or more.  That said, the address processing component may
    431      have updated the stack pointer.  At least, emit that ginsn and return.
    432      Also note, TBD_GINSN_GEN_NOT_SCFI.  */
    433   if (other_p || aarch64_get_qualifier_esize (opnd1->qualifier) < 8)
    434     return ginsn_ind;
    435 
    436   opnd_reg = ginsn_dw2_regnum (opnd1);
    437   /* Save / restore of WZR is not of interest for SCFI.  */
    438   if (ginsn_dw2_regnum_invalid_p (opnd_reg))
    439     return ginsn_ind;
    440 
    441   if (target_big_endian && opnd1->qualifier == AARCH64_OPND_QLF_S_Q)
    442     offset += 8;
    443 
    444   if (store_p)
    445     ginsn_mem = ginsn_new_store (insn_end_sym, false,
    446 				 GINSN_SRC_REG, opnd_reg,
    447 				 GINSN_DST_INDIRECT, addr_reg, offset);
    448   else
    449     ginsn_mem = ginsn_new_load (insn_end_sym, false,
    450 				GINSN_SRC_INDIRECT, addr_reg, offset,
    451 				GINSN_DST_REG, opnd_reg);
    452   ginsn_set_where (ginsn_mem);
    453 
    454   if (addr->addr.preind && addr->addr.writeback)
    455     gas_assert (!ginsn_link_next (ginsn_ind, ginsn_mem));
    456   else if (addr->addr.postind && addr->addr.writeback)
    457     gas_assert (!ginsn_link_next (ginsn_mem, ginsn_ind));
    458 
    459   /* Make note of the first instruction in the list.  */
    460   ginsn = (addr->addr.preind && addr->addr.writeback) ? ginsn_ind : ginsn_mem;
    461 
    462   return ginsn;
    463 }
    464 
    465 /* Generate ginsn for unconditional branch instructions.  */
    466 
    467 static ginsnS *
    468 aarch64_ginsn_branch_uncond (const symbolS *insn_end_sym)
    469 {
    470   ginsnS *ginsn = NULL;
    471   const symbolS *src_symbol = NULL;
    472   enum ginsn_src_type src_type = GINSN_SRC_UNKNOWN;
    473   unsigned int src_reg = 0;
    474 
    475   aarch64_inst *base = &inst.base;
    476   const aarch64_opcode *opcode = base->opcode;
    477 
    478   if (opcode->iclass == branch_imm
    479       && (inst.reloc.type == BFD_RELOC_AARCH64_CALL26
    480 	  || inst.reloc.type == BFD_RELOC_AARCH64_JUMP26))
    481     {
    482       if (inst.reloc.exp.X_add_number)
    483 	{
    484 	  /* A non-zero addend in b/bl target makes control-flow tracking
    485 	     difficult.  Skip SCFI for now.  */
    486 	  as_bad (_("SCFI: %#x op with non-zero addend to sym not supported"),
    487 		  opcode->opcode);
    488 	  return ginsn;
    489 	}
    490       /* b or bl.  */
    491       src_symbol = inst.reloc.exp.X_add_symbol;
    492       src_type = GINSN_SRC_SYMBOL;
    493     }
    494   else if (opcode->iclass == branch_reg
    495 	   && aarch64_num_of_operands (opcode) >= 1)
    496     {
    497       /* Some insns (e.g., braa, blraa etc.) may have > 1 operands.  For
    498 	 current SCFI implementation, it suffices however to simply pass
    499 	 the information about the first source.  Although, strictly speaking,
    500 	 (if reg) the source info is currently of no material use either.  */
    501       src_type = GINSN_SRC_REG;
    502       src_reg = ginsn_dw2_regnum (&base->operands[0]);
    503     }
    504   else
    505     /* Skip insns like branch imm.  */
    506     return ginsn;
    507 
    508   if (aarch64_opcode_subclass_p (opcode, F_BRANCH_CALL))
    509     {
    510       gas_assert (src_type != GINSN_SRC_UNKNOWN);
    511       ginsn = ginsn_new_call (insn_end_sym, true,
    512 			      src_type, src_reg, src_symbol);
    513     }
    514   else if (aarch64_opcode_subclass_p (opcode, F_BRANCH_RET))
    515     /* TBD_GINSN_REPRESENTATION_LIMIT.  The following function to create a
    516        GINSN_TYPE_RETURN does not allow src info ATM.  */
    517     ginsn = ginsn_new_return (insn_end_sym, true);
    518   else
    519     ginsn = ginsn_new_jump (insn_end_sym, true,
    520 			    src_type, src_reg, src_symbol);
    521 
    522   ginsn_set_where (ginsn);
    523 
    524   return ginsn;
    525 }
    526 
    527 /* Generate ginsn for conditional branch instructions.  */
    528 
    529 static ginsnS *
    530 aarch64_ginsn_branch_cond (const symbolS *insn_end_sym)
    531 {
    532   ginsnS *ginsn = NULL;
    533   const symbolS *src_symbol;
    534   enum ginsn_src_type src_type;
    535 
    536   aarch64_inst *base = &inst.base;
    537   const aarch64_opcode *opcode = base->opcode;
    538 
    539   if (inst.reloc.type == BFD_RELOC_AARCH64_BRANCH19
    540       || inst.reloc.type == BFD_RELOC_AARCH64_TSTBR14)
    541     {
    542       if (inst.reloc.exp.X_add_number)
    543 	{
    544 	  /* A non-zero addend in target makes control-flow tracking
    545 	     difficult.  Skip SCFI for now.  */
    546 	  as_bad (_("SCFI: %#x op with non-zero addend to sym not supported"),
    547 		  opcode->opcode);
    548 	  return ginsn;
    549 	}
    550 
    551       src_symbol = inst.reloc.exp.X_add_symbol;
    552       src_type = GINSN_SRC_SYMBOL;
    553 
    554       ginsn = ginsn_new_jump_cond (insn_end_sym, true, src_type, 0, src_symbol);
    555       ginsn_set_where (ginsn);
    556     }
    557 
    558   return ginsn;
    559 }
    560 
    561 /* Generate ginsn for mov instructions with reg opnd.  */
    562 
    563 static ginsnS *
    564 aarch64_ginsn_mov_reg (const symbolS *insn_end_sym)
    565 {
    566   ginsnS *ginsn = NULL;
    567   unsigned int src_reg = 0, dst_reg;
    568   aarch64_opnd_info *src, *dst;
    569   offsetT src_imm = 0;
    570   enum ginsn_src_type src_type;
    571 
    572   aarch64_inst *base = &inst.base;
    573   const aarch64_opcode *opcode = base->opcode;
    574 
    575   gas_assert (aarch64_num_of_operands (opcode) == 2);
    576 
    577   dst = &base->operands[0];
    578   src = &base->operands[1];
    579 
    580   dst_reg = ginsn_dw2_regnum (dst);
    581   src_reg = ginsn_dw2_regnum (src);
    582   src_type = GINSN_SRC_REG;
    583 
    584   /* FIXME Explicitly bar GINSN_TYPE_MOV with a GINSN_DW2_REGNUM_INVALID in src
    585      or dest at this time.  This can be removed later when SCFI machinery is
    586      more robust to deal with GINSN_DW2_REGNUM_INVALID.  */
    587   if (ginsn_dw2_regnum_invalid_p (dst_reg)
    588       || ginsn_dw2_regnum_invalid_p (src_reg))
    589     return ginsn;
    590 
    591   ginsn = ginsn_new_mov (insn_end_sym, false,
    592 			 src_type, src_reg, src_imm,
    593 			 GINSN_DST_REG, dst_reg, 0);
    594   ginsn_set_where (ginsn);
    595 
    596   return ginsn;
    597 }
    598 
    599 /* Generate ginsn for mov instructions with imm opnd.  */
    600 
    601 static ginsnS *
    602 aarch64_ginsn_mov_imm (const symbolS *insn_end_sym)
    603 {
    604   ginsnS *ginsn = NULL;
    605   unsigned int src_reg = 0, dst_reg;
    606   aarch64_opnd_info *src, *dst;
    607   offsetT src_imm = 0;
    608   enum ginsn_src_type src_type;
    609 
    610   aarch64_inst *base = &inst.base;
    611   const aarch64_opcode *opcode = base->opcode;
    612 
    613   gas_assert (aarch64_num_of_operands (opcode) == 2);
    614 
    615   dst = &base->operands[0];
    616   src = &base->operands[1];
    617 
    618   /* For some mov ops, e.g., movn, movk, or movz, there may optionally be more
    619      work than just a simple mov.  Skip handling these mov altogether and let
    620      the aarch64_ginsn_unhandled () alert if these insns affect SCFI
    621      correctness.  TBD_GINSN_GEN_NOT_SCFI.  */
    622   if (src->type == AARCH64_OPND_HALF)
    623     return ginsn;
    624 
    625   dst_reg = ginsn_dw2_regnum (dst);
    626   /* FIXME Explicitly bar GINSN_TYPE_MOV which write to WZR / XZR at this time.
    627      This can be removed later when SCFI machinery is more robust to deal with
    628      GINSN_DW2_REGNUM_INVALID.  */
    629   if (ginsn_dw2_regnum_invalid_p (dst_reg))
    630     return ginsn;
    631 
    632   if (src->type == AARCH64_OPND_IMM_MOV
    633       && aarch64_gas_internal_fixup_p () && inst.reloc.exp.X_op == O_constant)
    634     {
    635       src_imm = inst.reloc.exp.X_add_number;
    636       src_type = GINSN_SRC_IMM;
    637     }
    638   else
    639     /* Skip now and handle via aarch64_ginsn_unhandled () code path.  */
    640     return ginsn;
    641 
    642   ginsn = ginsn_new_mov (insn_end_sym, false,
    643 			 src_type, src_reg, src_imm,
    644 			 GINSN_DST_REG, dst_reg, 0);
    645   ginsn_set_where (ginsn);
    646 
    647   return ginsn;
    648 }
    649 
    650 /* Check if an instruction is whitelisted.
    651 
    652    An instruction is a candidate for whitelisting if not generating ginsn for
    653    it, does not affect SCFI correctness.
    654 
    655    TBD_GINSN_GEN_NOT_SCFI.  This function assumes GINSN_GEN_SCFI is in effect.
    656    When other ginsn_gen_mode are added, this will need fixing.  */
    657 
    658 static bool
    659 aarch64_ginsn_safe_to_skip_p (void)
    660 {
    661   bool skip_p = false;
    662   aarch64_opnd_info *opnd = NULL;
    663   unsigned int opnd_reg;
    664   int num_opnds = 0;
    665   bool dp_tag_only_p = false;
    666 
    667   aarch64_inst *base = &inst.base;
    668   const aarch64_opcode *opcode = base->opcode;
    669 
    670   /* ATM, whitelisting operations with no operands does not seem to be
    671      necessary.  In fact, whitelisting insns like ERET will be dangerous for
    672      SCFI.  So, return false now and bar any such insns from being whitelisted
    673      altogether.  */
    674   num_opnds = aarch64_num_of_operands (opcode);
    675   if (!num_opnds)
    676     return false;
    677 
    678   opnd = &base->operands[0];
    679 
    680   switch (opcode->iclass)
    681     {
    682     case ldst_regoff:
    683       /* It is not expected to have reg offset based ld/st ops to be used
    684 	 for reg save and restore operations.  Warn the user though.  */
    685       opnd_reg = ginsn_dw2_regnum (opnd);
    686       if (aarch64_scfi_callee_saved_p (opnd_reg))
    687 	{
    688 	  skip_p = true;
    689 	  as_warn ("SCFI: ignored probable save/restore op with reg offset");
    690 	}
    691       break;
    692 
    693     case dp_2src:
    694       /* irg insn needs to be explicitly whitelisted.  This is because the
    695 	 dest is Rd_SP, but irg insn affects the tag only.  To detect irg
    696 	 insn, avoid an opcode-based check, however.  */
    697       dp_tag_only_p = aarch64_opcode_subclass_p (opcode, F_DP_TAG_ONLY);
    698       if (dp_tag_only_p)
    699 	skip_p = true;
    700       break;
    701 
    702     default:
    703       break;
    704     }
    705 
    706   return skip_p;
    707 }
    708 
    709 enum aarch64_ginsn_unhandled_code
    710 {
    711   AARCH64_GINSN_UNHANDLED_NONE,
    712   AARCH64_GINSN_UNHANDLED_DEST_REG,
    713   AARCH64_GINSN_UNHANDLED_CFG,
    714   AARCH64_GINSN_UNHANDLED_STACKOP,
    715   AARCH64_GINSN_UNHANDLED_UNEXPECTED,
    716 };
    717 
    718 /* Check the input insn for its impact on the correctness of the synthesized
    719    CFI.  Returns an error code to the caller.  */
    720 
    721 static enum aarch64_ginsn_unhandled_code
    722 aarch64_ginsn_unhandled (void)
    723 {
    724   enum aarch64_ginsn_unhandled_code err = AARCH64_GINSN_UNHANDLED_NONE;
    725   aarch64_inst *base = &inst.base;
    726   const aarch64_opcode *opcode = base->opcode;
    727   aarch64_opnd_info *dest = &base->operands[0];
    728   int num_opnds = aarch64_num_of_operands (opcode);
    729   aarch64_opnd_info *addr;
    730   unsigned int dw2_regnum;
    731   unsigned int addr_reg;
    732   aarch64_opnd_info *opnd;
    733   unsigned int opnd_reg;
    734 
    735   /* All change of flow instructions (COFI) are important for SCFI.
    736      N.B. New iclasses for COFI when defined must be added here too.  */
    737   if (opcode->iclass == condbranch
    738       || opcode->iclass == compbranch
    739       || opcode->iclass == testbranch
    740       || opcode->iclass == branch_imm
    741       || opcode->iclass == branch_reg)
    742     err = AARCH64_GINSN_UNHANDLED_CFG;
    743   /* Also, any memory instructions that may involve an update to the stack
    744      pointer or save/restore of callee-saved registers must not be skipped.
    745      Note that, some iclasses cannot be used to push or pop stack because of
    746      disallowed writeback: ldst_unscaled, ldst_regoff, ldst_unpriv, ldstexcl,
    747      loadlit, ldstnapair_offs.  Except ldstnapair_offs from the afore-mentioned
    748      list, these iclasses do not seem to be amenable to being used for
    749      save/restore ops either.  */
    750   else if (opcode->iclass == ldstpair_off
    751 	   || opcode->iclass == ldstnapair_offs
    752 	   || opcode->iclass == ldstpair_indexed
    753 	   || opcode->iclass == ldst_imm9
    754 	   || opcode->iclass == ldst_imm10
    755 	   || opcode->iclass == ldst_pos)
    756     {
    757       addr = &base->operands[num_opnds - 1];
    758       addr_reg = ginsn_dw2_regnum (addr);
    759       if (addr_reg == REG_SP || addr_reg == REG_FP)
    760 	{
    761 	  /* For all skipped memory operations, check if an update to REG_SP or
    762 	     REG_FP is involved.  */
    763 	  if ((addr->addr.postind || addr->addr.preind) && addr->addr.writeback)
    764 	    err = AARCH64_GINSN_UNHANDLED_STACKOP;
    765 	  /* Also check if a save / restore of a callee-saved register has been
    766 	     missed.  */
    767 	  else if (!aarch64_opcode_subclass_p (opcode, F_SUBCLASS_OTHER))
    768 	    {
    769 	      for (int i = 0; i < num_opnds - 1; i++)
    770 		{
    771 		  opnd = &base->operands[i];
    772 		  opnd_reg = ginsn_dw2_regnum (opnd);
    773 		  if (aarch64_scfi_callee_saved_p (opnd_reg)
    774 		      && aarch64_get_qualifier_esize (opnd->qualifier) >= 8)
    775 		    {
    776 		      err = AARCH64_GINSN_UNHANDLED_STACKOP;
    777 		      break;
    778 		    }
    779 		}
    780 	    }
    781 	}
    782     }
    783   /* STR Zn are especially complicated as they do not store in the same byte
    784      order for big-endian: STR Qn stores as a 128-bit integer (MSB first),
    785      whereas STR Zn stores as a stream of bytes (LSB first).  FIXME Simply punt
    786      on the big-endian and little-endian SVE PCS case for now.  */
    787   else if (opcode->iclass == sve_misc)
    788     {
    789       opnd = &base->operands[0];
    790       addr = &base->operands[num_opnds - 1];
    791       addr_reg = ginsn_dw2_regnum (addr);
    792       opnd_reg = ginsn_dw2_regnum (opnd);
    793       /* For all skipped memory operations, check if an update to REG_SP or
    794 	 REG_FP is involved.  */
    795       if (aarch64_get_operand_class (addr->type) == AARCH64_OPND_CLASS_ADDRESS
    796 	  && (addr_reg == REG_SP || addr_reg == REG_FP)
    797 	  && (((addr->addr.postind || addr->addr.preind) && addr->addr.writeback)
    798 	      || aarch64_scfi_callee_saved_p (opnd_reg)))
    799 	err = AARCH64_GINSN_UNHANDLED_STACKOP;
    800     }
    801 
    802   /* Finally, irrespective of the iclass, check if the missed instructions are
    803      affecting REG_SP or REG_FP.  */
    804   else if (dest && (dest->type == AARCH64_OPND_Rd
    805 		    || dest->type == AARCH64_OPND_Rd_SP))
    806     {
    807       dw2_regnum = ginsn_dw2_regnum (dest);
    808 
    809       if (dw2_regnum == REG_SP || dw2_regnum == REG_FP)
    810 	err = AARCH64_GINSN_UNHANDLED_DEST_REG;
    811     }
    812 
    813   return err;
    814 }
    815 
    816 /* Generate one or more generic GAS instructions, a.k.a, ginsns for the
    817    current machine instruction.
    818 
    819    Returns the head of linked list of ginsn(s) added, if success; Returns NULL
    820    if failure.
    821 
    822    The input ginsn_gen_mode GMODE determines the set of minimal necessary
    823    ginsns necessary for correctness of any passes applicable for that mode.
    824    For supporting the GINSN_GEN_SCFI generation mode, following is the list of
    825    machine instructions that must be translated into the corresponding ginsns
    826    to ensure correctness of SCFI:
    827      - All instructions affecting the two registers that could potentially
    828        be used as the base register for CFA tracking.  For SCFI, the base
    829        register for CFA tracking is limited to REG_SP and REG_FP only.
    830      - All change of flow instructions: conditional and unconditional
    831        branches, call and return from functions.
    832      - All instructions that can potentially be a register save / restore
    833        operations.
    834      - All instructions that may update the stack pointer: pre-indexed and
    835        post-indexed stack operations with writeback.
    836 
    837    The function currently supports GINSN_GEN_SCFI ginsn generation mode only.
    838    To support other generation modes will require work on this target-specific
    839    process of creation of ginsns:
    840      - Some of such places are tagged with TBD_GINSN_GEN_NOT_SCFI to serve as
    841        possible starting points.
    842      - Also note that ginsn representation may need enhancements.  Specifically,
    843        note some TBD_GINSN_INFO_LOSS and TBD_GINSN_REPRESENTATION_LIMIT markers.
    844    */
    845 
    846 static ginsnS *
    847 aarch64_ginsn_new (const symbolS *insn_end_sym, enum ginsn_gen_mode gmode)
    848 {
    849   enum aarch64_ginsn_unhandled_code err = 0;
    850   ginsnS *ginsn = NULL;
    851   unsigned int dw2_regnum;
    852   aarch64_opnd_info *dest = NULL;
    853   aarch64_inst *base = &inst.base;
    854   const aarch64_opcode *opcode = base->opcode;
    855 
    856   /* Currently supports generation of selected ginsns, sufficient for
    857      the use-case of SCFI only.  To remove this condition will require
    858      work on this target-specific process of creation of ginsns.  Some
    859      of such places are tagged with TBD_GINSN_GEN_NOT_SCFI to serve as
    860      examples.  */
    861   if (gmode != GINSN_GEN_SCFI)
    862     return ginsn;
    863 
    864   switch (opcode->iclass)
    865     {
    866     case addsub_ext:
    867       /* TBD_GINSN_GEN_NOT_SCFI: other insns are not of interest for SCFI.  */
    868       if (aarch64_opcode_subclass_p (opcode, F_ARITH_ADD)
    869 	   || aarch64_opcode_subclass_p (opcode, F_ARITH_SUB))
    870 	ginsn = aarch64_ginsn_addsub_reg (insn_end_sym);
    871       break;
    872 
    873     case addsub_imm:
    874       if (aarch64_opcode_subclass_p (opcode, F_ARITH_MOV))
    875 	ginsn = aarch64_ginsn_mov_reg (insn_end_sym);
    876       else if (aarch64_opcode_subclass_p (opcode, F_ARITH_ADD)
    877 	       || aarch64_opcode_subclass_p (opcode, F_ARITH_SUB))
    878 	ginsn = aarch64_ginsn_addsub_imm (insn_end_sym);
    879       /* Note how addg, subg involving tags have F_SUBCLASS_OTHER flag.  These
    880 	 insns will see a GINSN_TYPE_OTHER created for them if the destination
    881 	 register is of interest via the aarch64_ginsn_unhandled ()
    882 	 codepath.  */
    883       break;
    884 
    885     case movewide:
    886       ginsn = aarch64_ginsn_mov_imm (insn_end_sym);
    887       break;
    888 
    889     case ldst_imm9:
    890     case ldst_pos:
    891       ginsn = aarch64_ginsn_ldstr (insn_end_sym);
    892       break;
    893 
    894     case ldstpair_indexed:
    895     case ldstpair_off:
    896     case ldstnapair_offs:
    897       ginsn = aarch64_ginsn_ldstp (insn_end_sym);
    898       break;
    899 
    900     case branch_imm:
    901     case branch_reg:
    902       ginsn = aarch64_ginsn_branch_uncond (insn_end_sym);
    903       break;
    904 
    905     case compbranch:
    906       /* Although cbz/cbnz has an additional operand and are functionally
    907 	 distinct from conditional branches, it is fine to use the same ginsn
    908 	 type for both from the perspective of SCFI.  */
    909     case testbranch:
    910     case condbranch:
    911       ginsn = aarch64_ginsn_branch_cond (insn_end_sym);
    912       break;
    913 
    914     default:
    915       /* TBD_GINSN_GEN_NOT_SCFI: Skip all other opcodes uninteresting for
    916 	 GINSN_GEN_SCFI mode.  */
    917       break;
    918     }
    919 
    920   if (!ginsn && !aarch64_ginsn_safe_to_skip_p ())
    921     {
    922       /* For all unhandled insns, check that they no not impact SCFI
    923 	 correctness.  */
    924       err = aarch64_ginsn_unhandled ();
    925       switch (err)
    926 	{
    927 	case AARCH64_GINSN_UNHANDLED_NONE:
    928 	  break;
    929 	case AARCH64_GINSN_UNHANDLED_DEST_REG:
    930 	  /* Not all writes to REG_FP are harmful in context of SCFI.  Simply
    931 	     generate a GINSN_TYPE_OTHER with destination set to the
    932 	     appropriate register.  The SCFI machinery will bail out if this
    933 	     ginsn affects SCFI correctness.  */
    934 	  dest = &base->operands[0];
    935 	  dw2_regnum = ginsn_dw2_regnum (dest);
    936 	  /* Sanity check.  */
    937 	  gas_assert (!ginsn_dw2_regnum_invalid_p (dw2_regnum));
    938 	  ginsn = ginsn_new_other (insn_end_sym, true,
    939 				   GINSN_SRC_IMM, 0,
    940 				   GINSN_SRC_IMM, 0,
    941 				   GINSN_DST_REG, dw2_regnum);
    942 	  ginsn_set_where (ginsn);
    943 	  break;
    944 	case AARCH64_GINSN_UNHANDLED_CFG:
    945 	case AARCH64_GINSN_UNHANDLED_STACKOP:
    946 	  as_bad (_("SCFI: unhandled op %#x may cause incorrect CFI"),
    947 		  opcode->opcode);
    948 	  break;
    949 	case AARCH64_GINSN_UNHANDLED_UNEXPECTED:
    950 	  as_bad (_("SCFI: unexpected op %#x may cause incorrect CFI"),
    951 		  opcode->opcode);
    952 	  break;
    953 	default:
    954 	  abort ();
    955 	  break;
    956 	}
    957     }
    958 
    959   return ginsn;
    960 }
    961 
    962 #endif /* OBJ_ELF.  */
    963 
    964