Home | History | Annotate | Line # | Download | only in config
tc-kvx.c revision 1.1.1.1.2.2
      1  1.1.1.1.2.2  perseant /* tc-kvx.c -- Assemble for the KVX ISA
      2  1.1.1.1.2.2  perseant 
      3  1.1.1.1.2.2  perseant    Copyright (C) 2009-2024 Free Software Foundation, Inc.
      4  1.1.1.1.2.2  perseant    Contributed by Kalray SA.
      5  1.1.1.1.2.2  perseant 
      6  1.1.1.1.2.2  perseant    This file is part of GAS.
      7  1.1.1.1.2.2  perseant 
      8  1.1.1.1.2.2  perseant    GAS is free software; you can redistribute it and/or modify
      9  1.1.1.1.2.2  perseant    it under the terms of the GNU General Public License as published by
     10  1.1.1.1.2.2  perseant    the Free Software Foundation; either version 3 of the license, or
     11  1.1.1.1.2.2  perseant    (at your option) any later version.
     12  1.1.1.1.2.2  perseant 
     13  1.1.1.1.2.2  perseant    GAS is distributed in the hope that it will be useful,
     14  1.1.1.1.2.2  perseant    but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  1.1.1.1.2.2  perseant    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  1.1.1.1.2.2  perseant    GNU General Public License for more details.
     17  1.1.1.1.2.2  perseant 
     18  1.1.1.1.2.2  perseant    You should have received a copy of the GNU General Public License
     19  1.1.1.1.2.2  perseant    along with this program; see the file COPYING3. If not,
     20  1.1.1.1.2.2  perseant    see <http://www.gnu.org/licenses/>.  */
     21  1.1.1.1.2.2  perseant 
     22  1.1.1.1.2.2  perseant #include "as.h"
     23  1.1.1.1.2.2  perseant #include "obstack.h"
     24  1.1.1.1.2.2  perseant #include "subsegs.h"
     25  1.1.1.1.2.2  perseant #include "tc-kvx.h"
     26  1.1.1.1.2.2  perseant #include "libiberty.h"
     27  1.1.1.1.2.2  perseant 
     28  1.1.1.1.2.2  perseant #include <assert.h>
     29  1.1.1.1.2.2  perseant #include <stdio.h>
     30  1.1.1.1.2.2  perseant #include <stdint.h>
     31  1.1.1.1.2.2  perseant #include <string.h>
     32  1.1.1.1.2.2  perseant #include <ctype.h>
     33  1.1.1.1.2.2  perseant 
     34  1.1.1.1.2.2  perseant #ifdef OBJ_ELF
     35  1.1.1.1.2.2  perseant #include "elf/kvx.h"
     36  1.1.1.1.2.2  perseant #include "dwarf2dbg.h"
     37  1.1.1.1.2.2  perseant #include "dw2gencfi.h"
     38  1.1.1.1.2.2  perseant #endif
     39  1.1.1.1.2.2  perseant 
     40  1.1.1.1.2.2  perseant #define D(args...) do { if(debug) fprintf(args); } while(0)
     41  1.1.1.1.2.2  perseant 
     42  1.1.1.1.2.2  perseant static void supported_cores (char buf[], size_t buflen);
     43  1.1.1.1.2.2  perseant 
     44  1.1.1.1.2.2  perseant #define NELEMS(a) ((int) (sizeof (a)/sizeof ((a)[0])))
     45  1.1.1.1.2.2  perseant 
     46  1.1.1.1.2.2  perseant #define STREQ(x,y) !strcmp(((x) ? (x) : ""), ((y) ? (y) : ""))
     47  1.1.1.1.2.2  perseant #define STRNEQ(x,y,n) !strncmp(((x) ? (x) : ""), ((y) ? (y) : ""),(n))
     48  1.1.1.1.2.2  perseant 
     49  1.1.1.1.2.2  perseant /* The PARALLEL_BIT is set to 0 when an instruction is the last of a bundle. */
     50  1.1.1.1.2.2  perseant #define PARALLEL_BIT (1u << 31)
     51  1.1.1.1.2.2  perseant 
     52  1.1.1.1.2.2  perseant /*TB begin*/
     53  1.1.1.1.2.2  perseant int size_type_function = 1;
     54  1.1.1.1.2.2  perseant /*TB end */
     55  1.1.1.1.2.2  perseant 
     56  1.1.1.1.2.2  perseant struct kvx_as_env env = {
     57  1.1.1.1.2.2  perseant   .params = {
     58  1.1.1.1.2.2  perseant     .abi = ELF_KVX_ABI_UNDEF,
     59  1.1.1.1.2.2  perseant     .osabi = ELFOSABI_NONE,
     60  1.1.1.1.2.2  perseant     .core = -1,
     61  1.1.1.1.2.2  perseant     .core_set = 0,
     62  1.1.1.1.2.2  perseant     .abi_set = 0,
     63  1.1.1.1.2.2  perseant     .osabi_set = 0,
     64  1.1.1.1.2.2  perseant     .pic_flags = 0,
     65  1.1.1.1.2.2  perseant     .arch_size = 64
     66  1.1.1.1.2.2  perseant   },
     67  1.1.1.1.2.2  perseant   .opts = {
     68  1.1.1.1.2.2  perseant     .march = NULL,
     69  1.1.1.1.2.2  perseant     .check_resource_usage = 1,
     70  1.1.1.1.2.2  perseant     .generate_illegal_code = 0,
     71  1.1.1.1.2.2  perseant     .dump_table = 0,
     72  1.1.1.1.2.2  perseant     .dump_insn = 0,
     73  1.1.1.1.2.2  perseant     .diagnostics = 1,
     74  1.1.1.1.2.2  perseant     .more = 1,
     75  1.1.1.1.2.2  perseant     .allow_all_sfr = 0
     76  1.1.1.1.2.2  perseant   }
     77  1.1.1.1.2.2  perseant };
     78  1.1.1.1.2.2  perseant 
     79  1.1.1.1.2.2  perseant /* This string should contain position in string where error occured. */
     80  1.1.1.1.2.2  perseant 
     81  1.1.1.1.2.2  perseant /* Default kvx_registers array. */
     82  1.1.1.1.2.2  perseant const struct kvx_Register *kvx_registers = NULL;
     83  1.1.1.1.2.2  perseant /* Default kvx_modifiers array. */
     84  1.1.1.1.2.2  perseant const char ***kvx_modifiers = NULL;
     85  1.1.1.1.2.2  perseant /* Default kvx_regfiles array. */
     86  1.1.1.1.2.2  perseant const int *kvx_regfiles = NULL;
     87  1.1.1.1.2.2  perseant /* Default values used if no assume directive is given */
     88  1.1.1.1.2.2  perseant const struct kvx_core_info *kvx_core_info = NULL;
     89  1.1.1.1.2.2  perseant 
     90  1.1.1.1.2.2  perseant /***********************************************/
     91  1.1.1.1.2.2  perseant /*    Generic Globals for GAS                  */
     92  1.1.1.1.2.2  perseant /***********************************************/
     93  1.1.1.1.2.2  perseant 
     94  1.1.1.1.2.2  perseant const char comment_chars[]        = "#";
     95  1.1.1.1.2.2  perseant const char line_comment_chars[]   = "#";
     96  1.1.1.1.2.2  perseant const char line_separator_chars[] = ";";
     97  1.1.1.1.2.2  perseant const char EXP_CHARS[]            = "eE";
     98  1.1.1.1.2.2  perseant const char FLT_CHARS[]            = "dD";
     99  1.1.1.1.2.2  perseant const int md_short_jump_size      = 0;
    100  1.1.1.1.2.2  perseant const int md_long_jump_size       = 0;
    101  1.1.1.1.2.2  perseant 
    102  1.1.1.1.2.2  perseant /***********************************************/
    103  1.1.1.1.2.2  perseant /*           Local Types                       */
    104  1.1.1.1.2.2  perseant /***********************************************/
    105  1.1.1.1.2.2  perseant 
    106  1.1.1.1.2.2  perseant /* a fix up record                       */
    107  1.1.1.1.2.2  perseant 
    108  1.1.1.1.2.2  perseant struct kvx_fixup
    109  1.1.1.1.2.2  perseant {
    110  1.1.1.1.2.2  perseant   /* The expression used.  */
    111  1.1.1.1.2.2  perseant   expressionS exp;
    112  1.1.1.1.2.2  perseant   /* The place in the frag where this goes.  */
    113  1.1.1.1.2.2  perseant   int where;
    114  1.1.1.1.2.2  perseant   /* The relocation.  */
    115  1.1.1.1.2.2  perseant   bfd_reloc_code_real_type reloc;
    116  1.1.1.1.2.2  perseant };
    117  1.1.1.1.2.2  perseant 
    118  1.1.1.1.2.2  perseant /* a single assembled instruction record */
    119  1.1.1.1.2.2  perseant /* may include immediate extension words  */
    120  1.1.1.1.2.2  perseant struct kvxinsn
    121  1.1.1.1.2.2  perseant {
    122  1.1.1.1.2.2  perseant   /* written out?  */
    123  1.1.1.1.2.2  perseant   int written;
    124  1.1.1.1.2.2  perseant   /* Opcode table entry for this insn */
    125  1.1.1.1.2.2  perseant   const struct kvxopc *opdef;
    126  1.1.1.1.2.2  perseant   /* length of instruction in words (1 or 2) */
    127  1.1.1.1.2.2  perseant   int len;
    128  1.1.1.1.2.2  perseant   /* insn is extended */
    129  1.1.1.1.2.2  perseant   int immx0;
    130  1.1.1.1.2.2  perseant   /* insn has two immx */
    131  1.1.1.1.2.2  perseant   int immx1;
    132  1.1.1.1.2.2  perseant   /* order to stabilize sort */
    133  1.1.1.1.2.2  perseant   int order;
    134  1.1.1.1.2.2  perseant   /* instruction words */
    135  1.1.1.1.2.2  perseant   uint32_t words[KVXMAXBUNDLEWORDS];
    136  1.1.1.1.2.2  perseant   /* the number of fixups [0,2] */
    137  1.1.1.1.2.2  perseant   int nfixups;
    138  1.1.1.1.2.2  perseant   /* the actual fixups */
    139  1.1.1.1.2.2  perseant   struct kvx_fixup fixup[2];
    140  1.1.1.1.2.2  perseant };
    141  1.1.1.1.2.2  perseant 
    142  1.1.1.1.2.2  perseant typedef void (*print_insn_t) (struct kvxopc * op);
    143  1.1.1.1.2.2  perseant static print_insn_t print_insn = NULL;
    144  1.1.1.1.2.2  perseant 
    145  1.1.1.1.2.2  perseant /* Set to TRUE when we assemble instructions.  */
    146  1.1.1.1.2.2  perseant static bool assembling_insn = false;
    147  1.1.1.1.2.2  perseant 
    148  1.1.1.1.2.2  perseant #define NOIMMX -1
    149  1.1.1.1.2.2  perseant 
    150  1.1.1.1.2.2  perseant /* Was KVXMAXBUNDLEISSUE, changed because of NOPs */
    151  1.1.1.1.2.2  perseant static struct kvxinsn insbuf[KVXMAXBUNDLEWORDS];
    152  1.1.1.1.2.2  perseant static int insncnt = 0;
    153  1.1.1.1.2.2  perseant static struct kvxinsn immxbuf[KVXMAXBUNDLEWORDS];
    154  1.1.1.1.2.2  perseant static int immxcnt = 0;
    155  1.1.1.1.2.2  perseant 
    156  1.1.1.1.2.2  perseant static void
    157  1.1.1.1.2.2  perseant incr_immxcnt (void)
    158  1.1.1.1.2.2  perseant {
    159  1.1.1.1.2.2  perseant   immxcnt++;
    160  1.1.1.1.2.2  perseant   if (immxcnt >= KVXMAXBUNDLEWORDS)
    161  1.1.1.1.2.2  perseant     as_bad ("Max immx number exceeded: %d", immxcnt);
    162  1.1.1.1.2.2  perseant }
    163  1.1.1.1.2.2  perseant 
    164  1.1.1.1.2.2  perseant static void set_byte_counter (asection * sec, int value);
    165  1.1.1.1.2.2  perseant static void
    166  1.1.1.1.2.2  perseant set_byte_counter (asection * sec, int value)
    167  1.1.1.1.2.2  perseant {
    168  1.1.1.1.2.2  perseant   sec->target_index = value;
    169  1.1.1.1.2.2  perseant }
    170  1.1.1.1.2.2  perseant 
    171  1.1.1.1.2.2  perseant static int get_byte_counter (asection * sec);
    172  1.1.1.1.2.2  perseant int
    173  1.1.1.1.2.2  perseant get_byte_counter (asection * sec)
    174  1.1.1.1.2.2  perseant {
    175  1.1.1.1.2.2  perseant   return sec->target_index;
    176  1.1.1.1.2.2  perseant }
    177  1.1.1.1.2.2  perseant 
    178  1.1.1.1.2.2  perseant const char *
    179  1.1.1.1.2.2  perseant kvx_target_format (void)
    180  1.1.1.1.2.2  perseant {
    181  1.1.1.1.2.2  perseant   return env.params.arch_size == 64 ? "elf64-kvx" : "elf32-kvx";
    182  1.1.1.1.2.2  perseant }
    183  1.1.1.1.2.2  perseant 
    184  1.1.1.1.2.2  perseant /****************************************************/
    185  1.1.1.1.2.2  perseant /*  ASSEMBLER Pseudo-ops.  Some of this just        */
    186  1.1.1.1.2.2  perseant /*  extends the default definitions                 */
    187  1.1.1.1.2.2  perseant /*  others are KVX specific                          */
    188  1.1.1.1.2.2  perseant /****************************************************/
    189  1.1.1.1.2.2  perseant 
    190  1.1.1.1.2.2  perseant static void kvx_check_resources (int);
    191  1.1.1.1.2.2  perseant static void kvx_proc (int start);
    192  1.1.1.1.2.2  perseant static void kvx_endp (int start);
    193  1.1.1.1.2.2  perseant static void kvx_type (int start);
    194  1.1.1.1.2.2  perseant 
    195  1.1.1.1.2.2  perseant const pseudo_typeS md_pseudo_table[] = {
    196  1.1.1.1.2.2  perseant   /* override default 2-bytes */
    197  1.1.1.1.2.2  perseant   { "word",             cons,                  4 },
    198  1.1.1.1.2.2  perseant 
    199  1.1.1.1.2.2  perseant   /* KVX specific */
    200  1.1.1.1.2.2  perseant   { "dword",            cons,                  8 },
    201  1.1.1.1.2.2  perseant 
    202  1.1.1.1.2.2  perseant   /* Override align directives to have a boundary as argument (and not the
    203  1.1.1.1.2.2  perseant      power of two as in p2align) */
    204  1.1.1.1.2.2  perseant   { "align",            s_align_bytes,         0 },
    205  1.1.1.1.2.2  perseant 
    206  1.1.1.1.2.2  perseant   { "checkresources",   kvx_check_resources,   1 },
    207  1.1.1.1.2.2  perseant   { "nocheckresources", kvx_check_resources,   0 },
    208  1.1.1.1.2.2  perseant 
    209  1.1.1.1.2.2  perseant   { "proc",             kvx_proc,              1 },
    210  1.1.1.1.2.2  perseant   { "endp",             kvx_endp,              0 },
    211  1.1.1.1.2.2  perseant 
    212  1.1.1.1.2.2  perseant   { "type",             kvx_type,              0 },
    213  1.1.1.1.2.2  perseant 
    214  1.1.1.1.2.2  perseant #ifdef OBJ_ELF
    215  1.1.1.1.2.2  perseant   { "file",             dwarf2_directive_file, 0 },
    216  1.1.1.1.2.2  perseant   { "loc",              dwarf2_directive_loc,  0 },
    217  1.1.1.1.2.2  perseant #endif
    218  1.1.1.1.2.2  perseant   { NULL,               0,                     0 }
    219  1.1.1.1.2.2  perseant };
    220  1.1.1.1.2.2  perseant 
    221  1.1.1.1.2.2  perseant 
    222  1.1.1.1.2.2  perseant static int inside_bundle = 0;
    223  1.1.1.1.2.2  perseant 
    224  1.1.1.1.2.2  perseant /* Stores the labels inside bundles (typically debug labels) that need
    225  1.1.1.1.2.2  perseant    to be postponed to the next bundle. */
    226  1.1.1.1.2.2  perseant struct label_fix
    227  1.1.1.1.2.2  perseant {
    228  1.1.1.1.2.2  perseant   struct label_fix *next;
    229  1.1.1.1.2.2  perseant   symbolS *sym;
    230  1.1.1.1.2.2  perseant } *label_fixes = 0;
    231  1.1.1.1.2.2  perseant 
    232  1.1.1.1.2.2  perseant /*****************************************************/
    233  1.1.1.1.2.2  perseant /*   OPTIONS PROCESSING                              */
    234  1.1.1.1.2.2  perseant /*****************************************************/
    235  1.1.1.1.2.2  perseant 
    236  1.1.1.1.2.2  perseant const char *md_shortopts = "hV";	/* catted to std short options */
    237  1.1.1.1.2.2  perseant 
    238  1.1.1.1.2.2  perseant /* added to std long options */
    239  1.1.1.1.2.2  perseant 
    240  1.1.1.1.2.2  perseant #define OPTION_HEXFILE               (OPTION_MD_BASE + 0)
    241  1.1.1.1.2.2  perseant #define OPTION_MARCH                 (OPTION_MD_BASE + 4)
    242  1.1.1.1.2.2  perseant #define OPTION_CHECK_RESOURCES       (OPTION_MD_BASE + 5)
    243  1.1.1.1.2.2  perseant #define OPTION_NO_CHECK_RESOURCES    (OPTION_MD_BASE + 6)
    244  1.1.1.1.2.2  perseant #define OPTION_GENERATE_ILLEGAL_CODE (OPTION_MD_BASE + 7)
    245  1.1.1.1.2.2  perseant #define OPTION_DUMP_TABLE            (OPTION_MD_BASE + 8)
    246  1.1.1.1.2.2  perseant #define OPTION_PIC                   (OPTION_MD_BASE + 9)
    247  1.1.1.1.2.2  perseant #define OPTION_BIGPIC                (OPTION_MD_BASE + 10)
    248  1.1.1.1.2.2  perseant #define OPTION_NOPIC                 (OPTION_MD_BASE + 12)
    249  1.1.1.1.2.2  perseant #define OPTION_32                    (OPTION_MD_BASE + 13)
    250  1.1.1.1.2.2  perseant #define OPTION_DUMPINSN              (OPTION_MD_BASE + 15)
    251  1.1.1.1.2.2  perseant #define OPTION_ALL_SFR               (OPTION_MD_BASE + 16)
    252  1.1.1.1.2.2  perseant #define OPTION_DIAGNOSTICS           (OPTION_MD_BASE + 17)
    253  1.1.1.1.2.2  perseant #define OPTION_NO_DIAGNOSTICS        (OPTION_MD_BASE + 18)
    254  1.1.1.1.2.2  perseant #define OPTION_MORE                  (OPTION_MD_BASE + 19)
    255  1.1.1.1.2.2  perseant #define OPTION_NO_MORE               (OPTION_MD_BASE + 20)
    256  1.1.1.1.2.2  perseant 
    257  1.1.1.1.2.2  perseant struct option md_longopts[] = {
    258  1.1.1.1.2.2  perseant   { "march",                 required_argument, NULL, OPTION_MARCH                 },
    259  1.1.1.1.2.2  perseant   { "check-resources",       no_argument,       NULL, OPTION_CHECK_RESOURCES       },
    260  1.1.1.1.2.2  perseant   { "no-check-resources",    no_argument,       NULL, OPTION_NO_CHECK_RESOURCES    },
    261  1.1.1.1.2.2  perseant   { "generate-illegal-code", no_argument,       NULL, OPTION_GENERATE_ILLEGAL_CODE },
    262  1.1.1.1.2.2  perseant   { "dump-table",            no_argument,       NULL, OPTION_DUMP_TABLE            },
    263  1.1.1.1.2.2  perseant   { "mpic",                  no_argument,       NULL, OPTION_PIC                   },
    264  1.1.1.1.2.2  perseant   { "mPIC",                  no_argument,       NULL, OPTION_BIGPIC                },
    265  1.1.1.1.2.2  perseant   { "mnopic",                no_argument,       NULL, OPTION_NOPIC                 },
    266  1.1.1.1.2.2  perseant   { "m32",                   no_argument,       NULL, OPTION_32                    },
    267  1.1.1.1.2.2  perseant   { "dump-insn",             no_argument,       NULL, OPTION_DUMPINSN              },
    268  1.1.1.1.2.2  perseant   { "all-sfr",               no_argument,       NULL, OPTION_ALL_SFR               },
    269  1.1.1.1.2.2  perseant   { "diagnostics",           no_argument,       NULL, OPTION_DIAGNOSTICS           },
    270  1.1.1.1.2.2  perseant   { "no-diagnostics",        no_argument,       NULL, OPTION_NO_DIAGNOSTICS        },
    271  1.1.1.1.2.2  perseant   { "more",                  no_argument,       NULL, OPTION_MORE                  },
    272  1.1.1.1.2.2  perseant   { "no-more",               no_argument,       NULL, OPTION_NO_MORE               },
    273  1.1.1.1.2.2  perseant   { NULL,                    no_argument,       NULL, 0                            }
    274  1.1.1.1.2.2  perseant };
    275  1.1.1.1.2.2  perseant 
    276  1.1.1.1.2.2  perseant size_t md_longopts_size = sizeof (md_longopts);
    277  1.1.1.1.2.2  perseant 
    278  1.1.1.1.2.2  perseant int
    279  1.1.1.1.2.2  perseant md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
    280  1.1.1.1.2.2  perseant {
    281  1.1.1.1.2.2  perseant   int find_core = 0;
    282  1.1.1.1.2.2  perseant 
    283  1.1.1.1.2.2  perseant   switch (c)
    284  1.1.1.1.2.2  perseant     {
    285  1.1.1.1.2.2  perseant     case 'h':
    286  1.1.1.1.2.2  perseant       md_show_usage (stdout);
    287  1.1.1.1.2.2  perseant       exit (EXIT_SUCCESS);
    288  1.1.1.1.2.2  perseant       break;
    289  1.1.1.1.2.2  perseant 
    290  1.1.1.1.2.2  perseant       /* -V: SVR4 argument to print version ID.  */
    291  1.1.1.1.2.2  perseant     case 'V':
    292  1.1.1.1.2.2  perseant       print_version_id ();
    293  1.1.1.1.2.2  perseant       exit (EXIT_SUCCESS);
    294  1.1.1.1.2.2  perseant       break;
    295  1.1.1.1.2.2  perseant     case OPTION_MARCH:
    296  1.1.1.1.2.2  perseant       env.opts.march = strdup (arg);
    297  1.1.1.1.2.2  perseant       for (int i = 0; i < KVXNUMCORES && !find_core; ++i)
    298  1.1.1.1.2.2  perseant 	    if (!strcasecmp (env.opts.march, kvx_core_info_table[i]->name))
    299  1.1.1.1.2.2  perseant 	      {
    300  1.1.1.1.2.2  perseant 		kvx_core_info = kvx_core_info_table[i];
    301  1.1.1.1.2.2  perseant 		kvx_registers = kvx_registers_table[i];
    302  1.1.1.1.2.2  perseant 		kvx_modifiers = kvx_modifiers_table[i];
    303  1.1.1.1.2.2  perseant 		kvx_regfiles = kvx_regfiles_table[i];
    304  1.1.1.1.2.2  perseant 
    305  1.1.1.1.2.2  perseant 		find_core = 1;
    306  1.1.1.1.2.2  perseant 		break;
    307  1.1.1.1.2.2  perseant 	      }
    308  1.1.1.1.2.2  perseant       if (!find_core)
    309  1.1.1.1.2.2  perseant 	{
    310  1.1.1.1.2.2  perseant 	  char buf[100];
    311  1.1.1.1.2.2  perseant 	  supported_cores (buf, sizeof (buf));
    312  1.1.1.1.2.2  perseant 	  as_fatal ("Specified arch not supported [%s]", buf);
    313  1.1.1.1.2.2  perseant 	}
    314  1.1.1.1.2.2  perseant       break;
    315  1.1.1.1.2.2  perseant     case OPTION_CHECK_RESOURCES:
    316  1.1.1.1.2.2  perseant       env.opts.check_resource_usage = 1;
    317  1.1.1.1.2.2  perseant       break;
    318  1.1.1.1.2.2  perseant     case OPTION_NO_CHECK_RESOURCES:
    319  1.1.1.1.2.2  perseant       env.opts.check_resource_usage = 0;
    320  1.1.1.1.2.2  perseant       break;
    321  1.1.1.1.2.2  perseant     case OPTION_GENERATE_ILLEGAL_CODE:
    322  1.1.1.1.2.2  perseant       env.opts.generate_illegal_code = 1;
    323  1.1.1.1.2.2  perseant       break;
    324  1.1.1.1.2.2  perseant     case OPTION_DUMP_TABLE:
    325  1.1.1.1.2.2  perseant       env.opts.dump_table = 1;
    326  1.1.1.1.2.2  perseant       break;
    327  1.1.1.1.2.2  perseant     case OPTION_DUMPINSN:
    328  1.1.1.1.2.2  perseant       env.opts.dump_insn = 1;
    329  1.1.1.1.2.2  perseant       break;
    330  1.1.1.1.2.2  perseant     case OPTION_ALL_SFR:
    331  1.1.1.1.2.2  perseant       env.opts.allow_all_sfr = 1;
    332  1.1.1.1.2.2  perseant       break;
    333  1.1.1.1.2.2  perseant     case OPTION_DIAGNOSTICS:
    334  1.1.1.1.2.2  perseant       env.opts.diagnostics = 1;
    335  1.1.1.1.2.2  perseant       break;
    336  1.1.1.1.2.2  perseant     case OPTION_NO_DIAGNOSTICS:
    337  1.1.1.1.2.2  perseant       env.opts.diagnostics = 0;
    338  1.1.1.1.2.2  perseant       break;
    339  1.1.1.1.2.2  perseant     case OPTION_MORE:
    340  1.1.1.1.2.2  perseant       env.opts.more = 1;
    341  1.1.1.1.2.2  perseant       break;
    342  1.1.1.1.2.2  perseant     case OPTION_NO_MORE:
    343  1.1.1.1.2.2  perseant       env.opts.more = 0;
    344  1.1.1.1.2.2  perseant       break;
    345  1.1.1.1.2.2  perseant     case OPTION_PIC:
    346  1.1.1.1.2.2  perseant       /* fallthrough, for now the same on KVX */
    347  1.1.1.1.2.2  perseant     case OPTION_BIGPIC:
    348  1.1.1.1.2.2  perseant       env.params.pic_flags |= ELF_KVX_ABI_PIC_BIT;
    349  1.1.1.1.2.2  perseant       break;
    350  1.1.1.1.2.2  perseant     case OPTION_NOPIC:
    351  1.1.1.1.2.2  perseant       env.params.pic_flags &= ~(ELF_KVX_ABI_PIC_BIT);
    352  1.1.1.1.2.2  perseant       break;
    353  1.1.1.1.2.2  perseant     case OPTION_32:
    354  1.1.1.1.2.2  perseant       env.params.arch_size = 32;
    355  1.1.1.1.2.2  perseant       break;
    356  1.1.1.1.2.2  perseant 
    357  1.1.1.1.2.2  perseant     default:
    358  1.1.1.1.2.2  perseant       return 0;
    359  1.1.1.1.2.2  perseant     }
    360  1.1.1.1.2.2  perseant   return 1;
    361  1.1.1.1.2.2  perseant }
    362  1.1.1.1.2.2  perseant 
    363  1.1.1.1.2.2  perseant void
    364  1.1.1.1.2.2  perseant md_show_usage (FILE * stream)
    365  1.1.1.1.2.2  perseant {
    366  1.1.1.1.2.2  perseant   char buf[100];
    367  1.1.1.1.2.2  perseant   supported_cores (buf, sizeof (buf));
    368  1.1.1.1.2.2  perseant 
    369  1.1.1.1.2.2  perseant   fprintf (stream, "\n"
    370  1.1.1.1.2.2  perseant "KVX specific options:\n\n"
    371  1.1.1.1.2.2  perseant "  --check-resources\t Perform minimal resource checking\n"
    372  1.1.1.1.2.2  perseant "  --march [%s]\t Select architecture\n"
    373  1.1.1.1.2.2  perseant "  -V \t\t\t Print assembler version number\n\n"
    374  1.1.1.1.2.2  perseant "  The options -M, --mri and -f are not supported in this assembler.\n", buf);
    375  1.1.1.1.2.2  perseant }
    376  1.1.1.1.2.2  perseant 
    377  1.1.1.1.2.2  perseant /**************************************************/
    378  1.1.1.1.2.2  perseant /*              UTILITIES                         */
    379  1.1.1.1.2.2  perseant /**************************************************/
    380  1.1.1.1.2.2  perseant 
    381  1.1.1.1.2.2  perseant /*
    382  1.1.1.1.2.2  perseant  * Read a value from to the object file
    383  1.1.1.1.2.2  perseant  */
    384  1.1.1.1.2.2  perseant 
    385  1.1.1.1.2.2  perseant static valueT md_chars_to_number (char *buf, int n);
    386  1.1.1.1.2.2  perseant valueT
    387  1.1.1.1.2.2  perseant md_chars_to_number (char *buf, int n)
    388  1.1.1.1.2.2  perseant {
    389  1.1.1.1.2.2  perseant   valueT val = 0;
    390  1.1.1.1.2.2  perseant 
    391  1.1.1.1.2.2  perseant   if (n > (int) sizeof (val) || n <= 0)
    392  1.1.1.1.2.2  perseant     abort ();
    393  1.1.1.1.2.2  perseant 
    394  1.1.1.1.2.2  perseant   while (n--)
    395  1.1.1.1.2.2  perseant     {
    396  1.1.1.1.2.2  perseant       val <<= 8;
    397  1.1.1.1.2.2  perseant       val |= (buf[n] & 0xff);
    398  1.1.1.1.2.2  perseant     }
    399  1.1.1.1.2.2  perseant 
    400  1.1.1.1.2.2  perseant   return val;
    401  1.1.1.1.2.2  perseant }
    402  1.1.1.1.2.2  perseant 
    403  1.1.1.1.2.2  perseant /* Returns the corresponding pseudo function matching SYM and to be
    404  1.1.1.1.2.2  perseant    used for data section */
    405  1.1.1.1.2.2  perseant static struct pseudo_func *
    406  1.1.1.1.2.2  perseant kvx_get_pseudo_func_data_scn (symbolS * sym)
    407  1.1.1.1.2.2  perseant {
    408  1.1.1.1.2.2  perseant   for (int i = 0; i < kvx_core_info->nb_pseudo_funcs; i++)
    409  1.1.1.1.2.2  perseant     if (sym == kvx_core_info->pseudo_funcs[i].sym
    410  1.1.1.1.2.2  perseant 	&& kvx_core_info->pseudo_funcs[i].pseudo_relocs.single != BFD_RELOC_UNUSED)
    411  1.1.1.1.2.2  perseant 	return &kvx_core_info->pseudo_funcs[i];
    412  1.1.1.1.2.2  perseant   return NULL;
    413  1.1.1.1.2.2  perseant }
    414  1.1.1.1.2.2  perseant 
    415  1.1.1.1.2.2  perseant /* Returns the corresponding pseudo function matching SYM and operand
    416  1.1.1.1.2.2  perseant    format OPND */
    417  1.1.1.1.2.2  perseant static struct pseudo_func *
    418  1.1.1.1.2.2  perseant kvx_get_pseudo_func2 (symbolS *sym, struct kvx_operand * opnd)
    419  1.1.1.1.2.2  perseant {
    420  1.1.1.1.2.2  perseant   for (int i = 0; i < kvx_core_info->nb_pseudo_funcs; i++)
    421  1.1.1.1.2.2  perseant     if (sym == kvx_core_info->pseudo_funcs[i].sym)
    422  1.1.1.1.2.2  perseant       for (int relidx = 0; relidx < opnd->reloc_nb; relidx++)
    423  1.1.1.1.2.2  perseant 	if (opnd->relocs[relidx] == kvx_core_info->pseudo_funcs[i].pseudo_relocs.kreloc
    424  1.1.1.1.2.2  perseant 	    && (env.params.arch_size == (int) kvx_core_info->pseudo_funcs[i].pseudo_relocs.avail_modes
    425  1.1.1.1.2.2  perseant 	      || kvx_core_info->pseudo_funcs[i].pseudo_relocs.avail_modes == PSEUDO_ALL))
    426  1.1.1.1.2.2  perseant 	  return &kvx_core_info->pseudo_funcs[i];
    427  1.1.1.1.2.2  perseant 
    428  1.1.1.1.2.2  perseant   return NULL;
    429  1.1.1.1.2.2  perseant }
    430  1.1.1.1.2.2  perseant 
    431  1.1.1.1.2.2  perseant static void
    432  1.1.1.1.2.2  perseant supported_cores (char buf[], size_t buflen)
    433  1.1.1.1.2.2  perseant {
    434  1.1.1.1.2.2  perseant   buf[0] = '\0';
    435  1.1.1.1.2.2  perseant   for (int i = 0; i < KVXNUMCORES; i++)
    436  1.1.1.1.2.2  perseant     {
    437  1.1.1.1.2.2  perseant       if (buf[0] == '\0')
    438  1.1.1.1.2.2  perseant 	strcpy (buf, kvx_core_info_table[i]->name);
    439  1.1.1.1.2.2  perseant       else
    440  1.1.1.1.2.2  perseant 	if ((strlen (buf) + 1 + strlen (kvx_core_info_table[i]->name) + 1) < buflen)
    441  1.1.1.1.2.2  perseant 	  {
    442  1.1.1.1.2.2  perseant 	    strcat (buf, "|");
    443  1.1.1.1.2.2  perseant 	    strcat (buf, kvx_core_info_table[i]->name);
    444  1.1.1.1.2.2  perseant 	  }
    445  1.1.1.1.2.2  perseant     }
    446  1.1.1.1.2.2  perseant }
    447  1.1.1.1.2.2  perseant 
    448  1.1.1.1.2.2  perseant /***************************************************/
    449  1.1.1.1.2.2  perseant /*   ASSEMBLE AN INSTRUCTION                       */
    450  1.1.1.1.2.2  perseant /***************************************************/
    451  1.1.1.1.2.2  perseant 
    452  1.1.1.1.2.2  perseant /*
    453  1.1.1.1.2.2  perseant  * Insert ARG into the operand described by OPDEF in instruction INSN
    454  1.1.1.1.2.2  perseant  * Returns 1 if the immediate extension (IMMX) has been
    455  1.1.1.1.2.2  perseant  * handled along with relocation, 0 if not.
    456  1.1.1.1.2.2  perseant  */
    457  1.1.1.1.2.2  perseant static int
    458  1.1.1.1.2.2  perseant insert_operand (struct kvxinsn *insn, struct kvx_operand *opdef,
    459  1.1.1.1.2.2  perseant 		struct token_list *tok)
    460  1.1.1.1.2.2  perseant {
    461  1.1.1.1.2.2  perseant   uint64_t op = 0;
    462  1.1.1.1.2.2  perseant   struct kvx_bitfield *bfields = opdef->bfield;
    463  1.1.1.1.2.2  perseant   int bf_nb = opdef->bitfields;
    464  1.1.1.1.2.2  perseant   int immx_ready = 0;
    465  1.1.1.1.2.2  perseant 
    466  1.1.1.1.2.2  perseant   if (opdef->width == 0)
    467  1.1.1.1.2.2  perseant     return 0;
    468  1.1.1.1.2.2  perseant 
    469  1.1.1.1.2.2  perseant #define add_fixup(insn_, reloc_, exp_) \
    470  1.1.1.1.2.2  perseant   do { \
    471  1.1.1.1.2.2  perseant     (insn_)->fixup[(insn_)->nfixups].reloc = (reloc_); \
    472  1.1.1.1.2.2  perseant     (insn_)->fixup[(insn_)->nfixups].exp = (exp_);     \
    473  1.1.1.1.2.2  perseant     (insn_)->fixup[(insn_)->nfixups].where = 0;        \
    474  1.1.1.1.2.2  perseant     (insn_)->nfixups++;                                \
    475  1.1.1.1.2.2  perseant   } while (0)
    476  1.1.1.1.2.2  perseant 
    477  1.1.1.1.2.2  perseant #define add_immx(insn_, words_, reloc_, exp_, nfixups_, len_) \
    478  1.1.1.1.2.2  perseant   do { \
    479  1.1.1.1.2.2  perseant     immxbuf[immxcnt].words[0] = (words_);                \
    480  1.1.1.1.2.2  perseant     immxbuf[immxcnt].fixup[0].reloc = (reloc_);          \
    481  1.1.1.1.2.2  perseant     immxbuf[immxcnt].fixup[0].exp = (exp_);              \
    482  1.1.1.1.2.2  perseant     immxbuf[immxcnt].fixup[0].where = 0;                 \
    483  1.1.1.1.2.2  perseant     immxbuf[immxcnt].nfixups = (nfixups_);               \
    484  1.1.1.1.2.2  perseant     immxbuf[immxcnt].len = (len_);                       \
    485  1.1.1.1.2.2  perseant     /* decrement insn->len: immx part handled separately \
    486  1.1.1.1.2.2  perseant        from insn and must not be emited twice.  */       \
    487  1.1.1.1.2.2  perseant     (insn_)->len -= 1;                                   \
    488  1.1.1.1.2.2  perseant     incr_immxcnt ();                                     \
    489  1.1.1.1.2.2  perseant   } while (0)
    490  1.1.1.1.2.2  perseant 
    491  1.1.1.1.2.2  perseant #define chk_imm(core_, imm_) \
    492  1.1.1.1.2.2  perseant   (env.params.core == ELF_KVX_CORE_## core_ && opdef->type == (imm_))
    493  1.1.1.1.2.2  perseant 
    494  1.1.1.1.2.2  perseant   /* try to resolve the value */
    495  1.1.1.1.2.2  perseant 
    496  1.1.1.1.2.2  perseant   switch (tok->category)
    497  1.1.1.1.2.2  perseant     {
    498  1.1.1.1.2.2  perseant     case CAT_REGISTER:
    499  1.1.1.1.2.2  perseant       op = S_GET_VALUE (str_hash_find (env.reg_hash, tok->tok));
    500  1.1.1.1.2.2  perseant       op -= opdef->bias;
    501  1.1.1.1.2.2  perseant       op >>= opdef->shift;
    502  1.1.1.1.2.2  perseant       break;
    503  1.1.1.1.2.2  perseant     case CAT_MODIFIER:
    504  1.1.1.1.2.2  perseant       op = tok->val;
    505  1.1.1.1.2.2  perseant       op -= opdef->bias;
    506  1.1.1.1.2.2  perseant       op >>= opdef->shift;
    507  1.1.1.1.2.2  perseant       break;
    508  1.1.1.1.2.2  perseant     case CAT_IMMEDIATE:
    509  1.1.1.1.2.2  perseant       {
    510  1.1.1.1.2.2  perseant 	char *ilp_save = input_line_pointer;
    511  1.1.1.1.2.2  perseant 	input_line_pointer = tok->tok;
    512  1.1.1.1.2.2  perseant 	expressionS exp = { 0 };
    513  1.1.1.1.2.2  perseant 	expression (&exp);
    514  1.1.1.1.2.2  perseant 	input_line_pointer = ilp_save;
    515  1.1.1.1.2.2  perseant 
    516  1.1.1.1.2.2  perseant 	/* We are dealing with a pseudo-function.  */
    517  1.1.1.1.2.2  perseant 	if (tok->tok[0] == '@')
    518  1.1.1.1.2.2  perseant 	  {
    519  1.1.1.1.2.2  perseant 	    if (insn->nfixups == 0)
    520  1.1.1.1.2.2  perseant 	      {
    521  1.1.1.1.2.2  perseant 		expressionS reloc_arg;
    522  1.1.1.1.2.2  perseant 		reloc_arg = exp;
    523  1.1.1.1.2.2  perseant 		reloc_arg.X_op = O_symbol;
    524  1.1.1.1.2.2  perseant 		struct pseudo_func *pf =
    525  1.1.1.1.2.2  perseant 		  kvx_get_pseudo_func2 (exp.X_op_symbol, opdef);
    526  1.1.1.1.2.2  perseant 		/* S64 uses LO10/UP27/EX27 format (3 words), with one reloc in each words (3) */
    527  1.1.1.1.2.2  perseant 		/* S43 uses LO10/EX6/UP27 format (2 words), with 2 relocs in main syllabes and 1 in extra word */
    528  1.1.1.1.2.2  perseant 		/* S37 uses LO10/UP27 format (2 words), with one reloc in each word (2) */
    529  1.1.1.1.2.2  perseant 
    530  1.1.1.1.2.2  perseant 		/* Beware that immxbuf must be filled in the same order as relocs should be emitted. */
    531  1.1.1.1.2.2  perseant 
    532  1.1.1.1.2.2  perseant 		if (pf->pseudo_relocs.reloc_type == S64_LO10_UP27_EX27
    533  1.1.1.1.2.2  perseant 		    || pf->pseudo_relocs.reloc_type == S43_LO10_UP27_EX6
    534  1.1.1.1.2.2  perseant 		    || pf->pseudo_relocs.reloc_type == S37_LO10_UP27)
    535  1.1.1.1.2.2  perseant 		  {
    536  1.1.1.1.2.2  perseant 		    add_fixup (insn, pf->pseudo_relocs.reloc_lo10, reloc_arg);
    537  1.1.1.1.2.2  perseant 
    538  1.1.1.1.2.2  perseant 		    insn->immx0 = immxcnt;
    539  1.1.1.1.2.2  perseant 		    add_immx (insn, 0, pf->pseudo_relocs.reloc_up27,
    540  1.1.1.1.2.2  perseant 			      reloc_arg, 1, 1);
    541  1.1.1.1.2.2  perseant 		    immx_ready = 1;
    542  1.1.1.1.2.2  perseant 		  }
    543  1.1.1.1.2.2  perseant 		else if (pf->pseudo_relocs.reloc_type == S32_LO5_UP27)
    544  1.1.1.1.2.2  perseant 		  {
    545  1.1.1.1.2.2  perseant 		    add_fixup (insn, pf->pseudo_relocs.reloc_lo5, reloc_arg);
    546  1.1.1.1.2.2  perseant 
    547  1.1.1.1.2.2  perseant 		    insn->immx0 = immxcnt;
    548  1.1.1.1.2.2  perseant 		    add_immx (insn, 0, pf->pseudo_relocs.reloc_up27,
    549  1.1.1.1.2.2  perseant 			      reloc_arg, 1, 1);
    550  1.1.1.1.2.2  perseant 		    immx_ready = 1;
    551  1.1.1.1.2.2  perseant 		  }
    552  1.1.1.1.2.2  perseant 		else if (pf->pseudo_relocs.reloc_type == S16)
    553  1.1.1.1.2.2  perseant 		  add_fixup (insn, pf->pseudo_relocs.single, reloc_arg);
    554  1.1.1.1.2.2  perseant 		else
    555  1.1.1.1.2.2  perseant 		  as_fatal ("Unexpected fixup");
    556  1.1.1.1.2.2  perseant 
    557  1.1.1.1.2.2  perseant 		if (pf->pseudo_relocs.reloc_type == S64_LO10_UP27_EX27)
    558  1.1.1.1.2.2  perseant 		  {
    559  1.1.1.1.2.2  perseant 		    insn->immx1 = immxcnt;
    560  1.1.1.1.2.2  perseant 		    add_immx (insn, 0, pf->pseudo_relocs.reloc_ex, reloc_arg,
    561  1.1.1.1.2.2  perseant 			      1, 1);
    562  1.1.1.1.2.2  perseant 		  }
    563  1.1.1.1.2.2  perseant 		else if (pf->pseudo_relocs.reloc_type == S43_LO10_UP27_EX6)
    564  1.1.1.1.2.2  perseant 		  add_fixup (insn, pf->pseudo_relocs.reloc_ex, reloc_arg);
    565  1.1.1.1.2.2  perseant 	      }
    566  1.1.1.1.2.2  perseant 	  }
    567  1.1.1.1.2.2  perseant 	else
    568  1.1.1.1.2.2  perseant 	  {
    569  1.1.1.1.2.2  perseant 	    if (exp.X_op == O_constant)
    570  1.1.1.1.2.2  perseant 	      {
    571  1.1.1.1.2.2  perseant 		/* This is a immediate: either a regular immediate, or an
    572  1.1.1.1.2.2  perseant 		   immediate that was saved in a variable through `.equ'.  */
    573  1.1.1.1.2.2  perseant 		uint64_t sval = (int64_t) tok->val;
    574  1.1.1.1.2.2  perseant 		op = opdef->flags & kvxSIGNED ? sval : tok->val;
    575  1.1.1.1.2.2  perseant 		op >>= opdef->shift;
    576  1.1.1.1.2.2  perseant 	      }
    577  1.1.1.1.2.2  perseant 	    else if (exp.X_op == O_subtract)
    578  1.1.1.1.2.2  perseant 	      as_fatal ("O_subtract not supported.");
    579  1.1.1.1.2.2  perseant 	    else
    580  1.1.1.1.2.2  perseant 	      {
    581  1.1.1.1.2.2  perseant 
    582  1.1.1.1.2.2  perseant 		/* This is a symbol which needs a relocation.  */
    583  1.1.1.1.2.2  perseant 		if (insn->nfixups == 0)
    584  1.1.1.1.2.2  perseant 		  {
    585  1.1.1.1.2.2  perseant 		    if (chk_imm (KV3_1, Immediate_kv3_v1_pcrel17)
    586  1.1.1.1.2.2  perseant 			|| chk_imm (KV3_2, Immediate_kv3_v2_pcrel17)
    587  1.1.1.1.2.2  perseant 			|| chk_imm (KV4_1, Immediate_kv4_v1_pcrel17))
    588  1.1.1.1.2.2  perseant 		      add_fixup (insn, BFD_RELOC_KVX_PCREL17, exp);
    589  1.1.1.1.2.2  perseant 		    else if (chk_imm (KV3_1, Immediate_kv3_v1_pcrel27)
    590  1.1.1.1.2.2  perseant 			     || chk_imm (KV3_2, Immediate_kv3_v2_pcrel27)
    591  1.1.1.1.2.2  perseant 			     || chk_imm (KV4_1, Immediate_kv4_v1_pcrel27))
    592  1.1.1.1.2.2  perseant 		      add_fixup (insn, BFD_RELOC_KVX_PCREL27, exp);
    593  1.1.1.1.2.2  perseant 		    else if (chk_imm (KV3_1, Immediate_kv3_v1_wrapped32)
    594  1.1.1.1.2.2  perseant 			     || chk_imm (KV3_2, Immediate_kv3_v2_wrapped32)
    595  1.1.1.1.2.2  perseant 			     || chk_imm (KV4_1, Immediate_kv4_v1_wrapped32))
    596  1.1.1.1.2.2  perseant 		      {
    597  1.1.1.1.2.2  perseant 			add_fixup (insn, BFD_RELOC_KVX_S32_LO5, exp);
    598  1.1.1.1.2.2  perseant 
    599  1.1.1.1.2.2  perseant 			insn->immx0 = immxcnt;
    600  1.1.1.1.2.2  perseant 			add_immx (insn, 0, BFD_RELOC_KVX_S32_UP27, exp, 1, 1);
    601  1.1.1.1.2.2  perseant 
    602  1.1.1.1.2.2  perseant 			immx_ready = 1;
    603  1.1.1.1.2.2  perseant 		      }
    604  1.1.1.1.2.2  perseant 		    else if (chk_imm (KV3_1, Immediate_kv3_v1_signed10)
    605  1.1.1.1.2.2  perseant 			     || chk_imm (KV3_2, Immediate_kv3_v2_signed10)
    606  1.1.1.1.2.2  perseant 			     || chk_imm (KV4_1, Immediate_kv4_v1_signed10))
    607  1.1.1.1.2.2  perseant 		      add_fixup (insn, BFD_RELOC_KVX_S37_LO10, exp);
    608  1.1.1.1.2.2  perseant 		    else if (chk_imm (KV3_1, Immediate_kv3_v1_signed37)
    609  1.1.1.1.2.2  perseant 			     || chk_imm (KV3_2, Immediate_kv3_v2_signed37)
    610  1.1.1.1.2.2  perseant 			     || chk_imm (KV4_1, Immediate_kv4_v1_signed37))
    611  1.1.1.1.2.2  perseant 		      {
    612  1.1.1.1.2.2  perseant 			add_fixup (insn, BFD_RELOC_KVX_S37_LO10, exp);
    613  1.1.1.1.2.2  perseant 
    614  1.1.1.1.2.2  perseant 			insn->immx0 = immxcnt;
    615  1.1.1.1.2.2  perseant 			add_immx (insn, 0, BFD_RELOC_KVX_S37_UP27, exp, 1, 1);
    616  1.1.1.1.2.2  perseant 
    617  1.1.1.1.2.2  perseant 			immx_ready = 1;
    618  1.1.1.1.2.2  perseant 		      }
    619  1.1.1.1.2.2  perseant 		    else if (chk_imm (KV3_1, Immediate_kv3_v1_signed43)
    620  1.1.1.1.2.2  perseant 			     || chk_imm (KV3_2, Immediate_kv3_v2_signed43)
    621  1.1.1.1.2.2  perseant 			     || chk_imm (KV4_1, Immediate_kv4_v1_signed43))
    622  1.1.1.1.2.2  perseant 		      {
    623  1.1.1.1.2.2  perseant 			add_fixup (insn, BFD_RELOC_KVX_S43_LO10, exp);
    624  1.1.1.1.2.2  perseant 			add_fixup (insn, BFD_RELOC_KVX_S43_EX6, exp);
    625  1.1.1.1.2.2  perseant 
    626  1.1.1.1.2.2  perseant 			insn->immx0 = immxcnt;
    627  1.1.1.1.2.2  perseant 			add_immx (insn, insn->words[1],
    628  1.1.1.1.2.2  perseant 				  BFD_RELOC_KVX_S43_UP27, exp, 1, 1);
    629  1.1.1.1.2.2  perseant 
    630  1.1.1.1.2.2  perseant 			immx_ready = 1;
    631  1.1.1.1.2.2  perseant 		      }
    632  1.1.1.1.2.2  perseant 		    else if (chk_imm (KV3_1, Immediate_kv3_v1_wrapped64)
    633  1.1.1.1.2.2  perseant 			     || chk_imm (KV3_2, Immediate_kv3_v2_wrapped64)
    634  1.1.1.1.2.2  perseant 			     || chk_imm (KV4_1, Immediate_kv4_v1_wrapped64))
    635  1.1.1.1.2.2  perseant 		      {
    636  1.1.1.1.2.2  perseant 			add_fixup (insn, BFD_RELOC_KVX_S64_LO10, exp);
    637  1.1.1.1.2.2  perseant 
    638  1.1.1.1.2.2  perseant 			insn->immx0 = immxcnt;
    639  1.1.1.1.2.2  perseant 			add_immx (insn, insn->words[1],
    640  1.1.1.1.2.2  perseant 				  BFD_RELOC_KVX_S64_UP27, exp, 1, 1);
    641  1.1.1.1.2.2  perseant 
    642  1.1.1.1.2.2  perseant 			insn->immx1 = immxcnt;
    643  1.1.1.1.2.2  perseant 			add_immx (insn, insn->words[2],
    644  1.1.1.1.2.2  perseant 				  BFD_RELOC_KVX_S64_EX27, exp, 1, 1);
    645  1.1.1.1.2.2  perseant 
    646  1.1.1.1.2.2  perseant 			immx_ready = 1;
    647  1.1.1.1.2.2  perseant 		      }
    648  1.1.1.1.2.2  perseant 		    else
    649  1.1.1.1.2.2  perseant 		      as_fatal ("don't know how to generate a fixup record");
    650  1.1.1.1.2.2  perseant 		    return immx_ready;
    651  1.1.1.1.2.2  perseant 		  }
    652  1.1.1.1.2.2  perseant 		else
    653  1.1.1.1.2.2  perseant 		  as_fatal ("No room for fixup ");
    654  1.1.1.1.2.2  perseant 	      }
    655  1.1.1.1.2.2  perseant 	  }
    656  1.1.1.1.2.2  perseant       }
    657  1.1.1.1.2.2  perseant       break;
    658  1.1.1.1.2.2  perseant     default:
    659  1.1.1.1.2.2  perseant       break;
    660  1.1.1.1.2.2  perseant     }
    661  1.1.1.1.2.2  perseant 
    662  1.1.1.1.2.2  perseant   for (int bf_idx = 0; bf_idx < bf_nb; bf_idx++)
    663  1.1.1.1.2.2  perseant     {
    664  1.1.1.1.2.2  perseant       uint64_t value =
    665  1.1.1.1.2.2  perseant 	((uint64_t) op >> bfields[bf_idx].from_offset);
    666  1.1.1.1.2.2  perseant       int j = 0;
    667  1.1.1.1.2.2  perseant       int to_offset = bfields[bf_idx].to_offset;
    668  1.1.1.1.2.2  perseant       value &= (1LL << bfields[bf_idx].size) - 1;
    669  1.1.1.1.2.2  perseant       j = to_offset / 32;
    670  1.1.1.1.2.2  perseant       to_offset = to_offset % 32;
    671  1.1.1.1.2.2  perseant       insn->words[j] |= (value << to_offset) & 0xffffffff;
    672  1.1.1.1.2.2  perseant     }
    673  1.1.1.1.2.2  perseant 
    674  1.1.1.1.2.2  perseant   return immx_ready;
    675  1.1.1.1.2.2  perseant 
    676  1.1.1.1.2.2  perseant #undef chk_imm
    677  1.1.1.1.2.2  perseant #undef add_immx
    678  1.1.1.1.2.2  perseant #undef add_fixup
    679  1.1.1.1.2.2  perseant }
    680  1.1.1.1.2.2  perseant 
    681  1.1.1.1.2.2  perseant /*
    682  1.1.1.1.2.2  perseant  * Given a set of operands and a matching instruction,
    683  1.1.1.1.2.2  perseant  * assemble it
    684  1.1.1.1.2.2  perseant  *
    685  1.1.1.1.2.2  perseant  */
    686  1.1.1.1.2.2  perseant static void
    687  1.1.1.1.2.2  perseant assemble_insn (const struct kvxopc * opcode, struct token_list *tok, struct kvxinsn *insn)
    688  1.1.1.1.2.2  perseant {
    689  1.1.1.1.2.2  perseant   unsigned immx_ready = 0;
    690  1.1.1.1.2.2  perseant 
    691  1.1.1.1.2.2  perseant   memset (insn, 0, sizeof (*insn));
    692  1.1.1.1.2.2  perseant   insn->opdef = opcode;
    693  1.1.1.1.2.2  perseant   for (int i = 0; i < opcode->wordcount; i++)
    694  1.1.1.1.2.2  perseant     {
    695  1.1.1.1.2.2  perseant       insn->words[i] = opcode->codewords[i].opcode;
    696  1.1.1.1.2.2  perseant       insn->len += 1;
    697  1.1.1.1.2.2  perseant     }
    698  1.1.1.1.2.2  perseant 
    699  1.1.1.1.2.2  perseant   insn->immx0 = NOIMMX;
    700  1.1.1.1.2.2  perseant   insn->immx1 = NOIMMX;
    701  1.1.1.1.2.2  perseant 
    702  1.1.1.1.2.2  perseant   struct token_list *tok_ = tok;
    703  1.1.1.1.2.2  perseant   struct kvx_operand **format = (struct kvx_operand **) opcode->format;
    704  1.1.1.1.2.2  perseant 
    705  1.1.1.1.2.2  perseant   while (tok_)
    706  1.1.1.1.2.2  perseant     {
    707  1.1.1.1.2.2  perseant       int ret = insert_operand (insn, *format, tok_);
    708  1.1.1.1.2.2  perseant       immx_ready |= ret;
    709  1.1.1.1.2.2  perseant       while ((tok_ = tok_->next) && tok_->category == CAT_SEPARATOR);
    710  1.1.1.1.2.2  perseant       format++;
    711  1.1.1.1.2.2  perseant     }
    712  1.1.1.1.2.2  perseant 
    713  1.1.1.1.2.2  perseant   // Handle immx if insert_operand did not already take care of that
    714  1.1.1.1.2.2  perseant   if (!immx_ready)
    715  1.1.1.1.2.2  perseant     {
    716  1.1.1.1.2.2  perseant       for (int i = 0; i < opcode->wordcount; i++)
    717  1.1.1.1.2.2  perseant 	{
    718  1.1.1.1.2.2  perseant 	  if (opcode->codewords[i].flags & kvxOPCODE_FLAG_IMMX0)
    719  1.1.1.1.2.2  perseant 	    {
    720  1.1.1.1.2.2  perseant 	      insn->immx0 = immxcnt;
    721  1.1.1.1.2.2  perseant 	      immxbuf[immxcnt].words[0] = insn->words[i];
    722  1.1.1.1.2.2  perseant 	      immxbuf[immxcnt].nfixups = 0;
    723  1.1.1.1.2.2  perseant 	      immxbuf[immxcnt].len = 1;
    724  1.1.1.1.2.2  perseant 	      insn->len -= 1;
    725  1.1.1.1.2.2  perseant 	      incr_immxcnt ();
    726  1.1.1.1.2.2  perseant 	    }
    727  1.1.1.1.2.2  perseant 	  if (opcode->codewords[i].flags & kvxOPCODE_FLAG_IMMX1)
    728  1.1.1.1.2.2  perseant 	    {
    729  1.1.1.1.2.2  perseant 	      insn->immx1 = immxcnt;
    730  1.1.1.1.2.2  perseant 	      immxbuf[immxcnt].words[0] = insn->words[i];
    731  1.1.1.1.2.2  perseant 	      immxbuf[immxcnt].nfixups = 0;
    732  1.1.1.1.2.2  perseant 	      immxbuf[immxcnt].len = 1;
    733  1.1.1.1.2.2  perseant 	      insn->len -= 1;
    734  1.1.1.1.2.2  perseant 	      incr_immxcnt ();
    735  1.1.1.1.2.2  perseant 	    }
    736  1.1.1.1.2.2  perseant 	}
    737  1.1.1.1.2.2  perseant     }
    738  1.1.1.1.2.2  perseant }
    739  1.1.1.1.2.2  perseant 
    740  1.1.1.1.2.2  perseant /* Emit an instruction from the instruction array into the object
    741  1.1.1.1.2.2  perseant  * file. INSN points to an element of the instruction array. STOPFLAG
    742  1.1.1.1.2.2  perseant  * is true if this is the last instruction in the bundle.
    743  1.1.1.1.2.2  perseant  *
    744  1.1.1.1.2.2  perseant  * Only handles main syllables of bundle. Immediate extensions are
    745  1.1.1.1.2.2  perseant  * handled by insert_operand.
    746  1.1.1.1.2.2  perseant  */
    747  1.1.1.1.2.2  perseant static void
    748  1.1.1.1.2.2  perseant emit_insn (struct kvxinsn * insn, int insn_pos, int stopflag)
    749  1.1.1.1.2.2  perseant {
    750  1.1.1.1.2.2  perseant   char *f;
    751  1.1.1.1.2.2  perseant   unsigned int image;
    752  1.1.1.1.2.2  perseant 
    753  1.1.1.1.2.2  perseant   /* if we are listing, attach frag to previous line.  */
    754  1.1.1.1.2.2  perseant   if (listing)
    755  1.1.1.1.2.2  perseant     listing_prev_line ();
    756  1.1.1.1.2.2  perseant 
    757  1.1.1.1.2.2  perseant   /* Update text size for lane parity checking.  */
    758  1.1.1.1.2.2  perseant   set_byte_counter (now_seg, (get_byte_counter (now_seg) + (insn->len * 4)));
    759  1.1.1.1.2.2  perseant 
    760  1.1.1.1.2.2  perseant   /* allocate space in the fragment.  */
    761  1.1.1.1.2.2  perseant   f = frag_more (insn->len * 4);
    762  1.1.1.1.2.2  perseant 
    763  1.1.1.1.2.2  perseant   /* spit out bits.  */
    764  1.1.1.1.2.2  perseant   for (int i = 0; i < insn->len; i++)
    765  1.1.1.1.2.2  perseant     {
    766  1.1.1.1.2.2  perseant       image = insn->words[i];
    767  1.1.1.1.2.2  perseant 
    768  1.1.1.1.2.2  perseant       /* Handle bundle parallel bit. */ ;
    769  1.1.1.1.2.2  perseant       if ((i == insn->len - 1) && stopflag)
    770  1.1.1.1.2.2  perseant 	image &= ~PARALLEL_BIT;
    771  1.1.1.1.2.2  perseant       else
    772  1.1.1.1.2.2  perseant 	image |= PARALLEL_BIT;
    773  1.1.1.1.2.2  perseant 
    774  1.1.1.1.2.2  perseant       /* Emit the instruction image. */
    775  1.1.1.1.2.2  perseant       md_number_to_chars (f + (i * 4), image, 4);
    776  1.1.1.1.2.2  perseant     }
    777  1.1.1.1.2.2  perseant 
    778  1.1.1.1.2.2  perseant   /* generate fixup records */
    779  1.1.1.1.2.2  perseant 
    780  1.1.1.1.2.2  perseant   for (int i = 0; i < insn->nfixups; i++)
    781  1.1.1.1.2.2  perseant     {
    782  1.1.1.1.2.2  perseant       int size, pcrel;
    783  1.1.1.1.2.2  perseant       reloc_howto_type *reloc_howto =
    784  1.1.1.1.2.2  perseant 	bfd_reloc_type_lookup (stdoutput, insn->fixup[i].reloc);
    785  1.1.1.1.2.2  perseant       assert (reloc_howto);
    786  1.1.1.1.2.2  perseant       size = bfd_get_reloc_size (reloc_howto);
    787  1.1.1.1.2.2  perseant       pcrel = reloc_howto->pc_relative;
    788  1.1.1.1.2.2  perseant 
    789  1.1.1.1.2.2  perseant       /* In case the PCREL relocation is not for the first insn in the
    790  1.1.1.1.2.2  perseant          bundle, we have to offset it.  The pc used by the hardware
    791  1.1.1.1.2.2  perseant          references a bundle and not separate insn.
    792  1.1.1.1.2.2  perseant        */
    793  1.1.1.1.2.2  perseant       assert (!(insn_pos == -1 && pcrel));
    794  1.1.1.1.2.2  perseant       if (pcrel && insn_pos > 0)
    795  1.1.1.1.2.2  perseant 	insn->fixup[i].exp.X_add_number += insn_pos * 4;
    796  1.1.1.1.2.2  perseant 
    797  1.1.1.1.2.2  perseant       fixS *fixup = fix_new_exp (frag_now,
    798  1.1.1.1.2.2  perseant 				 f - frag_now->fr_literal +
    799  1.1.1.1.2.2  perseant 				 insn->fixup[i].where,
    800  1.1.1.1.2.2  perseant 				 size,
    801  1.1.1.1.2.2  perseant 				 &(insn->fixup[i].exp),
    802  1.1.1.1.2.2  perseant 				 pcrel,
    803  1.1.1.1.2.2  perseant 				 insn->fixup[i].reloc);
    804  1.1.1.1.2.2  perseant       /*
    805  1.1.1.1.2.2  perseant        * Set this bit so that large value can still be
    806  1.1.1.1.2.2  perseant        * handled. Without it, assembler will fail in fixup_segment
    807  1.1.1.1.2.2  perseant        * when it checks there is enough bits to store the value. As we
    808  1.1.1.1.2.2  perseant        * usually split our reloc across different words, it may think
    809  1.1.1.1.2.2  perseant        * that 4 bytes are not enough for large value. This simply
    810  1.1.1.1.2.2  perseant        * skips the tests
    811  1.1.1.1.2.2  perseant        */
    812  1.1.1.1.2.2  perseant       fixup->fx_no_overflow = 1;
    813  1.1.1.1.2.2  perseant     }
    814  1.1.1.1.2.2  perseant }
    815  1.1.1.1.2.2  perseant 
    816  1.1.1.1.2.2  perseant 
    817  1.1.1.1.2.2  perseant /* Called for any expression that can not be recognized.  When the
    818  1.1.1.1.2.2  perseant  * function is called, `input_line_pointer' will point to the start of
    819  1.1.1.1.2.2  perseant  * the expression.  */
    820  1.1.1.1.2.2  perseant /* FIXME: Should be done by the parser */
    821  1.1.1.1.2.2  perseant void
    822  1.1.1.1.2.2  perseant md_operand (expressionS * e)
    823  1.1.1.1.2.2  perseant {
    824  1.1.1.1.2.2  perseant   /* enum pseudo_type pseudo_type; */
    825  1.1.1.1.2.2  perseant   /* char *name = NULL; */
    826  1.1.1.1.2.2  perseant   size_t len;
    827  1.1.1.1.2.2  perseant   int ch, i;
    828  1.1.1.1.2.2  perseant 
    829  1.1.1.1.2.2  perseant   switch (*input_line_pointer)
    830  1.1.1.1.2.2  perseant     {
    831  1.1.1.1.2.2  perseant     case '@':
    832  1.1.1.1.2.2  perseant       /* Find what relocation pseudo-function we're dealing with. */
    833  1.1.1.1.2.2  perseant       /* pseudo_type = 0; */
    834  1.1.1.1.2.2  perseant       ch = *++input_line_pointer;
    835  1.1.1.1.2.2  perseant       for (i = 0; i < kvx_core_info->nb_pseudo_funcs; ++i)
    836  1.1.1.1.2.2  perseant 	if (kvx_core_info->pseudo_funcs[i].name && kvx_core_info->pseudo_funcs[i].name[0] == ch)
    837  1.1.1.1.2.2  perseant 	  {
    838  1.1.1.1.2.2  perseant 	    len = strlen (kvx_core_info->pseudo_funcs[i].name);
    839  1.1.1.1.2.2  perseant 	    if (strncmp (kvx_core_info->pseudo_funcs[i].name + 1,
    840  1.1.1.1.2.2  perseant 			 input_line_pointer + 1, len - 1) == 0
    841  1.1.1.1.2.2  perseant 		&& !is_part_of_name (input_line_pointer[len]))
    842  1.1.1.1.2.2  perseant 	      {
    843  1.1.1.1.2.2  perseant 		input_line_pointer += len;
    844  1.1.1.1.2.2  perseant 		break;
    845  1.1.1.1.2.2  perseant 	      }
    846  1.1.1.1.2.2  perseant 	  }
    847  1.1.1.1.2.2  perseant       SKIP_WHITESPACE ();
    848  1.1.1.1.2.2  perseant       if (*input_line_pointer != '(')
    849  1.1.1.1.2.2  perseant 	{
    850  1.1.1.1.2.2  perseant 	  as_bad ("Expected '('");
    851  1.1.1.1.2.2  perseant 	  goto err;
    852  1.1.1.1.2.2  perseant 	}
    853  1.1.1.1.2.2  perseant       /* Skip '('.  */
    854  1.1.1.1.2.2  perseant       ++input_line_pointer;
    855  1.1.1.1.2.2  perseant       if (!kvx_core_info->pseudo_funcs[i].pseudo_relocs.has_no_arg)
    856  1.1.1.1.2.2  perseant 	expression (e);
    857  1.1.1.1.2.2  perseant       if (*input_line_pointer++ != ')')
    858  1.1.1.1.2.2  perseant 	{
    859  1.1.1.1.2.2  perseant 	  as_bad ("Missing ')'");
    860  1.1.1.1.2.2  perseant 	  goto err;
    861  1.1.1.1.2.2  perseant 	}
    862  1.1.1.1.2.2  perseant       if (!kvx_core_info->pseudo_funcs[i].pseudo_relocs.has_no_arg)
    863  1.1.1.1.2.2  perseant 	{
    864  1.1.1.1.2.2  perseant 	  if (e->X_op != O_symbol)
    865  1.1.1.1.2.2  perseant 	    as_fatal ("Illegal combination of relocation functions");
    866  1.1.1.1.2.2  perseant 	}
    867  1.1.1.1.2.2  perseant       /* Make sure gas doesn't get rid of local symbols that are used
    868  1.1.1.1.2.2  perseant          in relocs.  */
    869  1.1.1.1.2.2  perseant       e->X_op = O_pseudo_fixup;
    870  1.1.1.1.2.2  perseant       e->X_op_symbol = kvx_core_info->pseudo_funcs[i].sym;
    871  1.1.1.1.2.2  perseant       break;
    872  1.1.1.1.2.2  perseant 
    873  1.1.1.1.2.2  perseant     default:
    874  1.1.1.1.2.2  perseant       break;
    875  1.1.1.1.2.2  perseant     }
    876  1.1.1.1.2.2  perseant   return;
    877  1.1.1.1.2.2  perseant 
    878  1.1.1.1.2.2  perseant err:
    879  1.1.1.1.2.2  perseant   ignore_rest_of_line ();
    880  1.1.1.1.2.2  perseant }
    881  1.1.1.1.2.2  perseant 
    882  1.1.1.1.2.2  perseant /*
    883  1.1.1.1.2.2  perseant  * Return the Bundling type for an insn.
    884  1.1.1.1.2.2  perseant  */
    885  1.1.1.1.2.2  perseant static int
    886  1.1.1.1.2.2  perseant find_bundling (const struct kvxinsn * insn)
    887  1.1.1.1.2.2  perseant {
    888  1.1.1.1.2.2  perseant   return insn->opdef->bundling;
    889  1.1.1.1.2.2  perseant }
    890  1.1.1.1.2.2  perseant 
    891  1.1.1.1.2.2  perseant static int
    892  1.1.1.1.2.2  perseant find_reservation (const struct kvxinsn * insn)
    893  1.1.1.1.2.2  perseant {
    894  1.1.1.1.2.2  perseant   return insn->opdef->reservation;
    895  1.1.1.1.2.2  perseant }
    896  1.1.1.1.2.2  perseant 
    897  1.1.1.1.2.2  perseant static struct kvxopc *
    898  1.1.1.1.2.2  perseant assemble_tokens (struct token_list *tok_list)
    899  1.1.1.1.2.2  perseant {
    900  1.1.1.1.2.2  perseant   assert (tok_list != NULL);
    901  1.1.1.1.2.2  perseant   struct token_list *toks = tok_list;
    902  1.1.1.1.2.2  perseant 
    903  1.1.1.1.2.2  perseant   /* make sure there is room in instruction buffer */
    904  1.1.1.1.2.2  perseant   /* Was KVXMAXBUNDLEISSUE, changed because of NOPs */
    905  1.1.1.1.2.2  perseant   if (insncnt >= KVXMAXBUNDLEWORDS)
    906  1.1.1.1.2.2  perseant     as_fatal ("[assemble_tokens]: too many instructions in bundle.");
    907  1.1.1.1.2.2  perseant 
    908  1.1.1.1.2.2  perseant   /* TODO: Merge */
    909  1.1.1.1.2.2  perseant   struct kvxinsn *insn;
    910  1.1.1.1.2.2  perseant   insn = insbuf + insncnt;
    911  1.1.1.1.2.2  perseant 
    912  1.1.1.1.2.2  perseant   /* The formats table registers the modifier into the opcode, therefore we need
    913  1.1.1.1.2.2  perseant      to fuse both before looking up the opcodes hashtable.  */
    914  1.1.1.1.2.2  perseant   char *opcode = NULL;
    915  1.1.1.1.2.2  perseant 
    916  1.1.1.1.2.2  perseant   opcode = toks->tok;
    917  1.1.1.1.2.2  perseant   toks = toks->next;
    918  1.1.1.1.2.2  perseant 
    919  1.1.1.1.2.2  perseant   while (toks && toks->category == CAT_SEPARATOR)
    920  1.1.1.1.2.2  perseant     toks = toks->next;
    921  1.1.1.1.2.2  perseant 
    922  1.1.1.1.2.2  perseant   /* Find the format requested by the instruction.  */
    923  1.1.1.1.2.2  perseant   struct kvxopc *format_tbl = str_hash_find (env.opcode_hash, opcode);
    924  1.1.1.1.2.2  perseant   struct kvxopc *format = NULL;
    925  1.1.1.1.2.2  perseant 
    926  1.1.1.1.2.2  perseant   struct token_list *toks_ = toks;
    927  1.1.1.1.2.2  perseant 
    928  1.1.1.1.2.2  perseant   while (!format && format_tbl && STREQ (opcode, format_tbl->as_op))
    929  1.1.1.1.2.2  perseant   {
    930  1.1.1.1.2.2  perseant     for (int i = 0 ; toks_ && format_tbl->format[i]
    931  1.1.1.1.2.2  perseant 	&& toks_->class_id == format_tbl->format[i]->type ;)
    932  1.1.1.1.2.2  perseant       {
    933  1.1.1.1.2.2  perseant 	toks_ = toks_->next;
    934  1.1.1.1.2.2  perseant 	while (toks_ && toks_->category == CAT_SEPARATOR)
    935  1.1.1.1.2.2  perseant 	  toks_ = toks_->next;
    936  1.1.1.1.2.2  perseant 	i += 1;
    937  1.1.1.1.2.2  perseant       }
    938  1.1.1.1.2.2  perseant 
    939  1.1.1.1.2.2  perseant     if (!toks_)
    940  1.1.1.1.2.2  perseant       format = format_tbl;
    941  1.1.1.1.2.2  perseant     else
    942  1.1.1.1.2.2  perseant       {
    943  1.1.1.1.2.2  perseant 	toks_ = toks;
    944  1.1.1.1.2.2  perseant 	format_tbl++;
    945  1.1.1.1.2.2  perseant       }
    946  1.1.1.1.2.2  perseant   }
    947  1.1.1.1.2.2  perseant 
    948  1.1.1.1.2.2  perseant   assert (format != NULL);
    949  1.1.1.1.2.2  perseant 
    950  1.1.1.1.2.2  perseant   assemble_insn (format, toks, insn);
    951  1.1.1.1.2.2  perseant   insncnt++;
    952  1.1.1.1.2.2  perseant 
    953  1.1.1.1.2.2  perseant   return NULL;
    954  1.1.1.1.2.2  perseant }
    955  1.1.1.1.2.2  perseant 
    956  1.1.1.1.2.2  perseant /*
    957  1.1.1.1.2.2  perseant  * Write in buf at most buf_size.
    958  1.1.1.1.2.2  perseant  * Returns the number of writen characters.
    959  1.1.1.1.2.2  perseant  */
    960  1.1.1.1.2.2  perseant static int ATTRIBUTE_UNUSED
    961  1.1.1.1.2.2  perseant insn_syntax (struct kvxopc * op, char *buf, int buf_size)
    962  1.1.1.1.2.2  perseant {
    963  1.1.1.1.2.2  perseant   int chars = snprintf (buf, buf_size, "%s ", op->as_op);
    964  1.1.1.1.2.2  perseant   const char *fmtp = op->fmtstring;
    965  1.1.1.1.2.2  perseant   char ch = 0;
    966  1.1.1.1.2.2  perseant 
    967  1.1.1.1.2.2  perseant   for (int i = 0; op->format[i]; i++)
    968  1.1.1.1.2.2  perseant     {
    969  1.1.1.1.2.2  perseant       int type = op->format[i]->type;
    970  1.1.1.1.2.2  perseant       const char *type_name = TOKEN_NAME (type);
    971  1.1.1.1.2.2  perseant       int offset = 0;
    972  1.1.1.1.2.2  perseant 
    973  1.1.1.1.2.2  perseant       for (int j = 0 ; type_name[j] ; ++j)
    974  1.1.1.1.2.2  perseant 	if (type_name[j] == '_')
    975  1.1.1.1.2.2  perseant 	  offset = j + 1;
    976  1.1.1.1.2.2  perseant 
    977  1.1.1.1.2.2  perseant       /* Print characters in the format string up to the following * % or nul. */
    978  1.1.1.1.2.2  perseant       while ((chars < buf_size) && (ch = *fmtp) && ch != '%')
    979  1.1.1.1.2.2  perseant 	{
    980  1.1.1.1.2.2  perseant 	  buf[chars++] = ch;
    981  1.1.1.1.2.2  perseant 	  fmtp++;
    982  1.1.1.1.2.2  perseant 	}
    983  1.1.1.1.2.2  perseant 
    984  1.1.1.1.2.2  perseant       /* Skip past %s */
    985  1.1.1.1.2.2  perseant       if (ch == '%')
    986  1.1.1.1.2.2  perseant 	{
    987  1.1.1.1.2.2  perseant 	  ch = *fmtp++;
    988  1.1.1.1.2.2  perseant 	  fmtp++;
    989  1.1.1.1.2.2  perseant 	}
    990  1.1.1.1.2.2  perseant 
    991  1.1.1.1.2.2  perseant       chars += snprintf (&buf[chars], buf_size - chars, "%s", type_name + offset);
    992  1.1.1.1.2.2  perseant     }
    993  1.1.1.1.2.2  perseant 
    994  1.1.1.1.2.2  perseant   /* Print trailing characters in the format string, if any */
    995  1.1.1.1.2.2  perseant   while ((chars < buf_size) && (ch = *fmtp))
    996  1.1.1.1.2.2  perseant     {
    997  1.1.1.1.2.2  perseant       buf[chars++] = ch;
    998  1.1.1.1.2.2  perseant       fmtp++;
    999  1.1.1.1.2.2  perseant     }
   1000  1.1.1.1.2.2  perseant 
   1001  1.1.1.1.2.2  perseant   if (chars < buf_size)
   1002  1.1.1.1.2.2  perseant     buf[chars++] = '\0';
   1003  1.1.1.1.2.2  perseant   else
   1004  1.1.1.1.2.2  perseant     buf[buf_size - 1] = '\0';
   1005  1.1.1.1.2.2  perseant 
   1006  1.1.1.1.2.2  perseant   return chars;
   1007  1.1.1.1.2.2  perseant }
   1008  1.1.1.1.2.2  perseant 
   1009  1.1.1.1.2.2  perseant #define ASM_CHARS_MAX (71)
   1010  1.1.1.1.2.2  perseant 
   1011  1.1.1.1.2.2  perseant static void
   1012  1.1.1.1.2.2  perseant kvx_print_insn (struct kvxopc * op ATTRIBUTE_UNUSED)
   1013  1.1.1.1.2.2  perseant {
   1014  1.1.1.1.2.2  perseant   char asm_str[ASM_CHARS_MAX];
   1015  1.1.1.1.2.2  perseant   int chars = insn_syntax (op, asm_str, ASM_CHARS_MAX);
   1016  1.1.1.1.2.2  perseant   const char *insn_type = "UNKNOWN";
   1017  1.1.1.1.2.2  perseant   const char *insn_mode = "";
   1018  1.1.1.1.2.2  perseant 
   1019  1.1.1.1.2.2  perseant   for (int i = chars - 1; i < ASM_CHARS_MAX - 1; i++)
   1020  1.1.1.1.2.2  perseant     asm_str[i] = '-';
   1021  1.1.1.1.2.2  perseant 
   1022  1.1.1.1.2.2  perseant   /* This is a hack which works because the Bundling is the same for all cores
   1023  1.1.1.1.2.2  perseant      for now.  */
   1024  1.1.1.1.2.2  perseant   switch ((int) op->bundling)
   1025  1.1.1.1.2.2  perseant     {
   1026  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_ALL:
   1027  1.1.1.1.2.2  perseant       insn_type = "ALL  ";
   1028  1.1.1.1.2.2  perseant       break;
   1029  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_BCU:
   1030  1.1.1.1.2.2  perseant       insn_type = "BCU  ";
   1031  1.1.1.1.2.2  perseant       break;
   1032  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_TCA:
   1033  1.1.1.1.2.2  perseant       insn_type = "TCA  ";
   1034  1.1.1.1.2.2  perseant       break;
   1035  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_FULL:
   1036  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_FULL_X:
   1037  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_FULL_Y:
   1038  1.1.1.1.2.2  perseant       insn_type = "FULL ";
   1039  1.1.1.1.2.2  perseant       break;
   1040  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_LITE:
   1041  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_LITE_X:
   1042  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_LITE_Y:
   1043  1.1.1.1.2.2  perseant       insn_type = "LITE ";
   1044  1.1.1.1.2.2  perseant       break;
   1045  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_TINY:
   1046  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_TINY_X:
   1047  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_TINY_Y:
   1048  1.1.1.1.2.2  perseant       insn_type = "TINY ";
   1049  1.1.1.1.2.2  perseant       break;
   1050  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_MAU:
   1051  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_MAU_X:
   1052  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_MAU_Y:
   1053  1.1.1.1.2.2  perseant       insn_type = "MAU  ";
   1054  1.1.1.1.2.2  perseant       break;
   1055  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_LSU:
   1056  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_LSU_X:
   1057  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_LSU_Y:
   1058  1.1.1.1.2.2  perseant       insn_type = "LSU  ";
   1059  1.1.1.1.2.2  perseant       break;
   1060  1.1.1.1.2.2  perseant     case Bundling_kv3_v1_NOP:
   1061  1.1.1.1.2.2  perseant       insn_type = "NOP  ";
   1062  1.1.1.1.2.2  perseant       break;
   1063  1.1.1.1.2.2  perseant     default:
   1064  1.1.1.1.2.2  perseant       as_fatal ("Unhandled Bundling class %d", op->bundling);
   1065  1.1.1.1.2.2  perseant     }
   1066  1.1.1.1.2.2  perseant 
   1067  1.1.1.1.2.2  perseant   if (op->codewords[0].flags & kvxOPCODE_FLAG_MODE64
   1068  1.1.1.1.2.2  perseant       && op->codewords[0].flags & kvxOPCODE_FLAG_MODE32)
   1069  1.1.1.1.2.2  perseant     insn_mode = "32 and 64";
   1070  1.1.1.1.2.2  perseant   else if (op->codewords[0].flags & kvxOPCODE_FLAG_MODE64)
   1071  1.1.1.1.2.2  perseant     insn_mode = "64";
   1072  1.1.1.1.2.2  perseant   else if (op->codewords[0].flags & kvxOPCODE_FLAG_MODE32)
   1073  1.1.1.1.2.2  perseant     insn_mode = "32";
   1074  1.1.1.1.2.2  perseant   else
   1075  1.1.1.1.2.2  perseant     as_fatal ("Unknown instruction mode.");
   1076  1.1.1.1.2.2  perseant 
   1077  1.1.1.1.2.2  perseant   printf ("%s | syllables: %d | type: %s | mode: %s bits\n", asm_str,
   1078  1.1.1.1.2.2  perseant 	  op->wordcount, insn_type, insn_mode);
   1079  1.1.1.1.2.2  perseant }
   1080  1.1.1.1.2.2  perseant 
   1081  1.1.1.1.2.2  perseant /* Comparison function compatible with qsort.  This is used to sort the issues
   1082  1.1.1.1.2.2  perseant    into the right order.  */
   1083  1.1.1.1.2.2  perseant static int
   1084  1.1.1.1.2.2  perseant kvxinsn_compare (const void *a, const void *b)
   1085  1.1.1.1.2.2  perseant {
   1086  1.1.1.1.2.2  perseant   struct kvxinsn *kvxinsn_a = *(struct kvxinsn **) a;
   1087  1.1.1.1.2.2  perseant   struct kvxinsn *kvxinsn_b = *(struct kvxinsn **) b;
   1088  1.1.1.1.2.2  perseant   int bundling_a = find_bundling (kvxinsn_a);
   1089  1.1.1.1.2.2  perseant   int bundling_b = find_bundling (kvxinsn_b);
   1090  1.1.1.1.2.2  perseant   int order_a = kvxinsn_a->order;
   1091  1.1.1.1.2.2  perseant   int order_b = kvxinsn_b->order;
   1092  1.1.1.1.2.2  perseant   if (bundling_a != bundling_b)
   1093  1.1.1.1.2.2  perseant     return (bundling_b < bundling_a) - (bundling_a < bundling_b);
   1094  1.1.1.1.2.2  perseant   return (order_b < order_a) - (order_a < order_b);
   1095  1.1.1.1.2.2  perseant }
   1096  1.1.1.1.2.2  perseant 
   1097  1.1.1.1.2.2  perseant static void
   1098  1.1.1.1.2.2  perseant kvx_reorder_bundle (struct kvxinsn *bundle_insn[], int bundle_insncnt)
   1099  1.1.1.1.2.2  perseant {
   1100  1.1.1.1.2.2  perseant   enum
   1101  1.1.1.1.2.2  perseant   { EXU_BCU, EXU_TCA, EXU_ALU0, EXU_ALU1, EXU_MAU, EXU_LSU, EXU__ };
   1102  1.1.1.1.2.2  perseant   struct kvxinsn *issued[EXU__];
   1103  1.1.1.1.2.2  perseant   int tag, exu;
   1104  1.1.1.1.2.2  perseant 
   1105  1.1.1.1.2.2  perseant   memset (issued, 0, sizeof (issued));
   1106  1.1.1.1.2.2  perseant   for (int i = 0; i < bundle_insncnt; i++)
   1107  1.1.1.1.2.2  perseant     {
   1108  1.1.1.1.2.2  perseant       struct kvxinsn *kvxinsn = bundle_insn[i];
   1109  1.1.1.1.2.2  perseant       tag = -1, exu = -1;
   1110  1.1.1.1.2.2  perseant       /* This is a hack. It works because all the Bundling are the same for all
   1111  1.1.1.1.2.2  perseant          cores for now.  */
   1112  1.1.1.1.2.2  perseant       switch ((int) find_bundling (kvxinsn))
   1113  1.1.1.1.2.2  perseant 	{
   1114  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_ALL:
   1115  1.1.1.1.2.2  perseant 	  if (bundle_insncnt > 1)
   1116  1.1.1.1.2.2  perseant 	    as_fatal ("Too many ops in a single op bundle");
   1117  1.1.1.1.2.2  perseant 	  issued[0] = kvxinsn;
   1118  1.1.1.1.2.2  perseant 	  break;
   1119  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_BCU:
   1120  1.1.1.1.2.2  perseant 	  if (!issued[EXU_BCU])
   1121  1.1.1.1.2.2  perseant 	    issued[EXU_BCU] = kvxinsn;
   1122  1.1.1.1.2.2  perseant 	  else
   1123  1.1.1.1.2.2  perseant 	    as_fatal ("More than one BCU instruction in bundle");
   1124  1.1.1.1.2.2  perseant 	  break;
   1125  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_TCA:
   1126  1.1.1.1.2.2  perseant 	  if (!issued[EXU_TCA])
   1127  1.1.1.1.2.2  perseant 	    issued[EXU_TCA] = kvxinsn;
   1128  1.1.1.1.2.2  perseant 	  else
   1129  1.1.1.1.2.2  perseant 	    as_fatal ("More than one TCA instruction in bundle");
   1130  1.1.1.1.2.2  perseant 	  break;
   1131  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_FULL:
   1132  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_FULL_X:
   1133  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_FULL_Y:
   1134  1.1.1.1.2.2  perseant 	  if (!issued[EXU_ALU0])
   1135  1.1.1.1.2.2  perseant 	    {
   1136  1.1.1.1.2.2  perseant 	      issued[EXU_ALU0] = kvxinsn;
   1137  1.1.1.1.2.2  perseant 	      tag = Modifier_kv3_v1_exunum_ALU0;
   1138  1.1.1.1.2.2  perseant 	      exu = EXU_ALU0;
   1139  1.1.1.1.2.2  perseant 	    }
   1140  1.1.1.1.2.2  perseant 	  else
   1141  1.1.1.1.2.2  perseant 	    as_fatal ("More than one ALU FULL instruction in bundle");
   1142  1.1.1.1.2.2  perseant 	  break;
   1143  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_LITE:
   1144  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_LITE_X:
   1145  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_LITE_Y:
   1146  1.1.1.1.2.2  perseant 	  if (!issued[EXU_ALU0])
   1147  1.1.1.1.2.2  perseant 	    {
   1148  1.1.1.1.2.2  perseant 	      issued[EXU_ALU0] = kvxinsn;
   1149  1.1.1.1.2.2  perseant 	      tag = Modifier_kv3_v1_exunum_ALU0;
   1150  1.1.1.1.2.2  perseant 	      exu = EXU_ALU0;
   1151  1.1.1.1.2.2  perseant 	    }
   1152  1.1.1.1.2.2  perseant 	  else if (!issued[EXU_ALU1])
   1153  1.1.1.1.2.2  perseant 	    {
   1154  1.1.1.1.2.2  perseant 	      issued[EXU_ALU1] = kvxinsn;
   1155  1.1.1.1.2.2  perseant 	      tag = Modifier_kv3_v1_exunum_ALU1;
   1156  1.1.1.1.2.2  perseant 	      exu = EXU_ALU1;
   1157  1.1.1.1.2.2  perseant 	    }
   1158  1.1.1.1.2.2  perseant 	  else
   1159  1.1.1.1.2.2  perseant 	    as_fatal ("Too many ALU FULL or LITE instructions in bundle");
   1160  1.1.1.1.2.2  perseant 	  break;
   1161  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_MAU:
   1162  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_MAU_X:
   1163  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_MAU_Y:
   1164  1.1.1.1.2.2  perseant 	  if (!issued[EXU_MAU])
   1165  1.1.1.1.2.2  perseant 	    {
   1166  1.1.1.1.2.2  perseant 	      issued[EXU_MAU] = kvxinsn;
   1167  1.1.1.1.2.2  perseant 	      tag = Modifier_kv3_v1_exunum_MAU;
   1168  1.1.1.1.2.2  perseant 	      exu = EXU_MAU;
   1169  1.1.1.1.2.2  perseant 	    }
   1170  1.1.1.1.2.2  perseant 	  else
   1171  1.1.1.1.2.2  perseant 	    as_fatal ("More than one MAU instruction in bundle");
   1172  1.1.1.1.2.2  perseant 	  break;
   1173  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_LSU:
   1174  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_LSU_X:
   1175  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_LSU_Y:
   1176  1.1.1.1.2.2  perseant 	  if (!issued[EXU_LSU])
   1177  1.1.1.1.2.2  perseant 	    {
   1178  1.1.1.1.2.2  perseant 	      issued[EXU_LSU] = kvxinsn;
   1179  1.1.1.1.2.2  perseant 	      tag = Modifier_kv3_v1_exunum_LSU;
   1180  1.1.1.1.2.2  perseant 	      exu = EXU_LSU;
   1181  1.1.1.1.2.2  perseant 	    }
   1182  1.1.1.1.2.2  perseant 	  else
   1183  1.1.1.1.2.2  perseant 	    as_fatal ("More than one LSU instruction in bundle");
   1184  1.1.1.1.2.2  perseant 	  break;
   1185  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_TINY:
   1186  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_TINY_X:
   1187  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_TINY_Y:
   1188  1.1.1.1.2.2  perseant 	case Bundling_kv3_v1_NOP:
   1189  1.1.1.1.2.2  perseant 	  if (!issued[EXU_ALU0])
   1190  1.1.1.1.2.2  perseant 	    {
   1191  1.1.1.1.2.2  perseant 	      issued[EXU_ALU0] = kvxinsn;
   1192  1.1.1.1.2.2  perseant 	      tag = Modifier_kv3_v1_exunum_ALU0;
   1193  1.1.1.1.2.2  perseant 	      exu = EXU_ALU0;
   1194  1.1.1.1.2.2  perseant 	    }
   1195  1.1.1.1.2.2  perseant 	  else if (!issued[EXU_ALU1])
   1196  1.1.1.1.2.2  perseant 	    {
   1197  1.1.1.1.2.2  perseant 	      issued[EXU_ALU1] = kvxinsn;
   1198  1.1.1.1.2.2  perseant 	      tag = Modifier_kv3_v1_exunum_ALU1;
   1199  1.1.1.1.2.2  perseant 	      exu = EXU_ALU1;
   1200  1.1.1.1.2.2  perseant 	    }
   1201  1.1.1.1.2.2  perseant 	  else if (!issued[EXU_MAU])
   1202  1.1.1.1.2.2  perseant 	    {
   1203  1.1.1.1.2.2  perseant 	      issued[EXU_MAU] = kvxinsn;
   1204  1.1.1.1.2.2  perseant 	      tag = Modifier_kv3_v1_exunum_MAU;
   1205  1.1.1.1.2.2  perseant 	      exu = EXU_MAU;
   1206  1.1.1.1.2.2  perseant 	    }
   1207  1.1.1.1.2.2  perseant 	  else if (!issued[EXU_LSU])
   1208  1.1.1.1.2.2  perseant 	    {
   1209  1.1.1.1.2.2  perseant 	      issued[EXU_LSU] = kvxinsn;
   1210  1.1.1.1.2.2  perseant 	      tag = Modifier_kv3_v1_exunum_LSU;
   1211  1.1.1.1.2.2  perseant 	      exu = EXU_LSU;
   1212  1.1.1.1.2.2  perseant 	    }
   1213  1.1.1.1.2.2  perseant 	  else
   1214  1.1.1.1.2.2  perseant 	    as_fatal ("Too many ALU instructions in bundle");
   1215  1.1.1.1.2.2  perseant 	  break;
   1216  1.1.1.1.2.2  perseant 	default:
   1217  1.1.1.1.2.2  perseant 	  as_fatal ("Unhandled Bundling class %d", find_bundling (kvxinsn));
   1218  1.1.1.1.2.2  perseant 	}
   1219  1.1.1.1.2.2  perseant       if (tag >= 0)
   1220  1.1.1.1.2.2  perseant 	{
   1221  1.1.1.1.2.2  perseant 	  if (issued[exu]->immx0 != NOIMMX)
   1222  1.1.1.1.2.2  perseant 	    immxbuf[issued[exu]->immx0].words[0] |= (tag << 27);
   1223  1.1.1.1.2.2  perseant 	  if (issued[exu]->immx1 != NOIMMX)
   1224  1.1.1.1.2.2  perseant 	    immxbuf[issued[exu]->immx1].words[0] |= (tag << 27);
   1225  1.1.1.1.2.2  perseant 	}
   1226  1.1.1.1.2.2  perseant     }
   1227  1.1.1.1.2.2  perseant 
   1228  1.1.1.1.2.2  perseant   int i;
   1229  1.1.1.1.2.2  perseant   for (i = 0, exu = 0; exu < EXU__; exu++)
   1230  1.1.1.1.2.2  perseant     {
   1231  1.1.1.1.2.2  perseant       if (issued[exu])
   1232  1.1.1.1.2.2  perseant 	bundle_insn[i++] = issued[exu];
   1233  1.1.1.1.2.2  perseant     }
   1234  1.1.1.1.2.2  perseant   if (i != bundle_insncnt)
   1235  1.1.1.1.2.2  perseant     as_fatal ("Mismatch between bundle and issued instructions");
   1236  1.1.1.1.2.2  perseant }
   1237  1.1.1.1.2.2  perseant 
   1238  1.1.1.1.2.2  perseant static void
   1239  1.1.1.1.2.2  perseant kvx_check_resource_usage (struct kvxinsn **bundle_insn, int bundle_insncnt)
   1240  1.1.1.1.2.2  perseant {
   1241  1.1.1.1.2.2  perseant   const int reservation_table_len =
   1242  1.1.1.1.2.2  perseant     (kvx_core_info->reservation_table_lines * kvx_core_info->resource_max);
   1243  1.1.1.1.2.2  perseant   const int *resources = kvx_core_info->resources;
   1244  1.1.1.1.2.2  perseant   int *resources_used =
   1245  1.1.1.1.2.2  perseant     malloc (reservation_table_len * sizeof (int));
   1246  1.1.1.1.2.2  perseant   memset (resources_used, 0, reservation_table_len * sizeof (int));
   1247  1.1.1.1.2.2  perseant 
   1248  1.1.1.1.2.2  perseant   for (int i = 0; i < bundle_insncnt; i++)
   1249  1.1.1.1.2.2  perseant   {
   1250  1.1.1.1.2.2  perseant     int insn_reservation = find_reservation (bundle_insn[i]);
   1251  1.1.1.1.2.2  perseant     int reservation = insn_reservation & 0xff;
   1252  1.1.1.1.2.2  perseant     const int *reservation_table = kvx_core_info->reservation_table_table[reservation];
   1253  1.1.1.1.2.2  perseant     for (int j = 0; j < reservation_table_len; j++)
   1254  1.1.1.1.2.2  perseant       resources_used[j] += reservation_table[j];
   1255  1.1.1.1.2.2  perseant   }
   1256  1.1.1.1.2.2  perseant 
   1257  1.1.1.1.2.2  perseant   for (int i = 0; i < kvx_core_info->reservation_table_lines; i++)
   1258  1.1.1.1.2.2  perseant     {
   1259  1.1.1.1.2.2  perseant       for (int j = 0; j < kvx_core_info->resource_max; j++)
   1260  1.1.1.1.2.2  perseant 	if (resources_used[(i * kvx_core_info->resource_max) + j] > resources[j])
   1261  1.1.1.1.2.2  perseant 	  {
   1262  1.1.1.1.2.2  perseant 	    int v = resources_used[(i * kvx_core_info->resource_max) + j];
   1263  1.1.1.1.2.2  perseant 	    free (resources_used);
   1264  1.1.1.1.2.2  perseant 	    as_fatal ("Resource %s over-used in bundle: %d used, %d available",
   1265  1.1.1.1.2.2  perseant 		kvx_core_info->resource_names[j], v, resources[j]);
   1266  1.1.1.1.2.2  perseant 	  }
   1267  1.1.1.1.2.2  perseant   }
   1268  1.1.1.1.2.2  perseant   free (resources_used);
   1269  1.1.1.1.2.2  perseant }
   1270  1.1.1.1.2.2  perseant 
   1271  1.1.1.1.2.2  perseant /*
   1272  1.1.1.1.2.2  perseant  * Called by core to assemble a single line
   1273  1.1.1.1.2.2  perseant  */
   1274  1.1.1.1.2.2  perseant void
   1275  1.1.1.1.2.2  perseant md_assemble (char *line)
   1276  1.1.1.1.2.2  perseant {
   1277  1.1.1.1.2.2  perseant   char *line_cursor = line;
   1278  1.1.1.1.2.2  perseant 
   1279  1.1.1.1.2.2  perseant   if (get_byte_counter (now_seg) & 3)
   1280  1.1.1.1.2.2  perseant     as_fatal ("code segment not word aligned in md_assemble");
   1281  1.1.1.1.2.2  perseant 
   1282  1.1.1.1.2.2  perseant   while (line_cursor && line_cursor[0] && (line_cursor[0] == ' '))
   1283  1.1.1.1.2.2  perseant     line_cursor++;
   1284  1.1.1.1.2.2  perseant 
   1285  1.1.1.1.2.2  perseant   /* ;; was converted to "be" by line hook          */
   1286  1.1.1.1.2.2  perseant   /* here we look for the bundle end                */
   1287  1.1.1.1.2.2  perseant   /* and actually output any instructions in bundle */
   1288  1.1.1.1.2.2  perseant   /* also we need to implement the stop bit         */
   1289  1.1.1.1.2.2  perseant   /* check for bundle end */
   1290  1.1.1.1.2.2  perseant   if (strncmp (line_cursor, "be", 2) == 0)
   1291  1.1.1.1.2.2  perseant   {
   1292  1.1.1.1.2.2  perseant     inside_bundle = 0;
   1293  1.1.1.1.2.2  perseant     //int sec_align = bfd_get_section_alignment(stdoutput, now_seg);
   1294  1.1.1.1.2.2  perseant     /* Was KVXMAXBUNDLEISSUE, changed because of NOPs */
   1295  1.1.1.1.2.2  perseant     struct kvxinsn *bundle_insn[KVXMAXBUNDLEWORDS];
   1296  1.1.1.1.2.2  perseant     int bundle_insncnt = 0;
   1297  1.1.1.1.2.2  perseant     int syllables = 0;
   1298  1.1.1.1.2.2  perseant     int entry;
   1299  1.1.1.1.2.2  perseant 
   1300  1.1.1.1.2.2  perseant #ifdef OBJ_ELF
   1301  1.1.1.1.2.2  perseant     /* Emit Dwarf debug line information */
   1302  1.1.1.1.2.2  perseant     dwarf2_emit_insn (0);
   1303  1.1.1.1.2.2  perseant #endif
   1304  1.1.1.1.2.2  perseant     for (int j = 0; j < insncnt; j++)
   1305  1.1.1.1.2.2  perseant     {
   1306  1.1.1.1.2.2  perseant       insbuf[j].order = j;
   1307  1.1.1.1.2.2  perseant       bundle_insn[bundle_insncnt++] = &insbuf[j];
   1308  1.1.1.1.2.2  perseant       syllables += insbuf[j].len;
   1309  1.1.1.1.2.2  perseant     }
   1310  1.1.1.1.2.2  perseant 
   1311  1.1.1.1.2.2  perseant     if (syllables + immxcnt > KVXMAXBUNDLEWORDS)
   1312  1.1.1.1.2.2  perseant       as_fatal ("Bundle has too many syllables : %d instead of %d",
   1313  1.1.1.1.2.2  perseant 	  syllables + immxcnt, KVXMAXBUNDLEWORDS);
   1314  1.1.1.1.2.2  perseant 
   1315  1.1.1.1.2.2  perseant     if (env.opts.check_resource_usage)
   1316  1.1.1.1.2.2  perseant       kvx_check_resource_usage (bundle_insn, bundle_insncnt);
   1317  1.1.1.1.2.2  perseant 
   1318  1.1.1.1.2.2  perseant     /* Reorder and check the bundle.  */
   1319  1.1.1.1.2.2  perseant     if (!env.opts.generate_illegal_code)
   1320  1.1.1.1.2.2  perseant     {
   1321  1.1.1.1.2.2  perseant       /* Sort the bundle_insn in order of bundling. */
   1322  1.1.1.1.2.2  perseant       qsort (bundle_insn, bundle_insncnt, sizeof (struct kvxinsn *), kvxinsn_compare);
   1323  1.1.1.1.2.2  perseant 
   1324  1.1.1.1.2.2  perseant       kvx_reorder_bundle (bundle_insn, bundle_insncnt);
   1325  1.1.1.1.2.2  perseant     }
   1326  1.1.1.1.2.2  perseant 
   1327  1.1.1.1.2.2  perseant     /* The ordering of the insns has been set correctly in bundle_insn. */
   1328  1.1.1.1.2.2  perseant     for (int i = 0; i < bundle_insncnt; i++)
   1329  1.1.1.1.2.2  perseant     {
   1330  1.1.1.1.2.2  perseant       emit_insn (bundle_insn[i], i, (i == bundle_insncnt + immxcnt - 1));
   1331  1.1.1.1.2.2  perseant       bundle_insn[i]->written = 1;
   1332  1.1.1.1.2.2  perseant     }
   1333  1.1.1.1.2.2  perseant 
   1334  1.1.1.1.2.2  perseant     // Emit immx, ordering them by EXU tags, 0 to 3
   1335  1.1.1.1.2.2  perseant     entry = 0;
   1336  1.1.1.1.2.2  perseant     for (int tag = 0; tag < 4; tag++)
   1337  1.1.1.1.2.2  perseant     {
   1338  1.1.1.1.2.2  perseant       for (int j = 0; j < immxcnt; j++)
   1339  1.1.1.1.2.2  perseant       {
   1340  1.1.1.1.2.2  perseant #define kv3_exunum2_fld(x) (int)(((unsigned int)(x) >> 27) & 0x3)
   1341  1.1.1.1.2.2  perseant 	if (kv3_exunum2_fld (immxbuf[j].words[0]) == tag)
   1342  1.1.1.1.2.2  perseant 	{
   1343  1.1.1.1.2.2  perseant 	  assert (immxbuf[j].written == 0);
   1344  1.1.1.1.2.2  perseant 	  int insn_pos = bundle_insncnt + entry;
   1345  1.1.1.1.2.2  perseant 	  emit_insn (&(immxbuf[j]), insn_pos, entry == immxcnt - 1);
   1346  1.1.1.1.2.2  perseant 	  immxbuf[j].written = 1;
   1347  1.1.1.1.2.2  perseant 	  entry++;
   1348  1.1.1.1.2.2  perseant 	}
   1349  1.1.1.1.2.2  perseant #undef kv3_exunum2_fld
   1350  1.1.1.1.2.2  perseant       }
   1351  1.1.1.1.2.2  perseant     }
   1352  1.1.1.1.2.2  perseant     if (entry != immxcnt)
   1353  1.1.1.1.2.2  perseant       as_fatal ("%d IMMX produced, only %d emitted.", immxcnt, entry);
   1354  1.1.1.1.2.2  perseant 
   1355  1.1.1.1.2.2  perseant     /* The debug label that appear in the middle of bundles
   1356  1.1.1.1.2.2  perseant        had better appear to be attached to the next
   1357  1.1.1.1.2.2  perseant        bundle. This is because usually these labels point to
   1358  1.1.1.1.2.2  perseant        the first instruction where some condition is met. If
   1359  1.1.1.1.2.2  perseant        the label isn't handled this way it will be attached to
   1360  1.1.1.1.2.2  perseant        the current bundle which is wrong as the corresponding
   1361  1.1.1.1.2.2  perseant        instruction wasn't executed yet. */
   1362  1.1.1.1.2.2  perseant     while (label_fixes)
   1363  1.1.1.1.2.2  perseant     {
   1364  1.1.1.1.2.2  perseant       struct label_fix *fix = label_fixes;
   1365  1.1.1.1.2.2  perseant 
   1366  1.1.1.1.2.2  perseant       label_fixes = fix->next;
   1367  1.1.1.1.2.2  perseant       symbol_set_value_now (fix->sym);
   1368  1.1.1.1.2.2  perseant       free (fix);
   1369  1.1.1.1.2.2  perseant     }
   1370  1.1.1.1.2.2  perseant 
   1371  1.1.1.1.2.2  perseant     insncnt = 0;
   1372  1.1.1.1.2.2  perseant     immxcnt = 0;
   1373  1.1.1.1.2.2  perseant     memset (immxbuf, 0, sizeof (immxbuf));
   1374  1.1.1.1.2.2  perseant 
   1375  1.1.1.1.2.2  perseant     return;
   1376  1.1.1.1.2.2  perseant   }
   1377  1.1.1.1.2.2  perseant 
   1378  1.1.1.1.2.2  perseant     char *buf = NULL;
   1379  1.1.1.1.2.2  perseant     sscanf (line_cursor, "%m[^\n]", &buf);
   1380  1.1.1.1.2.2  perseant     struct token_s my_tok = { .insn = buf, .begin = 0, .end = 0, .class_id = -1 , .val = 0 };
   1381  1.1.1.1.2.2  perseant     struct token_list *tok_lst = parse (my_tok);
   1382  1.1.1.1.2.2  perseant     free (buf);
   1383  1.1.1.1.2.2  perseant 
   1384  1.1.1.1.2.2  perseant     if (!tok_lst)
   1385  1.1.1.1.2.2  perseant       return;
   1386  1.1.1.1.2.2  perseant 
   1387  1.1.1.1.2.2  perseant     /* Skip opcode */
   1388  1.1.1.1.2.2  perseant     line_cursor += strlen (tok_lst->tok);
   1389  1.1.1.1.2.2  perseant 
   1390  1.1.1.1.2.2  perseant   assembling_insn = true;
   1391  1.1.1.1.2.2  perseant 
   1392  1.1.1.1.2.2  perseant   inside_bundle = 1;
   1393  1.1.1.1.2.2  perseant   assemble_tokens (tok_lst);
   1394  1.1.1.1.2.2  perseant   free_token_list (tok_lst);
   1395  1.1.1.1.2.2  perseant   assembling_insn = false;
   1396  1.1.1.1.2.2  perseant }
   1397  1.1.1.1.2.2  perseant 
   1398  1.1.1.1.2.2  perseant static void
   1399  1.1.1.1.2.2  perseant kvx_set_cpu (void)
   1400  1.1.1.1.2.2  perseant {
   1401  1.1.1.1.2.2  perseant   if (!kvx_core_info)
   1402  1.1.1.1.2.2  perseant     kvx_core_info = &kvx_kv3_v1_core_info;
   1403  1.1.1.1.2.2  perseant 
   1404  1.1.1.1.2.2  perseant   if (!kvx_registers)
   1405  1.1.1.1.2.2  perseant     kvx_registers = kvx_kv3_v1_registers;
   1406  1.1.1.1.2.2  perseant 
   1407  1.1.1.1.2.2  perseant   if (!kvx_regfiles)
   1408  1.1.1.1.2.2  perseant     kvx_regfiles = kvx_kv3_v1_regfiles;
   1409  1.1.1.1.2.2  perseant 
   1410  1.1.1.1.2.2  perseant   if (!kvx_modifiers)
   1411  1.1.1.1.2.2  perseant     kvx_modifiers = kvx_kv3_v1_modifiers;
   1412  1.1.1.1.2.2  perseant 
   1413  1.1.1.1.2.2  perseant   if (env.params.core == -1)
   1414  1.1.1.1.2.2  perseant       env.params.core = kvx_core_info->elf_core;
   1415  1.1.1.1.2.2  perseant 
   1416  1.1.1.1.2.2  perseant   int kvx_bfd_mach;
   1417  1.1.1.1.2.2  perseant   print_insn = kvx_print_insn;
   1418  1.1.1.1.2.2  perseant 
   1419  1.1.1.1.2.2  perseant   switch (kvx_core_info->elf_core)
   1420  1.1.1.1.2.2  perseant     {
   1421  1.1.1.1.2.2  perseant     case ELF_KVX_CORE_KV3_1:
   1422  1.1.1.1.2.2  perseant       kvx_bfd_mach = env.params.arch_size == 32 ? bfd_mach_kv3_1 : bfd_mach_kv3_1_64;
   1423  1.1.1.1.2.2  perseant       setup (ELF_KVX_CORE_KV3_1);
   1424  1.1.1.1.2.2  perseant       break;
   1425  1.1.1.1.2.2  perseant     case ELF_KVX_CORE_KV3_2:
   1426  1.1.1.1.2.2  perseant       kvx_bfd_mach = env.params.arch_size == 32 ? bfd_mach_kv3_2 : bfd_mach_kv3_2_64;
   1427  1.1.1.1.2.2  perseant       setup (ELF_KVX_CORE_KV3_2);
   1428  1.1.1.1.2.2  perseant       break;
   1429  1.1.1.1.2.2  perseant     case ELF_KVX_CORE_KV4_1:
   1430  1.1.1.1.2.2  perseant       kvx_bfd_mach = env.params.arch_size == 32 ? bfd_mach_kv4_1 : bfd_mach_kv4_1_64;
   1431  1.1.1.1.2.2  perseant       setup (ELF_KVX_CORE_KV4_1);
   1432  1.1.1.1.2.2  perseant       break;
   1433  1.1.1.1.2.2  perseant     default:
   1434  1.1.1.1.2.2  perseant       as_fatal ("Unknown elf core: 0x%x", kvx_core_info->elf_core);
   1435  1.1.1.1.2.2  perseant     }
   1436  1.1.1.1.2.2  perseant 
   1437  1.1.1.1.2.2  perseant   if (!bfd_set_arch_mach (stdoutput, TARGET_ARCH, kvx_bfd_mach))
   1438  1.1.1.1.2.2  perseant     as_warn (_("could not set architecture and machine"));
   1439  1.1.1.1.2.2  perseant }
   1440  1.1.1.1.2.2  perseant 
   1441  1.1.1.1.2.2  perseant static int
   1442  1.1.1.1.2.2  perseant kvxop_compar (const void *a, const void *b)
   1443  1.1.1.1.2.2  perseant {
   1444  1.1.1.1.2.2  perseant   const struct kvxopc *opa = (const struct kvxopc *) a;
   1445  1.1.1.1.2.2  perseant   const struct kvxopc *opb = (const struct kvxopc *) b;
   1446  1.1.1.1.2.2  perseant   int res = strcmp (opa->as_op, opb->as_op);
   1447  1.1.1.1.2.2  perseant 
   1448  1.1.1.1.2.2  perseant   if (res)
   1449  1.1.1.1.2.2  perseant     return res;
   1450  1.1.1.1.2.2  perseant   else
   1451  1.1.1.1.2.2  perseant     {
   1452  1.1.1.1.2.2  perseant       for (int i = 0; opa->format[i] && opb->format[i]; ++i)
   1453  1.1.1.1.2.2  perseant 	if (opa->format[i]->width != opb->format[i]->width)
   1454  1.1.1.1.2.2  perseant 	  return opa->format[i]->width - opb->format[i]->width;
   1455  1.1.1.1.2.2  perseant       return 0;
   1456  1.1.1.1.2.2  perseant     }
   1457  1.1.1.1.2.2  perseant }
   1458  1.1.1.1.2.2  perseant 
   1459  1.1.1.1.2.2  perseant /***************************************************/
   1460  1.1.1.1.2.2  perseant /*    INITIALIZE ASSEMBLER                         */
   1461  1.1.1.1.2.2  perseant /***************************************************/
   1462  1.1.1.1.2.2  perseant 
   1463  1.1.1.1.2.2  perseant static int
   1464  1.1.1.1.2.2  perseant print_hash (void **slot, void *arg ATTRIBUTE_UNUSED)
   1465  1.1.1.1.2.2  perseant {
   1466  1.1.1.1.2.2  perseant   string_tuple_t *tuple = *((string_tuple_t **) slot);
   1467  1.1.1.1.2.2  perseant   printf ("%s\n", tuple->key);
   1468  1.1.1.1.2.2  perseant   return 1;
   1469  1.1.1.1.2.2  perseant }
   1470  1.1.1.1.2.2  perseant 
   1471  1.1.1.1.2.2  perseant static void
   1472  1.1.1.1.2.2  perseant declare_register (const char *name, int number)
   1473  1.1.1.1.2.2  perseant {
   1474  1.1.1.1.2.2  perseant   symbolS *regS = symbol_create (name, reg_section,
   1475  1.1.1.1.2.2  perseant 				 &zero_address_frag, number);
   1476  1.1.1.1.2.2  perseant 
   1477  1.1.1.1.2.2  perseant   if (str_hash_insert (env.reg_hash, S_GET_NAME (regS), regS, 0) != NULL)
   1478  1.1.1.1.2.2  perseant     as_fatal (_("duplicate %s"), name);
   1479  1.1.1.1.2.2  perseant }
   1480  1.1.1.1.2.2  perseant 
   1481  1.1.1.1.2.2  perseant void
   1482  1.1.1.1.2.2  perseant md_begin ()
   1483  1.1.1.1.2.2  perseant {
   1484  1.1.1.1.2.2  perseant   kvx_set_cpu ();
   1485  1.1.1.1.2.2  perseant 
   1486  1.1.1.1.2.2  perseant   /*
   1487  1.1.1.1.2.2  perseant    * Declare register names with symbols
   1488  1.1.1.1.2.2  perseant    */
   1489  1.1.1.1.2.2  perseant 
   1490  1.1.1.1.2.2  perseant   env.reg_hash = str_htab_create ();
   1491  1.1.1.1.2.2  perseant 
   1492  1.1.1.1.2.2  perseant   for (int i = 0; i < kvx_regfiles[KVX_REGFILE_REGISTERS]; i++)
   1493  1.1.1.1.2.2  perseant     declare_register (kvx_registers[i].name, kvx_registers[i].id);
   1494  1.1.1.1.2.2  perseant 
   1495  1.1.1.1.2.2  perseant   /* Sort optab, so that identical mnemonics appear consecutively */
   1496  1.1.1.1.2.2  perseant   {
   1497  1.1.1.1.2.2  perseant     int nel;
   1498  1.1.1.1.2.2  perseant     for (nel = 0; !STREQ ("", kvx_core_info->optab[nel].as_op); nel++)
   1499  1.1.1.1.2.2  perseant       ;
   1500  1.1.1.1.2.2  perseant     qsort (kvx_core_info->optab, nel, sizeof (kvx_core_info->optab[0]),
   1501  1.1.1.1.2.2  perseant 	   kvxop_compar);
   1502  1.1.1.1.2.2  perseant   }
   1503  1.1.1.1.2.2  perseant 
   1504  1.1.1.1.2.2  perseant   /* The '?' is an operand separator */
   1505  1.1.1.1.2.2  perseant   lex_type['?'] = 0;
   1506  1.1.1.1.2.2  perseant 
   1507  1.1.1.1.2.2  perseant   /* Create the opcode hash table      */
   1508  1.1.1.1.2.2  perseant   /* Each name should appear only once */
   1509  1.1.1.1.2.2  perseant 
   1510  1.1.1.1.2.2  perseant   env.opcode_hash = str_htab_create ();
   1511  1.1.1.1.2.2  perseant   env.reloc_hash = str_htab_create ();
   1512  1.1.1.1.2.2  perseant 
   1513  1.1.1.1.2.2  perseant   {
   1514  1.1.1.1.2.2  perseant     struct kvxopc *op;
   1515  1.1.1.1.2.2  perseant     const char *name = 0;
   1516  1.1.1.1.2.2  perseant     for (op = kvx_core_info->optab; !(STREQ ("", op->as_op)); op++)
   1517  1.1.1.1.2.2  perseant       {
   1518  1.1.1.1.2.2  perseant 	/* enter in hash table if this is a new name */
   1519  1.1.1.1.2.2  perseant 	if (!(STREQ (name, op->as_op)))
   1520  1.1.1.1.2.2  perseant 	  {
   1521  1.1.1.1.2.2  perseant 	    name = op->as_op;
   1522  1.1.1.1.2.2  perseant 	    if (str_hash_insert (env.opcode_hash, name, op, 0))
   1523  1.1.1.1.2.2  perseant 	      as_fatal ("internal error: can't hash opcode `%s'", name);
   1524  1.1.1.1.2.2  perseant 	  }
   1525  1.1.1.1.2.2  perseant 
   1526  1.1.1.1.2.2  perseant 
   1527  1.1.1.1.2.2  perseant 	for (int i = 0 ; op->format[i] ; ++i)
   1528  1.1.1.1.2.2  perseant 	  {
   1529  1.1.1.1.2.2  perseant 	    const char *reloc_name = TOKEN_NAME (op->format[i]->type);
   1530  1.1.1.1.2.2  perseant 	    void *relocs = op->format[i]->relocs;
   1531  1.1.1.1.2.2  perseant 	    if (op->format[i]->relocs[0] != 0
   1532  1.1.1.1.2.2  perseant 		&& !str_hash_find (env.reloc_hash, reloc_name))
   1533  1.1.1.1.2.2  perseant 	      if (str_hash_insert (env.reloc_hash, reloc_name, relocs, 0))
   1534  1.1.1.1.2.2  perseant 		  as_fatal ("internal error: can't hash type `%s'", reloc_name);
   1535  1.1.1.1.2.2  perseant 	  }
   1536  1.1.1.1.2.2  perseant       }
   1537  1.1.1.1.2.2  perseant   }
   1538  1.1.1.1.2.2  perseant 
   1539  1.1.1.1.2.2  perseant   if (env.opts.dump_table)
   1540  1.1.1.1.2.2  perseant     {
   1541  1.1.1.1.2.2  perseant       htab_traverse (env.opcode_hash, print_hash, NULL);
   1542  1.1.1.1.2.2  perseant       exit (0);
   1543  1.1.1.1.2.2  perseant     }
   1544  1.1.1.1.2.2  perseant 
   1545  1.1.1.1.2.2  perseant   if (env.opts.dump_insn)
   1546  1.1.1.1.2.2  perseant     {
   1547  1.1.1.1.2.2  perseant       for (struct kvxopc *op = kvx_core_info->optab; !(STREQ ("", op->as_op)); op++)
   1548  1.1.1.1.2.2  perseant 	print_insn (op);
   1549  1.1.1.1.2.2  perseant       exit (0);
   1550  1.1.1.1.2.2  perseant     }
   1551  1.1.1.1.2.2  perseant 
   1552  1.1.1.1.2.2  perseant   /* Here we enforce the minimum section alignment.  Remember, in
   1553  1.1.1.1.2.2  perseant    * the linker we can make the boudaries between the linked sections
   1554  1.1.1.1.2.2  perseant    * on larger boundaries.  The text segment is aligned to long words
   1555  1.1.1.1.2.2  perseant    * because of the odd/even constraint on immediate extensions
   1556  1.1.1.1.2.2  perseant    */
   1557  1.1.1.1.2.2  perseant 
   1558  1.1.1.1.2.2  perseant   bfd_set_section_alignment (text_section, 3);	/* -- 8 bytes */
   1559  1.1.1.1.2.2  perseant   bfd_set_section_alignment (data_section, 2);	/* -- 4 bytes */
   1560  1.1.1.1.2.2  perseant   bfd_set_section_alignment (bss_section, 2);	/* -- 4 bytes */
   1561  1.1.1.1.2.2  perseant   subseg_set (text_section, 0);
   1562  1.1.1.1.2.2  perseant 
   1563  1.1.1.1.2.2  perseant   symbolS *gotoff_sym   = symbol_create (".<gotoff>",   undefined_section, &zero_address_frag, 0);
   1564  1.1.1.1.2.2  perseant   symbolS *got_sym      = symbol_create (".<got>",      undefined_section, &zero_address_frag, 0);
   1565  1.1.1.1.2.2  perseant   symbolS *plt_sym      = symbol_create (".<plt>",      undefined_section, &zero_address_frag, 0);
   1566  1.1.1.1.2.2  perseant   symbolS *tlsgd_sym    = symbol_create (".<tlsgd>",    undefined_section, &zero_address_frag, 0);
   1567  1.1.1.1.2.2  perseant   symbolS *tlsie_sym    = symbol_create (".<tlsie>",    undefined_section, &zero_address_frag, 0);
   1568  1.1.1.1.2.2  perseant   symbolS *tlsle_sym    = symbol_create (".<tlsle>",    undefined_section, &zero_address_frag, 0);
   1569  1.1.1.1.2.2  perseant   symbolS *tlsld_sym    = symbol_create (".<tlsld>",    undefined_section, &zero_address_frag, 0);
   1570  1.1.1.1.2.2  perseant   symbolS *dtpoff_sym   = symbol_create (".<dtpoff>",   undefined_section, &zero_address_frag, 0);
   1571  1.1.1.1.2.2  perseant   symbolS *plt64_sym    = symbol_create (".<plt64>",    undefined_section, &zero_address_frag, 0);
   1572  1.1.1.1.2.2  perseant   symbolS *gotaddr_sym  = symbol_create (".<gotaddr>",  undefined_section, &zero_address_frag, 0);
   1573  1.1.1.1.2.2  perseant   symbolS *pcrel16_sym  = symbol_create (".<pcrel16>",  undefined_section, &zero_address_frag, 0);
   1574  1.1.1.1.2.2  perseant   symbolS *pcrel_sym    = symbol_create (".<pcrel>",    undefined_section, &zero_address_frag, 0);
   1575  1.1.1.1.2.2  perseant   symbolS *signed32_sym = symbol_create (".<signed32>", undefined_section, &zero_address_frag, 0);
   1576  1.1.1.1.2.2  perseant 
   1577  1.1.1.1.2.2  perseant   for (int i = 0; i < kvx_core_info->nb_pseudo_funcs; ++i)
   1578  1.1.1.1.2.2  perseant     {
   1579  1.1.1.1.2.2  perseant       symbolS *sym;
   1580  1.1.1.1.2.2  perseant       if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "gotoff"))
   1581  1.1.1.1.2.2  perseant 	sym = gotoff_sym;
   1582  1.1.1.1.2.2  perseant       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "got"))
   1583  1.1.1.1.2.2  perseant 	sym = got_sym;
   1584  1.1.1.1.2.2  perseant       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "plt"))
   1585  1.1.1.1.2.2  perseant 	sym = plt_sym;
   1586  1.1.1.1.2.2  perseant       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "tlsgd"))
   1587  1.1.1.1.2.2  perseant 	sym = tlsgd_sym;
   1588  1.1.1.1.2.2  perseant       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "tlsle"))
   1589  1.1.1.1.2.2  perseant 	sym = tlsle_sym;
   1590  1.1.1.1.2.2  perseant       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "tlsld"))
   1591  1.1.1.1.2.2  perseant 	sym = tlsld_sym;
   1592  1.1.1.1.2.2  perseant       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "dtpoff"))
   1593  1.1.1.1.2.2  perseant 	sym = dtpoff_sym;
   1594  1.1.1.1.2.2  perseant       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "tlsie"))
   1595  1.1.1.1.2.2  perseant 	sym = tlsie_sym;
   1596  1.1.1.1.2.2  perseant       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "plt64"))
   1597  1.1.1.1.2.2  perseant 	sym = plt64_sym;
   1598  1.1.1.1.2.2  perseant       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "pcrel16"))
   1599  1.1.1.1.2.2  perseant 	sym = pcrel16_sym;
   1600  1.1.1.1.2.2  perseant       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "pcrel"))
   1601  1.1.1.1.2.2  perseant 	sym = pcrel_sym;
   1602  1.1.1.1.2.2  perseant       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "gotaddr"))
   1603  1.1.1.1.2.2  perseant 	sym = gotaddr_sym;
   1604  1.1.1.1.2.2  perseant       else if (!strcmp (kvx_core_info->pseudo_funcs[i].name, "signed32"))
   1605  1.1.1.1.2.2  perseant 	sym = signed32_sym;
   1606  1.1.1.1.2.2  perseant       else
   1607  1.1.1.1.2.2  perseant 	as_fatal ("internal error: Unknown pseudo func `%s'",
   1608  1.1.1.1.2.2  perseant 	    kvx_core_info->pseudo_funcs[i].name);
   1609  1.1.1.1.2.2  perseant 
   1610  1.1.1.1.2.2  perseant       kvx_core_info->pseudo_funcs[i].sym = sym;
   1611  1.1.1.1.2.2  perseant     }
   1612  1.1.1.1.2.2  perseant }
   1613  1.1.1.1.2.2  perseant 
   1614  1.1.1.1.2.2  perseant /***************************************************/
   1615  1.1.1.1.2.2  perseant /*          ASSEMBLER CLEANUP STUFF                */
   1616  1.1.1.1.2.2  perseant /***************************************************/
   1617  1.1.1.1.2.2  perseant 
   1618  1.1.1.1.2.2  perseant /* Return non-zero if the indicated VALUE has overflowed the maximum
   1619  1.1.1.1.2.2  perseant    range expressible by a signed number with the indicated number of
   1620  1.1.1.1.2.2  perseant    BITS.
   1621  1.1.1.1.2.2  perseant 
   1622  1.1.1.1.2.2  perseant    This is from tc-aarch64.c
   1623  1.1.1.1.2.2  perseant */
   1624  1.1.1.1.2.2  perseant 
   1625  1.1.1.1.2.2  perseant static bfd_boolean
   1626  1.1.1.1.2.2  perseant signed_overflow (offsetT value, unsigned bits)
   1627  1.1.1.1.2.2  perseant {
   1628  1.1.1.1.2.2  perseant   offsetT lim;
   1629  1.1.1.1.2.2  perseant   if (bits >= sizeof (offsetT) * 8)
   1630  1.1.1.1.2.2  perseant     return FALSE;
   1631  1.1.1.1.2.2  perseant   lim = (offsetT) 1 << (bits - 1);
   1632  1.1.1.1.2.2  perseant   return (value < -lim || value >= lim);
   1633  1.1.1.1.2.2  perseant }
   1634  1.1.1.1.2.2  perseant 
   1635  1.1.1.1.2.2  perseant /***************************************************/
   1636  1.1.1.1.2.2  perseant /*          ASSEMBLER FIXUP STUFF                  */
   1637  1.1.1.1.2.2  perseant /***************************************************/
   1638  1.1.1.1.2.2  perseant 
   1639  1.1.1.1.2.2  perseant void
   1640  1.1.1.1.2.2  perseant md_apply_fix (fixS * fixP, valueT * valueP, segT segmentP ATTRIBUTE_UNUSED)
   1641  1.1.1.1.2.2  perseant {
   1642  1.1.1.1.2.2  perseant   char *const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
   1643  1.1.1.1.2.2  perseant   valueT value = *valueP;
   1644  1.1.1.1.2.2  perseant   valueT image;
   1645  1.1.1.1.2.2  perseant   arelent *rel;
   1646  1.1.1.1.2.2  perseant 
   1647  1.1.1.1.2.2  perseant   rel = (arelent *) xmalloc (sizeof (arelent));
   1648  1.1.1.1.2.2  perseant 
   1649  1.1.1.1.2.2  perseant   rel->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type);
   1650  1.1.1.1.2.2  perseant   if (rel->howto == NULL)
   1651  1.1.1.1.2.2  perseant     {
   1652  1.1.1.1.2.2  perseant       as_fatal
   1653  1.1.1.1.2.2  perseant 	("[md_apply_fix] unsupported relocation type (can't find howto)");
   1654  1.1.1.1.2.2  perseant     }
   1655  1.1.1.1.2.2  perseant 
   1656  1.1.1.1.2.2  perseant   /* Note whether this will delete the relocation.  */
   1657  1.1.1.1.2.2  perseant   if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
   1658  1.1.1.1.2.2  perseant     fixP->fx_done = 1;
   1659  1.1.1.1.2.2  perseant 
   1660  1.1.1.1.2.2  perseant   if (fixP->fx_size > 0)
   1661  1.1.1.1.2.2  perseant     image = md_chars_to_number (fixpos, fixP->fx_size);
   1662  1.1.1.1.2.2  perseant   else
   1663  1.1.1.1.2.2  perseant     image = 0;
   1664  1.1.1.1.2.2  perseant   if (fixP->fx_addsy != NULL)
   1665  1.1.1.1.2.2  perseant     {
   1666  1.1.1.1.2.2  perseant       switch (fixP->fx_r_type)
   1667  1.1.1.1.2.2  perseant 	{
   1668  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_TLS_LE_UP27:
   1669  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_TLS_LE_LO10:
   1670  1.1.1.1.2.2  perseant 
   1671  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_TLS_LE_EX6:
   1672  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_TLS_LE_UP27:
   1673  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_TLS_LE_LO10:
   1674  1.1.1.1.2.2  perseant 
   1675  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_TLS_GD_LO10:
   1676  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_TLS_GD_UP27:
   1677  1.1.1.1.2.2  perseant 
   1678  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_TLS_GD_LO10:
   1679  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_TLS_GD_UP27:
   1680  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_TLS_GD_EX6:
   1681  1.1.1.1.2.2  perseant 
   1682  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_TLS_IE_LO10:
   1683  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_TLS_IE_UP27:
   1684  1.1.1.1.2.2  perseant 
   1685  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_TLS_IE_LO10:
   1686  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_TLS_IE_UP27:
   1687  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_TLS_IE_EX6:
   1688  1.1.1.1.2.2  perseant 
   1689  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_TLS_LD_LO10:
   1690  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_TLS_LD_UP27:
   1691  1.1.1.1.2.2  perseant 
   1692  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_TLS_LD_LO10:
   1693  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_TLS_LD_UP27:
   1694  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_TLS_LD_EX6:
   1695  1.1.1.1.2.2  perseant 
   1696  1.1.1.1.2.2  perseant 	  S_SET_THREAD_LOCAL (fixP->fx_addsy);
   1697  1.1.1.1.2.2  perseant 	  break;
   1698  1.1.1.1.2.2  perseant 	default:
   1699  1.1.1.1.2.2  perseant 	  break;
   1700  1.1.1.1.2.2  perseant 	}
   1701  1.1.1.1.2.2  perseant     }
   1702  1.1.1.1.2.2  perseant 
   1703  1.1.1.1.2.2  perseant   /* If relocation has been marked for deletion, apply remaining changes */
   1704  1.1.1.1.2.2  perseant   if (fixP->fx_done)
   1705  1.1.1.1.2.2  perseant     {
   1706  1.1.1.1.2.2  perseant       switch (fixP->fx_r_type)
   1707  1.1.1.1.2.2  perseant 	{
   1708  1.1.1.1.2.2  perseant 	case BFD_RELOC_8:
   1709  1.1.1.1.2.2  perseant 	case BFD_RELOC_16:
   1710  1.1.1.1.2.2  perseant 	case BFD_RELOC_32:
   1711  1.1.1.1.2.2  perseant 	case BFD_RELOC_64:
   1712  1.1.1.1.2.2  perseant 
   1713  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_GLOB_DAT:
   1714  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_32_GOT:
   1715  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_64_GOT:
   1716  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_64_GOTOFF:
   1717  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_32_GOTOFF:
   1718  1.1.1.1.2.2  perseant 	  image = value;
   1719  1.1.1.1.2.2  perseant 	  md_number_to_chars (fixpos, image, fixP->fx_size);
   1720  1.1.1.1.2.2  perseant 	  break;
   1721  1.1.1.1.2.2  perseant 
   1722  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_PCREL17:
   1723  1.1.1.1.2.2  perseant 	  if (signed_overflow (value, 17 + 2))
   1724  1.1.1.1.2.2  perseant 	    as_bad_where (fixP->fx_file, fixP->fx_line,
   1725  1.1.1.1.2.2  perseant 			  _("branch out of range"));
   1726  1.1.1.1.2.2  perseant 	  goto pcrel_common;
   1727  1.1.1.1.2.2  perseant 
   1728  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_PCREL27:
   1729  1.1.1.1.2.2  perseant 	  if (signed_overflow (value, 27 + 2))
   1730  1.1.1.1.2.2  perseant 	    as_bad_where (fixP->fx_file, fixP->fx_line,
   1731  1.1.1.1.2.2  perseant 			  _("branch out of range"));
   1732  1.1.1.1.2.2  perseant 	  goto pcrel_common;
   1733  1.1.1.1.2.2  perseant 
   1734  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S16_PCREL:
   1735  1.1.1.1.2.2  perseant 	  if (signed_overflow (value, 16))
   1736  1.1.1.1.2.2  perseant 	    as_bad_where (fixP->fx_file, fixP->fx_line,
   1737  1.1.1.1.2.2  perseant 			  _("signed16 PCREL value out of range"));
   1738  1.1.1.1.2.2  perseant 	  goto pcrel_common;
   1739  1.1.1.1.2.2  perseant 
   1740  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_PCREL_LO10:
   1741  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_PCREL_UP27:
   1742  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_PCREL_EX6:
   1743  1.1.1.1.2.2  perseant 	  if (signed_overflow (value, 10 + 27 + 6))
   1744  1.1.1.1.2.2  perseant 	    as_bad_where (fixP->fx_file, fixP->fx_line,
   1745  1.1.1.1.2.2  perseant 			  _("signed43 PCREL value out of range"));
   1746  1.1.1.1.2.2  perseant 	  goto pcrel_common;
   1747  1.1.1.1.2.2  perseant 
   1748  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_PCREL_LO10:
   1749  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_PCREL_UP27:
   1750  1.1.1.1.2.2  perseant 	  if (signed_overflow (value, 10 + 27))
   1751  1.1.1.1.2.2  perseant 	    as_bad_where (fixP->fx_file, fixP->fx_line,
   1752  1.1.1.1.2.2  perseant 			  _("signed37 PCREL value out of range"));
   1753  1.1.1.1.2.2  perseant 	  goto pcrel_common;
   1754  1.1.1.1.2.2  perseant 
   1755  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S64_PCREL_LO10:
   1756  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S64_PCREL_UP27:
   1757  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S64_PCREL_EX27:
   1758  1.1.1.1.2.2  perseant 
   1759  1.1.1.1.2.2  perseant 	pcrel_common:
   1760  1.1.1.1.2.2  perseant 	  if (fixP->fx_pcrel || fixP->fx_addsy)
   1761  1.1.1.1.2.2  perseant 	    return;
   1762  1.1.1.1.2.2  perseant 	  value =
   1763  1.1.1.1.2.2  perseant 	    (((value >> rel->howto->rightshift) << rel->howto->bitpos) & rel->
   1764  1.1.1.1.2.2  perseant 	     howto->dst_mask);
   1765  1.1.1.1.2.2  perseant 	  image = (image & ~(rel->howto->dst_mask)) | value;
   1766  1.1.1.1.2.2  perseant 	  md_number_to_chars (fixpos, image, fixP->fx_size);
   1767  1.1.1.1.2.2  perseant 	  break;
   1768  1.1.1.1.2.2  perseant 
   1769  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S64_GOTADDR_LO10:
   1770  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S64_GOTADDR_UP27:
   1771  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S64_GOTADDR_EX27:
   1772  1.1.1.1.2.2  perseant 
   1773  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_GOTADDR_LO10:
   1774  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_GOTADDR_UP27:
   1775  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_GOTADDR_EX6:
   1776  1.1.1.1.2.2  perseant 
   1777  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_GOTADDR_LO10:
   1778  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_GOTADDR_UP27:
   1779  1.1.1.1.2.2  perseant 	  value = 0;
   1780  1.1.1.1.2.2  perseant 	  /* Fallthrough */
   1781  1.1.1.1.2.2  perseant 
   1782  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S32_UP27:
   1783  1.1.1.1.2.2  perseant 
   1784  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_UP27:
   1785  1.1.1.1.2.2  perseant 
   1786  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_UP27:
   1787  1.1.1.1.2.2  perseant 
   1788  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S64_UP27:
   1789  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S64_EX27:
   1790  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S64_LO10:
   1791  1.1.1.1.2.2  perseant 
   1792  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_TLS_LE_UP27:
   1793  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_TLS_LE_EX6:
   1794  1.1.1.1.2.2  perseant 
   1795  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_TLS_LE_UP27:
   1796  1.1.1.1.2.2  perseant 
   1797  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_GOTOFF_UP27:
   1798  1.1.1.1.2.2  perseant 
   1799  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_GOTOFF_UP27:
   1800  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_GOTOFF_EX6:
   1801  1.1.1.1.2.2  perseant 
   1802  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_GOT_UP27:
   1803  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_GOT_EX6:
   1804  1.1.1.1.2.2  perseant 
   1805  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_GOT_UP27:
   1806  1.1.1.1.2.2  perseant 
   1807  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S32_LO5:
   1808  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_LO10:
   1809  1.1.1.1.2.2  perseant 
   1810  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_LO10:
   1811  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_EX6:
   1812  1.1.1.1.2.2  perseant 
   1813  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_TLS_LE_LO10:
   1814  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_TLS_LE_LO10:
   1815  1.1.1.1.2.2  perseant 
   1816  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_GOTOFF_LO10:
   1817  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_GOTOFF_LO10:
   1818  1.1.1.1.2.2  perseant 
   1819  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S43_GOT_LO10:
   1820  1.1.1.1.2.2  perseant 	case BFD_RELOC_KVX_S37_GOT_LO10:
   1821  1.1.1.1.2.2  perseant 
   1822  1.1.1.1.2.2  perseant 	default:
   1823  1.1.1.1.2.2  perseant 	  as_fatal ("[md_apply_fix]:"
   1824  1.1.1.1.2.2  perseant 		    "unsupported relocation type (type not handled : %d)",
   1825  1.1.1.1.2.2  perseant 		    fixP->fx_r_type);
   1826  1.1.1.1.2.2  perseant 	}
   1827  1.1.1.1.2.2  perseant     }
   1828  1.1.1.1.2.2  perseant }
   1829  1.1.1.1.2.2  perseant 
   1830  1.1.1.1.2.2  perseant /*
   1831  1.1.1.1.2.2  perseant  * Warning: Can be called only in fixup_segment() after fx_addsy field
   1832  1.1.1.1.2.2  perseant  * has been updated by calling symbol_get_value_expression(...->X_add_symbol)
   1833  1.1.1.1.2.2  perseant  */
   1834  1.1.1.1.2.2  perseant int
   1835  1.1.1.1.2.2  perseant kvx_validate_sub_fix (fixS * fixP)
   1836  1.1.1.1.2.2  perseant {
   1837  1.1.1.1.2.2  perseant   segT add_symbol_segment, sub_symbol_segment;
   1838  1.1.1.1.2.2  perseant 
   1839  1.1.1.1.2.2  perseant   switch (fixP->fx_r_type)
   1840  1.1.1.1.2.2  perseant     {
   1841  1.1.1.1.2.2  perseant     case BFD_RELOC_8:
   1842  1.1.1.1.2.2  perseant     case BFD_RELOC_16:
   1843  1.1.1.1.2.2  perseant     case BFD_RELOC_32:
   1844  1.1.1.1.2.2  perseant       if (fixP->fx_addsy != NULL)
   1845  1.1.1.1.2.2  perseant 	add_symbol_segment = S_GET_SEGMENT (fixP->fx_addsy);
   1846  1.1.1.1.2.2  perseant       else
   1847  1.1.1.1.2.2  perseant 	return 0;
   1848  1.1.1.1.2.2  perseant       if (fixP->fx_subsy != NULL)
   1849  1.1.1.1.2.2  perseant 	sub_symbol_segment = S_GET_SEGMENT (fixP->fx_subsy);
   1850  1.1.1.1.2.2  perseant       else
   1851  1.1.1.1.2.2  perseant 	return 0;
   1852  1.1.1.1.2.2  perseant 
   1853  1.1.1.1.2.2  perseant       if ((strcmp (S_GET_NAME (fixP->fx_addsy),
   1854  1.1.1.1.2.2  perseant 		   S_GET_NAME (fixP->fx_subsy)) == 0) &&
   1855  1.1.1.1.2.2  perseant 	  (add_symbol_segment == sub_symbol_segment))
   1856  1.1.1.1.2.2  perseant 	return 1;
   1857  1.1.1.1.2.2  perseant       break;
   1858  1.1.1.1.2.2  perseant     default:
   1859  1.1.1.1.2.2  perseant       break;
   1860  1.1.1.1.2.2  perseant     }
   1861  1.1.1.1.2.2  perseant 
   1862  1.1.1.1.2.2  perseant   return 0;
   1863  1.1.1.1.2.2  perseant }
   1864  1.1.1.1.2.2  perseant 
   1865  1.1.1.1.2.2  perseant /* This is called whenever some data item (not an instruction) needs a
   1866  1.1.1.1.2.2  perseant  * fixup.  */
   1867  1.1.1.1.2.2  perseant void
   1868  1.1.1.1.2.2  perseant kvx_cons_fix_new (fragS * f, int where, int nbytes, expressionS * exp,
   1869  1.1.1.1.2.2  perseant 		  bfd_reloc_code_real_type code)
   1870  1.1.1.1.2.2  perseant {
   1871  1.1.1.1.2.2  perseant   if (exp->X_op == O_pseudo_fixup)
   1872  1.1.1.1.2.2  perseant     {
   1873  1.1.1.1.2.2  perseant       exp->X_op = O_symbol;
   1874  1.1.1.1.2.2  perseant       struct pseudo_func *pf =
   1875  1.1.1.1.2.2  perseant 	kvx_get_pseudo_func_data_scn (exp->X_op_symbol);
   1876  1.1.1.1.2.2  perseant       assert (pf != NULL);
   1877  1.1.1.1.2.2  perseant       code = pf->pseudo_relocs.single;
   1878  1.1.1.1.2.2  perseant 
   1879  1.1.1.1.2.2  perseant       if (code == BFD_RELOC_UNUSED)
   1880  1.1.1.1.2.2  perseant 	as_fatal ("Unsupported relocation");
   1881  1.1.1.1.2.2  perseant     }
   1882  1.1.1.1.2.2  perseant   else
   1883  1.1.1.1.2.2  perseant     {
   1884  1.1.1.1.2.2  perseant       switch (nbytes)
   1885  1.1.1.1.2.2  perseant 	{
   1886  1.1.1.1.2.2  perseant 	case 1:
   1887  1.1.1.1.2.2  perseant 	  code = BFD_RELOC_8;
   1888  1.1.1.1.2.2  perseant 	  break;
   1889  1.1.1.1.2.2  perseant 	case 2:
   1890  1.1.1.1.2.2  perseant 	  code = BFD_RELOC_16;
   1891  1.1.1.1.2.2  perseant 	  break;
   1892  1.1.1.1.2.2  perseant 	case 4:
   1893  1.1.1.1.2.2  perseant 	  code = BFD_RELOC_32;
   1894  1.1.1.1.2.2  perseant 	  break;
   1895  1.1.1.1.2.2  perseant 	case 8:
   1896  1.1.1.1.2.2  perseant 	  code = BFD_RELOC_64;
   1897  1.1.1.1.2.2  perseant 	  break;
   1898  1.1.1.1.2.2  perseant 	default:
   1899  1.1.1.1.2.2  perseant 	  as_fatal ("unsupported BFD relocation size %u", nbytes);
   1900  1.1.1.1.2.2  perseant 	  break;
   1901  1.1.1.1.2.2  perseant 	}
   1902  1.1.1.1.2.2  perseant     }
   1903  1.1.1.1.2.2  perseant   fix_new_exp (f, where, nbytes, exp, 0, code);
   1904  1.1.1.1.2.2  perseant }
   1905  1.1.1.1.2.2  perseant 
   1906  1.1.1.1.2.2  perseant /*
   1907  1.1.1.1.2.2  perseant  * generate a relocation record
   1908  1.1.1.1.2.2  perseant  */
   1909  1.1.1.1.2.2  perseant 
   1910  1.1.1.1.2.2  perseant arelent *
   1911  1.1.1.1.2.2  perseant tc_gen_reloc (asection * sec ATTRIBUTE_UNUSED, fixS * fixp)
   1912  1.1.1.1.2.2  perseant {
   1913  1.1.1.1.2.2  perseant   arelent *reloc;
   1914  1.1.1.1.2.2  perseant   bfd_reloc_code_real_type code;
   1915  1.1.1.1.2.2  perseant 
   1916  1.1.1.1.2.2  perseant   reloc = (arelent *) xmalloc (sizeof (arelent));
   1917  1.1.1.1.2.2  perseant 
   1918  1.1.1.1.2.2  perseant   reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
   1919  1.1.1.1.2.2  perseant   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   1920  1.1.1.1.2.2  perseant   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
   1921  1.1.1.1.2.2  perseant 
   1922  1.1.1.1.2.2  perseant   code = fixp->fx_r_type;
   1923  1.1.1.1.2.2  perseant   if (code == BFD_RELOC_32 && fixp->fx_pcrel)
   1924  1.1.1.1.2.2  perseant     code = BFD_RELOC_32_PCREL;
   1925  1.1.1.1.2.2  perseant   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
   1926  1.1.1.1.2.2  perseant 
   1927  1.1.1.1.2.2  perseant   if (reloc->howto == NULL)
   1928  1.1.1.1.2.2  perseant     {
   1929  1.1.1.1.2.2  perseant       as_bad_where (fixp->fx_file, fixp->fx_line,
   1930  1.1.1.1.2.2  perseant 		    "cannot represent `%s' relocation in object file",
   1931  1.1.1.1.2.2  perseant 		    bfd_get_reloc_code_name (code));
   1932  1.1.1.1.2.2  perseant       return NULL;
   1933  1.1.1.1.2.2  perseant     }
   1934  1.1.1.1.2.2  perseant 
   1935  1.1.1.1.2.2  perseant //  if (!fixp->fx_pcrel != !reloc->howto->pc_relative)
   1936  1.1.1.1.2.2  perseant //    {
   1937  1.1.1.1.2.2  perseant //      as_fatal ("internal error? cannot generate `%s' relocation",
   1938  1.1.1.1.2.2  perseant //		bfd_get_reloc_code_name (code));
   1939  1.1.1.1.2.2  perseant //    }
   1940  1.1.1.1.2.2  perseant //  assert (!fixp->fx_pcrel == !reloc->howto->pc_relative);
   1941  1.1.1.1.2.2  perseant 
   1942  1.1.1.1.2.2  perseant   reloc->addend = fixp->fx_offset;
   1943  1.1.1.1.2.2  perseant 
   1944  1.1.1.1.2.2  perseant   /*
   1945  1.1.1.1.2.2  perseant    * Ohhh, this is ugly.  The problem is that if this is a local global
   1946  1.1.1.1.2.2  perseant    * symbol, the relocation will entirely be performed at link time, not
   1947  1.1.1.1.2.2  perseant    * at assembly time.  bfd_perform_reloc doesn't know about this sort
   1948  1.1.1.1.2.2  perseant    * of thing, and as a result we need to fake it out here.
   1949  1.1.1.1.2.2  perseant    */
   1950  1.1.1.1.2.2  perseant 
   1951  1.1.1.1.2.2  perseant   /* GD I'm not sure what this is used for in the kvx case but it sure  */
   1952  1.1.1.1.2.2  perseant   /* messes up the relocs when emit_all_relocs is used as they are not */
   1953  1.1.1.1.2.2  perseant   /* resolved with respect to a global sysmbol (e.g. .text), and hence */
   1954  1.1.1.1.2.2  perseant   /* they are ALWAYS resolved at link time                             */
   1955  1.1.1.1.2.2  perseant   /* FIXME FIXME                                                       */
   1956  1.1.1.1.2.2  perseant 
   1957  1.1.1.1.2.2  perseant   /* clarkes: 030827:  This code (and the other half of the fix in write.c)
   1958  1.1.1.1.2.2  perseant    * have caused problems with the PIC relocations.
   1959  1.1.1.1.2.2  perseant    * The root problem is that bfd_install_relocation adds in to the reloc
   1960  1.1.1.1.2.2  perseant    * addend the section offset of a symbol defined in the current object.
   1961  1.1.1.1.2.2  perseant    * This causes problems on numerous other targets too, and there are
   1962  1.1.1.1.2.2  perseant    * several different methods used to get around it:
   1963  1.1.1.1.2.2  perseant    *   1.  In tc_gen_reloc, subtract off the value that bfd_install_relocation
   1964  1.1.1.1.2.2  perseant    *       added.  That is what we do here, and it is also done the
   1965  1.1.1.1.2.2  perseant    *       same way for alpha.
   1966  1.1.1.1.2.2  perseant    *   2.  In md_apply_fix, subtract off the value that bfd_install_relocation
   1967  1.1.1.1.2.2  perseant    *       will add.  This is done on SH (non-ELF) and sparc targets.
   1968  1.1.1.1.2.2  perseant    *   3.  In the howto structure for the relocations, specify a
   1969  1.1.1.1.2.2  perseant    *       special function that does not return bfd_reloc_continue.
   1970  1.1.1.1.2.2  perseant    *       This causes bfd_install_relocaion to terminate before it
   1971  1.1.1.1.2.2  perseant    *       adds in the symbol offset.  This is done on SH ELF targets.
   1972  1.1.1.1.2.2  perseant    *       Note that on ST200 we specify bfd_elf_generic_reloc as
   1973  1.1.1.1.2.2  perseant    *       the special function.  This will return bfd_reloc_continue
   1974  1.1.1.1.2.2  perseant    *       only in some circumstances, but in particular if the reloc
   1975  1.1.1.1.2.2  perseant    *       is marked as partial_inplace in the bfd howto structure, then
   1976  1.1.1.1.2.2  perseant    *       bfd_elf_generic_reloc will return bfd_reloc_continue.
   1977  1.1.1.1.2.2  perseant    *       Some ST200 relocations are marked as partial_inplace
   1978  1.1.1.1.2.2  perseant    *       (this is an error in my opinion because ST200 always uses
   1979  1.1.1.1.2.2  perseant    *       a separate addend), but some are not.  The PIC relocations
   1980  1.1.1.1.2.2  perseant    *       are not marked as partial_inplace, so for them,
   1981  1.1.1.1.2.2  perseant    *       bfd_elf_generic_reloc returns bfd_reloc_ok, and the addend
   1982  1.1.1.1.2.2  perseant    *       is not modified by bfd_install_relocation.   The relocations
   1983  1.1.1.1.2.2  perseant    *       R_KVX_16 and R_KVX_32 are marked partial_inplace, and so for
   1984  1.1.1.1.2.2  perseant    *       these we need to correct the addend.
   1985  1.1.1.1.2.2  perseant    * In the code below, the condition in the emit_all_relocs branch
   1986  1.1.1.1.2.2  perseant    * (now moved to write.c) is the inverse of the condition that
   1987  1.1.1.1.2.2  perseant    * bfd_elf_generic_reloc uses to short-circuit the code in
   1988  1.1.1.1.2.2  perseant    * bfd_install_relocation that modifies the addend.  The condition
   1989  1.1.1.1.2.2  perseant    * in the else branch match the condition used in the alpha version
   1990  1.1.1.1.2.2  perseant    * of tc_gen_reloc (see tc-alpha.c).
   1991  1.1.1.1.2.2  perseant    * I do not know why we need to use different conditions in these
   1992  1.1.1.1.2.2  perseant    * two branches, it seems to me that the condition should be the same
   1993  1.1.1.1.2.2  perseant    * whether or not emit_all_relocs is true.
   1994  1.1.1.1.2.2  perseant    * I also do not understand why it was necessary to move the emit_all_relocs
   1995  1.1.1.1.2.2  perseant    * condition to write.c.
   1996  1.1.1.1.2.2  perseant    */
   1997  1.1.1.1.2.2  perseant 
   1998  1.1.1.1.2.2  perseant   if (S_IS_EXTERNAL (fixp->fx_addsy) &&
   1999  1.1.1.1.2.2  perseant       !S_IS_COMMON (fixp->fx_addsy) && reloc->howto->partial_inplace)
   2000  1.1.1.1.2.2  perseant     reloc->addend -= symbol_get_bfdsym (fixp->fx_addsy)->value;
   2001  1.1.1.1.2.2  perseant 
   2002  1.1.1.1.2.2  perseant   return reloc;
   2003  1.1.1.1.2.2  perseant }
   2004  1.1.1.1.2.2  perseant 
   2005  1.1.1.1.2.2  perseant /* Round up segment to appropriate boundary */
   2006  1.1.1.1.2.2  perseant 
   2007  1.1.1.1.2.2  perseant valueT
   2008  1.1.1.1.2.2  perseant md_section_align (asection * seg ATTRIBUTE_UNUSED, valueT size)
   2009  1.1.1.1.2.2  perseant {
   2010  1.1.1.1.2.2  perseant #ifndef OBJ_ELF
   2011  1.1.1.1.2.2  perseant   /* This is not right for ELF; a.out wants it, and COFF will force
   2012  1.1.1.1.2.2  perseant    * the alignment anyways.  */
   2013  1.1.1.1.2.2  perseant   int align = bfd_get_section_alignment (stdoutput, seg);
   2014  1.1.1.1.2.2  perseant   valueT mask = ((valueT) 1 << align) - 1;
   2015  1.1.1.1.2.2  perseant   return (size + mask) & ~mask;
   2016  1.1.1.1.2.2  perseant #else
   2017  1.1.1.1.2.2  perseant   return size;
   2018  1.1.1.1.2.2  perseant #endif
   2019  1.1.1.1.2.2  perseant }
   2020  1.1.1.1.2.2  perseant 
   2021  1.1.1.1.2.2  perseant int
   2022  1.1.1.1.2.2  perseant md_estimate_size_before_relax (register fragS * fragP ATTRIBUTE_UNUSED,
   2023  1.1.1.1.2.2  perseant 			       segT segtype ATTRIBUTE_UNUSED)
   2024  1.1.1.1.2.2  perseant {
   2025  1.1.1.1.2.2  perseant   as_fatal ("estimate_size_before_relax called");
   2026  1.1.1.1.2.2  perseant }
   2027  1.1.1.1.2.2  perseant 
   2028  1.1.1.1.2.2  perseant void
   2029  1.1.1.1.2.2  perseant md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
   2030  1.1.1.1.2.2  perseant 		 asection * sec ATTRIBUTE_UNUSED,
   2031  1.1.1.1.2.2  perseant 		 fragS * fragp ATTRIBUTE_UNUSED)
   2032  1.1.1.1.2.2  perseant {
   2033  1.1.1.1.2.2  perseant   as_fatal ("kvx convert_frag");
   2034  1.1.1.1.2.2  perseant }
   2035  1.1.1.1.2.2  perseant 
   2036  1.1.1.1.2.2  perseant symbolS *
   2037  1.1.1.1.2.2  perseant md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
   2038  1.1.1.1.2.2  perseant {
   2039  1.1.1.1.2.2  perseant   return 0;
   2040  1.1.1.1.2.2  perseant }
   2041  1.1.1.1.2.2  perseant 
   2042  1.1.1.1.2.2  perseant const char *
   2043  1.1.1.1.2.2  perseant md_atof (int type ATTRIBUTE_UNUSED,
   2044  1.1.1.1.2.2  perseant 	 char *litp ATTRIBUTE_UNUSED, int *sizep ATTRIBUTE_UNUSED)
   2045  1.1.1.1.2.2  perseant {
   2046  1.1.1.1.2.2  perseant   return ieee_md_atof (type, litp, sizep, TARGET_BYTES_BIG_ENDIAN);
   2047  1.1.1.1.2.2  perseant }
   2048  1.1.1.1.2.2  perseant 
   2049  1.1.1.1.2.2  perseant /*
   2050  1.1.1.1.2.2  perseant  * calculate the base for a pcrel fixup
   2051  1.1.1.1.2.2  perseant  * -- for relocation, we might need to add addend ?
   2052  1.1.1.1.2.2  perseant  */
   2053  1.1.1.1.2.2  perseant 
   2054  1.1.1.1.2.2  perseant long
   2055  1.1.1.1.2.2  perseant md_pcrel_from (fixS * fixP)
   2056  1.1.1.1.2.2  perseant {
   2057  1.1.1.1.2.2  perseant   return (fixP->fx_where + fixP->fx_frag->fr_address);
   2058  1.1.1.1.2.2  perseant }
   2059  1.1.1.1.2.2  perseant 
   2060  1.1.1.1.2.2  perseant /************************************************************/
   2061  1.1.1.1.2.2  perseant /*   Hooks into standard processing -- we hook into label   */
   2062  1.1.1.1.2.2  perseant /*   handling code to detect double ':' and we hook before  */
   2063  1.1.1.1.2.2  perseant /*   a line of code is processed to do some simple sed style */
   2064  1.1.1.1.2.2  perseant /*   edits.                                                 */
   2065  1.1.1.1.2.2  perseant /************************************************************/
   2066  1.1.1.1.2.2  perseant 
   2067  1.1.1.1.2.2  perseant static symbolS *last_proc_sym = NULL;
   2068  1.1.1.1.2.2  perseant static int update_last_proc_sym = 0;
   2069  1.1.1.1.2.2  perseant 
   2070  1.1.1.1.2.2  perseant void
   2071  1.1.1.1.2.2  perseant kvx_frob_label (symbolS *sym)
   2072  1.1.1.1.2.2  perseant {
   2073  1.1.1.1.2.2  perseant   if (update_last_proc_sym)
   2074  1.1.1.1.2.2  perseant     {
   2075  1.1.1.1.2.2  perseant       last_proc_sym = sym;
   2076  1.1.1.1.2.2  perseant       update_last_proc_sym = 0;
   2077  1.1.1.1.2.2  perseant     }
   2078  1.1.1.1.2.2  perseant 
   2079  1.1.1.1.2.2  perseant   if (inside_bundle)
   2080  1.1.1.1.2.2  perseant     {
   2081  1.1.1.1.2.2  perseant       struct label_fix *fix;
   2082  1.1.1.1.2.2  perseant       fix = malloc (sizeof (*fix));
   2083  1.1.1.1.2.2  perseant       fix->next = label_fixes;
   2084  1.1.1.1.2.2  perseant       fix->sym = sym;
   2085  1.1.1.1.2.2  perseant       label_fixes = fix;
   2086  1.1.1.1.2.2  perseant     }
   2087  1.1.1.1.2.2  perseant 
   2088  1.1.1.1.2.2  perseant   dwarf2_emit_label (sym);
   2089  1.1.1.1.2.2  perseant }
   2090  1.1.1.1.2.2  perseant 
   2091  1.1.1.1.2.2  perseant void
   2092  1.1.1.1.2.2  perseant kvx_check_label (symbolS *sym)
   2093  1.1.1.1.2.2  perseant {
   2094  1.1.1.1.2.2  perseant   /* Labels followed by a second semi-colon are considered external symbols.  */
   2095  1.1.1.1.2.2  perseant   if (*input_line_pointer == ':')
   2096  1.1.1.1.2.2  perseant     {
   2097  1.1.1.1.2.2  perseant       S_SET_EXTERNAL (sym);
   2098  1.1.1.1.2.2  perseant       input_line_pointer++;
   2099  1.1.1.1.2.2  perseant     }
   2100  1.1.1.1.2.2  perseant }
   2101  1.1.1.1.2.2  perseant 
   2102  1.1.1.1.2.2  perseant /* Emit single bundle nop. This is needed by .nop asm directive
   2103  1.1.1.1.2.2  perseant  * Have to manage end of bundle done usually by start_line_hook
   2104  1.1.1.1.2.2  perseant  * using BE pseudo op
   2105  1.1.1.1.2.2  perseant  */
   2106  1.1.1.1.2.2  perseant void
   2107  1.1.1.1.2.2  perseant kvx_emit_single_noop (void)
   2108  1.1.1.1.2.2  perseant {
   2109  1.1.1.1.2.2  perseant   char *nop;
   2110  1.1.1.1.2.2  perseant   char *end_of_bundle;
   2111  1.1.1.1.2.2  perseant 
   2112  1.1.1.1.2.2  perseant   if (asprintf (&nop, "nop") < 0)
   2113  1.1.1.1.2.2  perseant     as_fatal ("%s", xstrerror (errno));
   2114  1.1.1.1.2.2  perseant 
   2115  1.1.1.1.2.2  perseant   if (asprintf (&end_of_bundle, "be") < 0)
   2116  1.1.1.1.2.2  perseant     as_fatal ("%s", xstrerror (errno));
   2117  1.1.1.1.2.2  perseant 
   2118  1.1.1.1.2.2  perseant   char *saved_ilp = input_line_pointer;
   2119  1.1.1.1.2.2  perseant   md_assemble (nop);
   2120  1.1.1.1.2.2  perseant   md_assemble (end_of_bundle);
   2121  1.1.1.1.2.2  perseant   input_line_pointer = saved_ilp;
   2122  1.1.1.1.2.2  perseant   free (nop);
   2123  1.1.1.1.2.2  perseant   free (end_of_bundle);
   2124  1.1.1.1.2.2  perseant }
   2125  1.1.1.1.2.2  perseant 
   2126  1.1.1.1.2.2  perseant /*  edit out some syntactic sugar that confuses GAS       */
   2127  1.1.1.1.2.2  perseant /*  input_line_pointer is guaranteed to point to the      */
   2128  1.1.1.1.2.2  perseant /*  the current line but may include text from following  */
   2129  1.1.1.1.2.2  perseant /*  lines.  Thus, '\n' must be scanned for as well as '\0' */
   2130  1.1.1.1.2.2  perseant 
   2131  1.1.1.1.2.2  perseant void
   2132  1.1.1.1.2.2  perseant kvx_md_start_line_hook (void)
   2133  1.1.1.1.2.2  perseant {
   2134  1.1.1.1.2.2  perseant   char *t;
   2135  1.1.1.1.2.2  perseant 
   2136  1.1.1.1.2.2  perseant   for (t = input_line_pointer; t && t[0] == ' '; t++);
   2137  1.1.1.1.2.2  perseant 
   2138  1.1.1.1.2.2  perseant   /* Detect illegal syntax patterns:
   2139  1.1.1.1.2.2  perseant    * - two bundle ends on the same line: ;; ;;
   2140  1.1.1.1.2.2  perseant    * - illegal token: ;;;
   2141  1.1.1.1.2.2  perseant    */
   2142  1.1.1.1.2.2  perseant   if (t && (t[0] == ';') && (t[1] == ';'))
   2143  1.1.1.1.2.2  perseant     {
   2144  1.1.1.1.2.2  perseant       char *tmp_t;
   2145  1.1.1.1.2.2  perseant       bool newline_seen = false;
   2146  1.1.1.1.2.2  perseant 
   2147  1.1.1.1.2.2  perseant       if (t[2] == ';')
   2148  1.1.1.1.2.2  perseant 	as_fatal ("Syntax error: Illegal ;;; token");
   2149  1.1.1.1.2.2  perseant 
   2150  1.1.1.1.2.2  perseant       tmp_t = t + 2;
   2151  1.1.1.1.2.2  perseant 
   2152  1.1.1.1.2.2  perseant       while (tmp_t && tmp_t[0])
   2153  1.1.1.1.2.2  perseant 	{
   2154  1.1.1.1.2.2  perseant 	  while (tmp_t && tmp_t[0] &&
   2155  1.1.1.1.2.2  perseant 		 ((tmp_t[0] == ' ') || (tmp_t[0] == '\n')))
   2156  1.1.1.1.2.2  perseant 	    {
   2157  1.1.1.1.2.2  perseant 	      if (tmp_t[0] == '\n')
   2158  1.1.1.1.2.2  perseant 		newline_seen = true;
   2159  1.1.1.1.2.2  perseant 	      tmp_t++;
   2160  1.1.1.1.2.2  perseant 	    }
   2161  1.1.1.1.2.2  perseant 	  if (tmp_t[0] == ';' && tmp_t[1] == ';')
   2162  1.1.1.1.2.2  perseant 	    {
   2163  1.1.1.1.2.2  perseant 	      /* if there's no newline between the two bundle stops
   2164  1.1.1.1.2.2  perseant 	       * then raise a syntax error now, otherwise a strange error
   2165  1.1.1.1.2.2  perseant 	       * message from read.c will be raised: "junk at end of line..."
   2166  1.1.1.1.2.2  perseant 	       */
   2167  1.1.1.1.2.2  perseant 	      if (tmp_t[2] == ';')
   2168  1.1.1.1.2.2  perseant 		as_fatal ("Syntax error: Illegal ;;; token");
   2169  1.1.1.1.2.2  perseant 
   2170  1.1.1.1.2.2  perseant 	      if (!newline_seen)
   2171  1.1.1.1.2.2  perseant 		  as_fatal ("Syntax error: More than one bundle stop on a line");
   2172  1.1.1.1.2.2  perseant 	      newline_seen = false;	/* reset */
   2173  1.1.1.1.2.2  perseant 
   2174  1.1.1.1.2.2  perseant 	      /* this is an empty bundle, transform it into an
   2175  1.1.1.1.2.2  perseant 	       * empty statement */
   2176  1.1.1.1.2.2  perseant 	      tmp_t[0] = ';';
   2177  1.1.1.1.2.2  perseant 	      tmp_t[1] = ' ';
   2178  1.1.1.1.2.2  perseant 
   2179  1.1.1.1.2.2  perseant 	      tmp_t += 2;
   2180  1.1.1.1.2.2  perseant 	    }
   2181  1.1.1.1.2.2  perseant 	  else
   2182  1.1.1.1.2.2  perseant 	    break;
   2183  1.1.1.1.2.2  perseant 	}
   2184  1.1.1.1.2.2  perseant     }
   2185  1.1.1.1.2.2  perseant 
   2186  1.1.1.1.2.2  perseant   /* check for bundle end                             */
   2187  1.1.1.1.2.2  perseant   /* we transform these into a special opcode BE      */
   2188  1.1.1.1.2.2  perseant   /* because gas has ';' hardwired as a statement end */
   2189  1.1.1.1.2.2  perseant   if (t && (t[0] == ';') && (t[1] == ';'))
   2190  1.1.1.1.2.2  perseant     {
   2191  1.1.1.1.2.2  perseant       t[0] = 'B';
   2192  1.1.1.1.2.2  perseant       t[1] = 'E';
   2193  1.1.1.1.2.2  perseant       return;
   2194  1.1.1.1.2.2  perseant     }
   2195  1.1.1.1.2.2  perseant }
   2196  1.1.1.1.2.2  perseant 
   2197  1.1.1.1.2.2  perseant static void
   2198  1.1.1.1.2.2  perseant kvx_check_resources (int f)
   2199  1.1.1.1.2.2  perseant {
   2200  1.1.1.1.2.2  perseant   env.opts.check_resource_usage = f;
   2201  1.1.1.1.2.2  perseant }
   2202  1.1.1.1.2.2  perseant 
   2203  1.1.1.1.2.2  perseant /** called before write_object_file */
   2204  1.1.1.1.2.2  perseant void
   2205  1.1.1.1.2.2  perseant kvx_end (void)
   2206  1.1.1.1.2.2  perseant {
   2207  1.1.1.1.2.2  perseant   int newflags;
   2208  1.1.1.1.2.2  perseant 
   2209  1.1.1.1.2.2  perseant   if (!env.params.core_set)
   2210  1.1.1.1.2.2  perseant     env.params.core = kvx_core_info->elf_core;
   2211  1.1.1.1.2.2  perseant 
   2212  1.1.1.1.2.2  perseant   /* (pp) the flags must be set at once */
   2213  1.1.1.1.2.2  perseant   newflags = env.params.core | env.params.abi | env.params.pic_flags;
   2214  1.1.1.1.2.2  perseant 
   2215  1.1.1.1.2.2  perseant   if (env.params.arch_size == 64)
   2216  1.1.1.1.2.2  perseant     newflags |= ELF_KVX_ABI_64B_ADDR_BIT;
   2217  1.1.1.1.2.2  perseant 
   2218  1.1.1.1.2.2  perseant   bfd_set_private_flags (stdoutput, newflags);
   2219  1.1.1.1.2.2  perseant 
   2220  1.1.1.1.2.2  perseant   cleanup ();
   2221  1.1.1.1.2.2  perseant 
   2222  1.1.1.1.2.2  perseant   if (inside_bundle && insncnt != 0)
   2223  1.1.1.1.2.2  perseant     as_bad ("unexpected end-of-file while processing a bundle."
   2224  1.1.1.1.2.2  perseant 	    "  Please check that ;; is on its own line.");
   2225  1.1.1.1.2.2  perseant }
   2226  1.1.1.1.2.2  perseant 
   2227  1.1.1.1.2.2  perseant static void
   2228  1.1.1.1.2.2  perseant kvx_type (int start ATTRIBUTE_UNUSED)
   2229  1.1.1.1.2.2  perseant {
   2230  1.1.1.1.2.2  perseant   char *name;
   2231  1.1.1.1.2.2  perseant   char c;
   2232  1.1.1.1.2.2  perseant   int type;
   2233  1.1.1.1.2.2  perseant   char *typename = NULL;
   2234  1.1.1.1.2.2  perseant   symbolS *sym;
   2235  1.1.1.1.2.2  perseant   elf_symbol_type *elfsym;
   2236  1.1.1.1.2.2  perseant 
   2237  1.1.1.1.2.2  perseant   c = get_symbol_name (&name);
   2238  1.1.1.1.2.2  perseant   sym = symbol_find_or_make (name);
   2239  1.1.1.1.2.2  perseant   elfsym = (elf_symbol_type *) symbol_get_bfdsym (sym);
   2240  1.1.1.1.2.2  perseant   *input_line_pointer = c;
   2241  1.1.1.1.2.2  perseant 
   2242  1.1.1.1.2.2  perseant   if (!*S_GET_NAME (sym))
   2243  1.1.1.1.2.2  perseant     as_bad (_("Missing symbol name in directive"));
   2244  1.1.1.1.2.2  perseant 
   2245  1.1.1.1.2.2  perseant   SKIP_WHITESPACE ();
   2246  1.1.1.1.2.2  perseant   if (*input_line_pointer == ',')
   2247  1.1.1.1.2.2  perseant     ++input_line_pointer;
   2248  1.1.1.1.2.2  perseant 
   2249  1.1.1.1.2.2  perseant 
   2250  1.1.1.1.2.2  perseant   SKIP_WHITESPACE ();
   2251  1.1.1.1.2.2  perseant   if (*input_line_pointer == '#'
   2252  1.1.1.1.2.2  perseant       || *input_line_pointer == '@'
   2253  1.1.1.1.2.2  perseant       || *input_line_pointer == '"' || *input_line_pointer == '%')
   2254  1.1.1.1.2.2  perseant     ++input_line_pointer;
   2255  1.1.1.1.2.2  perseant 
   2256  1.1.1.1.2.2  perseant   /* typename = input_line_pointer; */
   2257  1.1.1.1.2.2  perseant   /* c = get_symbol_end(); */
   2258  1.1.1.1.2.2  perseant   c = get_symbol_name (&typename);
   2259  1.1.1.1.2.2  perseant 
   2260  1.1.1.1.2.2  perseant   type = 0;
   2261  1.1.1.1.2.2  perseant   if (strcmp (typename, "function") == 0
   2262  1.1.1.1.2.2  perseant       || strcmp (typename, "STT_FUNC") == 0)
   2263  1.1.1.1.2.2  perseant     type = BSF_FUNCTION;
   2264  1.1.1.1.2.2  perseant   else if (strcmp (typename, "object") == 0
   2265  1.1.1.1.2.2  perseant 	   || strcmp (typename, "STT_OBJECT") == 0)
   2266  1.1.1.1.2.2  perseant     type = BSF_OBJECT;
   2267  1.1.1.1.2.2  perseant   else if (strcmp (typename, "tls_object") == 0
   2268  1.1.1.1.2.2  perseant 	   || strcmp (typename, "STT_TLS") == 0)
   2269  1.1.1.1.2.2  perseant     type = BSF_OBJECT | BSF_THREAD_LOCAL;
   2270  1.1.1.1.2.2  perseant   else if (strcmp (typename, "common") == 0
   2271  1.1.1.1.2.2  perseant 	   || strcmp (typename, "STT_COMMON") == 0)
   2272  1.1.1.1.2.2  perseant     type = BSF_ELF_COMMON;
   2273  1.1.1.1.2.2  perseant   else if (strcmp (typename, "gnu_unique_object") == 0
   2274  1.1.1.1.2.2  perseant 	   || strcmp (typename, "STB_GNU_UNIQUE") == 0)
   2275  1.1.1.1.2.2  perseant     {
   2276  1.1.1.1.2.2  perseant       elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_unique;
   2277  1.1.1.1.2.2  perseant       type = BSF_OBJECT | BSF_GNU_UNIQUE;
   2278  1.1.1.1.2.2  perseant     }
   2279  1.1.1.1.2.2  perseant   else if (strcmp (typename, "notype") == 0
   2280  1.1.1.1.2.2  perseant 	   || strcmp (typename, "STT_NOTYPE") == 0)
   2281  1.1.1.1.2.2  perseant     ;
   2282  1.1.1.1.2.2  perseant #ifdef md_elf_symbol_type
   2283  1.1.1.1.2.2  perseant   else if ((type = md_elf_symbol_type (typename, sym, elfsym)) != -1)
   2284  1.1.1.1.2.2  perseant     ;
   2285  1.1.1.1.2.2  perseant #endif
   2286  1.1.1.1.2.2  perseant   else
   2287  1.1.1.1.2.2  perseant     as_bad (_("unrecognized symbol type \"%s\""), typename);
   2288  1.1.1.1.2.2  perseant 
   2289  1.1.1.1.2.2  perseant   *input_line_pointer = c;
   2290  1.1.1.1.2.2  perseant 
   2291  1.1.1.1.2.2  perseant   if (*input_line_pointer == '"')
   2292  1.1.1.1.2.2  perseant     ++input_line_pointer;
   2293  1.1.1.1.2.2  perseant 
   2294  1.1.1.1.2.2  perseant   elfsym->symbol.flags |= type;
   2295  1.1.1.1.2.2  perseant   symbol_get_bfdsym (sym)->flags |= type;
   2296  1.1.1.1.2.2  perseant 
   2297  1.1.1.1.2.2  perseant   demand_empty_rest_of_line ();
   2298  1.1.1.1.2.2  perseant }
   2299  1.1.1.1.2.2  perseant 
   2300  1.1.1.1.2.2  perseant #define ENDPROCEXTENSION	"$endproc"
   2301  1.1.1.1.2.2  perseant #define MINUSEXPR		".-"
   2302  1.1.1.1.2.2  perseant 
   2303  1.1.1.1.2.2  perseant static int proc_endp_status = 0;
   2304  1.1.1.1.2.2  perseant 
   2305  1.1.1.1.2.2  perseant static void
   2306  1.1.1.1.2.2  perseant kvx_endp (int start ATTRIBUTE_UNUSED)
   2307  1.1.1.1.2.2  perseant {
   2308  1.1.1.1.2.2  perseant   char c;
   2309  1.1.1.1.2.2  perseant   char *name;
   2310  1.1.1.1.2.2  perseant 
   2311  1.1.1.1.2.2  perseant   if (inside_bundle)
   2312  1.1.1.1.2.2  perseant     as_warn (".endp directive inside a bundle.");
   2313  1.1.1.1.2.2  perseant   /* function name is optionnal and is ignored */
   2314  1.1.1.1.2.2  perseant   /* there may be several names separated by commas... */
   2315  1.1.1.1.2.2  perseant   while (1)
   2316  1.1.1.1.2.2  perseant     {
   2317  1.1.1.1.2.2  perseant       SKIP_WHITESPACE ();
   2318  1.1.1.1.2.2  perseant       c = get_symbol_name (&name);
   2319  1.1.1.1.2.2  perseant       (void) restore_line_pointer (c);
   2320  1.1.1.1.2.2  perseant       SKIP_WHITESPACE ();
   2321  1.1.1.1.2.2  perseant       if (*input_line_pointer != ',')
   2322  1.1.1.1.2.2  perseant 	break;
   2323  1.1.1.1.2.2  perseant       ++input_line_pointer;
   2324  1.1.1.1.2.2  perseant     }
   2325  1.1.1.1.2.2  perseant   demand_empty_rest_of_line ();
   2326  1.1.1.1.2.2  perseant 
   2327  1.1.1.1.2.2  perseant   if (!proc_endp_status)
   2328  1.1.1.1.2.2  perseant     {
   2329  1.1.1.1.2.2  perseant       as_warn (".endp directive doesn't follow .proc -- ignoring ");
   2330  1.1.1.1.2.2  perseant       return;
   2331  1.1.1.1.2.2  perseant     }
   2332  1.1.1.1.2.2  perseant 
   2333  1.1.1.1.2.2  perseant   proc_endp_status = 0;
   2334  1.1.1.1.2.2  perseant 
   2335  1.1.1.1.2.2  perseant   /* TB begin : add BSF_FUNCTION attribute to last_proc_sym symbol */
   2336  1.1.1.1.2.2  perseant   if (size_type_function)
   2337  1.1.1.1.2.2  perseant     {
   2338  1.1.1.1.2.2  perseant       if (!last_proc_sym)
   2339  1.1.1.1.2.2  perseant 	{
   2340  1.1.1.1.2.2  perseant 	  as_bad ("Cannot set function attributes (bad symbol)");
   2341  1.1.1.1.2.2  perseant 	  return;
   2342  1.1.1.1.2.2  perseant 	}
   2343  1.1.1.1.2.2  perseant 
   2344  1.1.1.1.2.2  perseant       /*    last_proc_sym->symbol.flags |= BSF_FUNCTION; */
   2345  1.1.1.1.2.2  perseant       symbol_get_bfdsym (last_proc_sym)->flags |= BSF_FUNCTION;
   2346  1.1.1.1.2.2  perseant       /* Add .size funcname,.-funcname in order to add size
   2347  1.1.1.1.2.2  perseant        * attribute to the current function */
   2348  1.1.1.1.2.2  perseant       {
   2349  1.1.1.1.2.2  perseant 	const int newdirective_sz =
   2350  1.1.1.1.2.2  perseant 	  strlen (S_GET_NAME (last_proc_sym)) + strlen (MINUSEXPR) + 1;
   2351  1.1.1.1.2.2  perseant 	char *newdirective = malloc (newdirective_sz);
   2352  1.1.1.1.2.2  perseant 	char *savep = input_line_pointer;
   2353  1.1.1.1.2.2  perseant 	expressionS exp;
   2354  1.1.1.1.2.2  perseant 
   2355  1.1.1.1.2.2  perseant 	memset (newdirective, 0, newdirective_sz);
   2356  1.1.1.1.2.2  perseant 
   2357  1.1.1.1.2.2  perseant 	/* BUILD :".-funcname" expression */
   2358  1.1.1.1.2.2  perseant 	strcat (newdirective, MINUSEXPR);
   2359  1.1.1.1.2.2  perseant 	strcat (newdirective, S_GET_NAME (last_proc_sym));
   2360  1.1.1.1.2.2  perseant 	input_line_pointer = newdirective;
   2361  1.1.1.1.2.2  perseant 	expression (&exp);
   2362  1.1.1.1.2.2  perseant 
   2363  1.1.1.1.2.2  perseant 	if (exp.X_op == O_constant)
   2364  1.1.1.1.2.2  perseant 	  {
   2365  1.1.1.1.2.2  perseant 	    S_SET_SIZE (last_proc_sym, exp.X_add_number);
   2366  1.1.1.1.2.2  perseant 	    if (symbol_get_obj (last_proc_sym)->size)
   2367  1.1.1.1.2.2  perseant 	      {
   2368  1.1.1.1.2.2  perseant 		xfree (symbol_get_obj (last_proc_sym)->size);
   2369  1.1.1.1.2.2  perseant 		symbol_get_obj (last_proc_sym)->size = NULL;
   2370  1.1.1.1.2.2  perseant 	      }
   2371  1.1.1.1.2.2  perseant 	  }
   2372  1.1.1.1.2.2  perseant 	else
   2373  1.1.1.1.2.2  perseant 	  {
   2374  1.1.1.1.2.2  perseant 	    symbol_get_obj (last_proc_sym)->size =
   2375  1.1.1.1.2.2  perseant 	      (expressionS *) xmalloc (sizeof (expressionS));
   2376  1.1.1.1.2.2  perseant 	    *symbol_get_obj (last_proc_sym)->size = exp;
   2377  1.1.1.1.2.2  perseant 	  }
   2378  1.1.1.1.2.2  perseant 
   2379  1.1.1.1.2.2  perseant 	/* just restore the real input pointer */
   2380  1.1.1.1.2.2  perseant 	input_line_pointer = savep;
   2381  1.1.1.1.2.2  perseant 	free (newdirective);
   2382  1.1.1.1.2.2  perseant       }
   2383  1.1.1.1.2.2  perseant     }
   2384  1.1.1.1.2.2  perseant   /* TB end */
   2385  1.1.1.1.2.2  perseant 
   2386  1.1.1.1.2.2  perseant   last_proc_sym = NULL;
   2387  1.1.1.1.2.2  perseant }
   2388  1.1.1.1.2.2  perseant 
   2389  1.1.1.1.2.2  perseant static void
   2390  1.1.1.1.2.2  perseant kvx_proc (int start ATTRIBUTE_UNUSED)
   2391  1.1.1.1.2.2  perseant {
   2392  1.1.1.1.2.2  perseant   char c;
   2393  1.1.1.1.2.2  perseant   char *name;
   2394  1.1.1.1.2.2  perseant   /* there may be several names separated by commas... */
   2395  1.1.1.1.2.2  perseant   while (1)
   2396  1.1.1.1.2.2  perseant     {
   2397  1.1.1.1.2.2  perseant       SKIP_WHITESPACE ();
   2398  1.1.1.1.2.2  perseant       c = get_symbol_name (&name);
   2399  1.1.1.1.2.2  perseant       (void) restore_line_pointer (c);
   2400  1.1.1.1.2.2  perseant 
   2401  1.1.1.1.2.2  perseant       SKIP_WHITESPACE ();
   2402  1.1.1.1.2.2  perseant       if (*input_line_pointer != ',')
   2403  1.1.1.1.2.2  perseant 	break;
   2404  1.1.1.1.2.2  perseant       ++input_line_pointer;
   2405  1.1.1.1.2.2  perseant     }
   2406  1.1.1.1.2.2  perseant   demand_empty_rest_of_line ();
   2407  1.1.1.1.2.2  perseant 
   2408  1.1.1.1.2.2  perseant   if (proc_endp_status)
   2409  1.1.1.1.2.2  perseant     {
   2410  1.1.1.1.2.2  perseant       as_warn (".proc follows .proc -- ignoring");
   2411  1.1.1.1.2.2  perseant       return;
   2412  1.1.1.1.2.2  perseant     }
   2413  1.1.1.1.2.2  perseant 
   2414  1.1.1.1.2.2  perseant   proc_endp_status = 1;
   2415  1.1.1.1.2.2  perseant 
   2416  1.1.1.1.2.2  perseant   /* this code emit a global symbol to mark the end of each function    */
   2417  1.1.1.1.2.2  perseant   /* the symbol emitted has a name formed by the original function name */
   2418  1.1.1.1.2.2  perseant   /* concatenated with $endproc so if _foo is a function name the symbol */
   2419  1.1.1.1.2.2  perseant   /* marking the end of it is _foo$endproc                              */
   2420  1.1.1.1.2.2  perseant   /* It is also required for generation of .size directive in kvx_endp() */
   2421  1.1.1.1.2.2  perseant 
   2422  1.1.1.1.2.2  perseant   if (size_type_function)
   2423  1.1.1.1.2.2  perseant     update_last_proc_sym = 1;
   2424  1.1.1.1.2.2  perseant }
   2425  1.1.1.1.2.2  perseant 
   2426  1.1.1.1.2.2  perseant int
   2427  1.1.1.1.2.2  perseant kvx_force_reloc (fixS * fixP)
   2428  1.1.1.1.2.2  perseant {
   2429  1.1.1.1.2.2  perseant   symbolS *sym;
   2430  1.1.1.1.2.2  perseant   asection *symsec;
   2431  1.1.1.1.2.2  perseant 
   2432  1.1.1.1.2.2  perseant   if (generic_force_reloc (fixP))
   2433  1.1.1.1.2.2  perseant     return 1;
   2434  1.1.1.1.2.2  perseant 
   2435  1.1.1.1.2.2  perseant   switch (fixP->fx_r_type)
   2436  1.1.1.1.2.2  perseant     {
   2437  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_32_GOTOFF:
   2438  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_S37_GOTOFF_UP27:
   2439  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_S37_GOTOFF_LO10:
   2440  1.1.1.1.2.2  perseant 
   2441  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_64_GOTOFF:
   2442  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_S43_GOTOFF_UP27:
   2443  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_S43_GOTOFF_LO10:
   2444  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_S43_GOTOFF_EX6:
   2445  1.1.1.1.2.2  perseant 
   2446  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_32_GOT:
   2447  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_64_GOT:
   2448  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_S37_GOT_UP27:
   2449  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_S37_GOT_LO10:
   2450  1.1.1.1.2.2  perseant 
   2451  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_GLOB_DAT:
   2452  1.1.1.1.2.2  perseant       return 1;
   2453  1.1.1.1.2.2  perseant     default:
   2454  1.1.1.1.2.2  perseant       return 0;
   2455  1.1.1.1.2.2  perseant     }
   2456  1.1.1.1.2.2  perseant 
   2457  1.1.1.1.2.2  perseant   sym = fixP->fx_addsy;
   2458  1.1.1.1.2.2  perseant   if (sym)
   2459  1.1.1.1.2.2  perseant     {
   2460  1.1.1.1.2.2  perseant       symsec = S_GET_SEGMENT (sym);
   2461  1.1.1.1.2.2  perseant       /* if (bfd_is_abs_section (symsec)) return 0; */
   2462  1.1.1.1.2.2  perseant       if (!SEG_NORMAL (symsec))
   2463  1.1.1.1.2.2  perseant 	return 0;
   2464  1.1.1.1.2.2  perseant     }
   2465  1.1.1.1.2.2  perseant   return 1;
   2466  1.1.1.1.2.2  perseant }
   2467  1.1.1.1.2.2  perseant 
   2468  1.1.1.1.2.2  perseant int
   2469  1.1.1.1.2.2  perseant kvx_force_reloc_sub_same (fixS * fixP, segT sec)
   2470  1.1.1.1.2.2  perseant {
   2471  1.1.1.1.2.2  perseant   symbolS *sym;
   2472  1.1.1.1.2.2  perseant   asection *symsec;
   2473  1.1.1.1.2.2  perseant   const char *sec_name = NULL;
   2474  1.1.1.1.2.2  perseant 
   2475  1.1.1.1.2.2  perseant   if (generic_force_reloc (fixP))
   2476  1.1.1.1.2.2  perseant     return 1;
   2477  1.1.1.1.2.2  perseant 
   2478  1.1.1.1.2.2  perseant   switch (fixP->fx_r_type)
   2479  1.1.1.1.2.2  perseant     {
   2480  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_32_GOTOFF:
   2481  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_S37_GOTOFF_UP27:
   2482  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_S37_GOTOFF_LO10:
   2483  1.1.1.1.2.2  perseant 
   2484  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_64_GOTOFF:
   2485  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_S43_GOTOFF_UP27:
   2486  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_S43_GOTOFF_LO10:
   2487  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_S43_GOTOFF_EX6:
   2488  1.1.1.1.2.2  perseant 
   2489  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_32_GOT:
   2490  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_64_GOT:
   2491  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_S37_GOT_UP27:
   2492  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_S37_GOT_LO10:
   2493  1.1.1.1.2.2  perseant 
   2494  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_S37_LO10:
   2495  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_S37_UP27:
   2496  1.1.1.1.2.2  perseant 
   2497  1.1.1.1.2.2  perseant     case BFD_RELOC_KVX_GLOB_DAT:
   2498  1.1.1.1.2.2  perseant       return 1;
   2499  1.1.1.1.2.2  perseant 
   2500  1.1.1.1.2.2  perseant     default:
   2501  1.1.1.1.2.2  perseant       return 0;
   2502  1.1.1.1.2.2  perseant     }
   2503  1.1.1.1.2.2  perseant 
   2504  1.1.1.1.2.2  perseant   sym = fixP->fx_addsy;
   2505  1.1.1.1.2.2  perseant   if (sym)
   2506  1.1.1.1.2.2  perseant     {
   2507  1.1.1.1.2.2  perseant       symsec = S_GET_SEGMENT (sym);
   2508  1.1.1.1.2.2  perseant       /* if (bfd_is_abs_section (symsec)) return 0; */
   2509  1.1.1.1.2.2  perseant       if (!SEG_NORMAL (symsec))
   2510  1.1.1.1.2.2  perseant 	return 0;
   2511  1.1.1.1.2.2  perseant 
   2512  1.1.1.1.2.2  perseant       /*
   2513  1.1.1.1.2.2  perseant        * for .debug_arrange, .debug_frame, .eh_frame sections, containing
   2514  1.1.1.1.2.2  perseant        * expressions of the form "sym2 - sym1 + addend", solve them even when
   2515  1.1.1.1.2.2  perseant        * --emit-all-relocs is set. Otherwise, a relocation on two symbols
   2516  1.1.1.1.2.2  perseant        * is necessary and fails at elf level. Binopt should not be impacted by
   2517  1.1.1.1.2.2  perseant        * the resolution of this relocatable expression on symbols inside a
   2518  1.1.1.1.2.2  perseant        * function.
   2519  1.1.1.1.2.2  perseant        */
   2520  1.1.1.1.2.2  perseant       sec_name = segment_name (sec);
   2521  1.1.1.1.2.2  perseant       if ((strcmp (sec_name, ".eh_frame") == 0) ||
   2522  1.1.1.1.2.2  perseant 	  (strcmp (sec_name, ".except_table") == 0) ||
   2523  1.1.1.1.2.2  perseant 	  (strncmp (sec_name, ".debug_", sizeof (".debug_")) == 0))
   2524  1.1.1.1.2.2  perseant 	return 0;
   2525  1.1.1.1.2.2  perseant     }
   2526  1.1.1.1.2.2  perseant   return 1;
   2527  1.1.1.1.2.2  perseant }
   2528  1.1.1.1.2.2  perseant 
   2529  1.1.1.1.2.2  perseant /* Implement HANDLE_ALIGN.  */
   2530  1.1.1.1.2.2  perseant 
   2531  1.1.1.1.2.2  perseant static void
   2532  1.1.1.1.2.2  perseant kvx_make_nops (char *buf, bfd_vma bytes)
   2533  1.1.1.1.2.2  perseant {
   2534  1.1.1.1.2.2  perseant   bfd_vma i = 0;
   2535  1.1.1.1.2.2  perseant   unsigned int j;
   2536  1.1.1.1.2.2  perseant 
   2537  1.1.1.1.2.2  perseant   static unsigned int nop_single = 0;
   2538  1.1.1.1.2.2  perseant 
   2539  1.1.1.1.2.2  perseant   if (!nop_single)
   2540  1.1.1.1.2.2  perseant     {
   2541  1.1.1.1.2.2  perseant       const struct kvxopc *opcode =
   2542  1.1.1.1.2.2  perseant 	(struct kvxopc *) str_hash_find (env.opcode_hash, "nop");
   2543  1.1.1.1.2.2  perseant 
   2544  1.1.1.1.2.2  perseant       if (opcode == NULL)
   2545  1.1.1.1.2.2  perseant 	as_fatal
   2546  1.1.1.1.2.2  perseant 	  ("internal error: could not find opcode for 'nop' during padding");
   2547  1.1.1.1.2.2  perseant 
   2548  1.1.1.1.2.2  perseant       nop_single = opcode->codewords[0].opcode;
   2549  1.1.1.1.2.2  perseant     }
   2550  1.1.1.1.2.2  perseant 
   2551  1.1.1.1.2.2  perseant   /* KVX instructions are always 4-bytes aligned. If we are at a position */
   2552  1.1.1.1.2.2  perseant   /* that is not 4 bytes aligned, it means this is not part of an instruction, */
   2553  1.1.1.1.2.2  perseant   /* so it is safe to use a zero byte for padding. */
   2554  1.1.1.1.2.2  perseant 
   2555  1.1.1.1.2.2  perseant   for (j = bytes % 4; j > 0; j--)
   2556  1.1.1.1.2.2  perseant     buf[i++] = 0;
   2557  1.1.1.1.2.2  perseant 
   2558  1.1.1.1.2.2  perseant   for (j = 0; j < (bytes - i); j += 4)
   2559  1.1.1.1.2.2  perseant     {
   2560  1.1.1.1.2.2  perseant       unsigned nop = nop_single;
   2561  1.1.1.1.2.2  perseant 
   2562  1.1.1.1.2.2  perseant       // nop has bundle end only if #4 nop or last padding nop.
   2563  1.1.1.1.2.2  perseant       // Sets the parallel bit when neither conditions are matched.
   2564  1.1.1.1.2.2  perseant       // 4*4 = biggest nop bundle we can get
   2565  1.1.1.1.2.2  perseant       // 12 = offset when writting the last nop possible in a 4 nops bundle
   2566  1.1.1.1.2.2  perseant       // bytes-i-4 = offset for the last 4-words in the padding
   2567  1.1.1.1.2.2  perseant       if (j % (4 * 4) != 12 && j != (bytes - i - 4))
   2568  1.1.1.1.2.2  perseant 	nop |= PARALLEL_BIT;
   2569  1.1.1.1.2.2  perseant 
   2570  1.1.1.1.2.2  perseant       memcpy (buf + i + j, &nop, sizeof (nop));
   2571  1.1.1.1.2.2  perseant     }
   2572  1.1.1.1.2.2  perseant }
   2573  1.1.1.1.2.2  perseant 
   2574  1.1.1.1.2.2  perseant /* Pads code section with bundle of nops when possible, 0 if not. */
   2575  1.1.1.1.2.2  perseant void
   2576  1.1.1.1.2.2  perseant kvx_handle_align (fragS *fragP)
   2577  1.1.1.1.2.2  perseant {
   2578  1.1.1.1.2.2  perseant   switch (fragP->fr_type)
   2579  1.1.1.1.2.2  perseant     {
   2580  1.1.1.1.2.2  perseant     case rs_align_code:
   2581  1.1.1.1.2.2  perseant       {
   2582  1.1.1.1.2.2  perseant 	bfd_signed_vma bytes = (fragP->fr_next->fr_address
   2583  1.1.1.1.2.2  perseant 				- fragP->fr_address - fragP->fr_fix);
   2584  1.1.1.1.2.2  perseant 	char *p = fragP->fr_literal + fragP->fr_fix;
   2585  1.1.1.1.2.2  perseant 
   2586  1.1.1.1.2.2  perseant 	if (bytes <= 0)
   2587  1.1.1.1.2.2  perseant 	  break;
   2588  1.1.1.1.2.2  perseant 
   2589  1.1.1.1.2.2  perseant 	/* Insert zeros or nops to get 4 byte alignment.  */
   2590  1.1.1.1.2.2  perseant 	kvx_make_nops (p, bytes);
   2591  1.1.1.1.2.2  perseant 	fragP->fr_fix += bytes;
   2592  1.1.1.1.2.2  perseant       }
   2593  1.1.1.1.2.2  perseant       break;
   2594  1.1.1.1.2.2  perseant 
   2595  1.1.1.1.2.2  perseant     default:
   2596  1.1.1.1.2.2  perseant       break;
   2597  1.1.1.1.2.2  perseant     }
   2598  1.1.1.1.2.2  perseant }
   2599  1.1.1.1.2.2  perseant /*
   2600  1.1.1.1.2.2  perseant  * This is just used for debugging
   2601  1.1.1.1.2.2  perseant  */
   2602  1.1.1.1.2.2  perseant 
   2603  1.1.1.1.2.2  perseant ATTRIBUTE_UNUSED
   2604  1.1.1.1.2.2  perseant static void
   2605  1.1.1.1.2.2  perseant print_operand (expressionS * e, FILE * out)
   2606  1.1.1.1.2.2  perseant {
   2607  1.1.1.1.2.2  perseant   if (e)
   2608  1.1.1.1.2.2  perseant     {
   2609  1.1.1.1.2.2  perseant       switch (e->X_op)
   2610  1.1.1.1.2.2  perseant 	{
   2611  1.1.1.1.2.2  perseant 	case O_register:
   2612  1.1.1.1.2.2  perseant 	  fprintf (out, "%s", kvx_registers[e->X_add_number].name);
   2613  1.1.1.1.2.2  perseant 	  break;
   2614  1.1.1.1.2.2  perseant 
   2615  1.1.1.1.2.2  perseant 	case O_constant:
   2616  1.1.1.1.2.2  perseant 	  if (e->X_add_symbol)
   2617  1.1.1.1.2.2  perseant 	    {
   2618  1.1.1.1.2.2  perseant 	      if (e->X_add_number)
   2619  1.1.1.1.2.2  perseant 		fprintf (out, "(%s + %d)", S_GET_NAME (e->X_add_symbol),
   2620  1.1.1.1.2.2  perseant 			 (int) e->X_add_number);
   2621  1.1.1.1.2.2  perseant 	      else
   2622  1.1.1.1.2.2  perseant 		fprintf (out, "%s", S_GET_NAME (e->X_add_symbol));
   2623  1.1.1.1.2.2  perseant 	    }
   2624  1.1.1.1.2.2  perseant 	  else
   2625  1.1.1.1.2.2  perseant 	    fprintf (out, "%d", (int) e->X_add_number);
   2626  1.1.1.1.2.2  perseant 	  break;
   2627  1.1.1.1.2.2  perseant 
   2628  1.1.1.1.2.2  perseant 	case O_symbol:
   2629  1.1.1.1.2.2  perseant 	  if (e->X_add_symbol)
   2630  1.1.1.1.2.2  perseant 	    {
   2631  1.1.1.1.2.2  perseant 	      if (e->X_add_number)
   2632  1.1.1.1.2.2  perseant 		fprintf (out, "(%s + %d)", S_GET_NAME (e->X_add_symbol),
   2633  1.1.1.1.2.2  perseant 			 (int) e->X_add_number);
   2634  1.1.1.1.2.2  perseant 	      else
   2635  1.1.1.1.2.2  perseant 		fprintf (out, "%s", S_GET_NAME (e->X_add_symbol));
   2636  1.1.1.1.2.2  perseant 	    }
   2637  1.1.1.1.2.2  perseant 	  else
   2638  1.1.1.1.2.2  perseant 	    fprintf (out, "%d", (int) e->X_add_number);
   2639  1.1.1.1.2.2  perseant 	  break;
   2640  1.1.1.1.2.2  perseant 
   2641  1.1.1.1.2.2  perseant 	default:
   2642  1.1.1.1.2.2  perseant 	  fprintf (out, "o,ptype-%d", e->X_op);
   2643  1.1.1.1.2.2  perseant 	}
   2644  1.1.1.1.2.2  perseant     }
   2645  1.1.1.1.2.2  perseant }
   2646  1.1.1.1.2.2  perseant 
   2647  1.1.1.1.2.2  perseant void
   2648  1.1.1.1.2.2  perseant kvx_cfi_frame_initial_instructions (void)
   2649  1.1.1.1.2.2  perseant {
   2650  1.1.1.1.2.2  perseant   cfi_add_CFA_def_cfa (KVX_SP_REGNO, 0);
   2651  1.1.1.1.2.2  perseant }
   2652  1.1.1.1.2.2  perseant 
   2653  1.1.1.1.2.2  perseant int
   2654  1.1.1.1.2.2  perseant kvx_regname_to_dw2regnum (const char *regname)
   2655  1.1.1.1.2.2  perseant {
   2656  1.1.1.1.2.2  perseant   unsigned int regnum = -1;
   2657  1.1.1.1.2.2  perseant   const char *p;
   2658  1.1.1.1.2.2  perseant   char *q;
   2659  1.1.1.1.2.2  perseant 
   2660  1.1.1.1.2.2  perseant   if (regname[0] == 'r')
   2661  1.1.1.1.2.2  perseant     {
   2662  1.1.1.1.2.2  perseant       p = regname + 1;
   2663  1.1.1.1.2.2  perseant       regnum = strtoul (p, &q, 10);
   2664  1.1.1.1.2.2  perseant       if (p == q || *q || regnum >= 64)
   2665  1.1.1.1.2.2  perseant 	return -1;
   2666  1.1.1.1.2.2  perseant     }
   2667  1.1.1.1.2.2  perseant   return regnum;
   2668  1.1.1.1.2.2  perseant }
   2669