Home | History | Annotate | Download | only in opcodes
      1 /* ia64-opc.c -- Functions to access the compacted opcode table
      2    Copyright (C) 1999-2014 Free Software Foundation, Inc.
      3    Written by Bob Manson of Cygnus Solutions, <manson (at) cygnus.com>
      4 
      5    This file is part of the GNU opcodes library.
      6 
      7    This library is free software; you can redistribute it and/or modify
      8    it under the terms of the GNU General Public License as published by
      9    the Free Software Foundation; either version 3, or (at your option)
     10    any later version.
     11 
     12    It is distributed in the hope that it will be useful, but WITHOUT
     13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     15    License for more details.
     16 
     17    You should have received a copy of the GNU General Public License
     18    along with this file; see the file COPYING.  If not, write to the
     19    Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
     20    MA 02110-1301, USA.  */
     21 
     22 #include "sysdep.h"
     23 #include "libiberty.h"
     24 #include "ia64-asmtab.h"
     25 #include "ia64-asmtab.c"
     26 
     27 static void get_opc_prefix (const char **, char *);
     28 static short int find_string_ent (const char *);
     29 static short int find_main_ent (short int);
     30 static short int find_completer (short int, short int, const char *);
     31 static ia64_insn apply_completer (ia64_insn, int);
     32 static int extract_op_bits (int, int, int);
     33 static int extract_op (int, int *, unsigned int *);
     34 static int opcode_verify (ia64_insn, int, enum ia64_insn_type);
     35 static int locate_opcode_ent (ia64_insn, enum ia64_insn_type);
     36 static struct ia64_opcode *make_ia64_opcode
     37   (ia64_insn, const char *, int, int);
     38 static struct ia64_opcode *ia64_find_matching_opcode
     39   (const char *, short int);
     40 
     41 const struct ia64_templ_desc ia64_templ_desc[16] =
     42   {
     43     { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" },	/* 0 */
     44     { 2, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_I }, "MII" },
     45     { 0, { IA64_UNIT_M, IA64_UNIT_L, IA64_UNIT_X }, "MLX" },
     46     { 0, { 0, },				    "-3-" },
     47     { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" },	/* 4 */
     48     { 1, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_I }, "MMI" },
     49     { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_I }, "MFI" },
     50     { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_F }, "MMF" },
     51     { 0, { IA64_UNIT_M, IA64_UNIT_I, IA64_UNIT_B }, "MIB" },	/* 8 */
     52     { 0, { IA64_UNIT_M, IA64_UNIT_B, IA64_UNIT_B }, "MBB" },
     53     { 0, { 0, },				    "-a-" },
     54     { 0, { IA64_UNIT_B, IA64_UNIT_B, IA64_UNIT_B }, "BBB" },
     55     { 0, { IA64_UNIT_M, IA64_UNIT_M, IA64_UNIT_B }, "MMB" },	/* c */
     56     { 0, { 0, },				    "-d-" },
     57     { 0, { IA64_UNIT_M, IA64_UNIT_F, IA64_UNIT_B }, "MFB" },
     58     { 0, { 0, },				    "-f-" },
     59   };
     60 
     61 
     62 /* Copy the prefix contained in *PTR (up to a '.' or a NUL) to DEST.
     63    PTR will be adjusted to point to the start of the next portion
     64    of the opcode, or at the NUL character. */
     65 
     66 static void
     67 get_opc_prefix (const char **ptr, char *dest)
     68 {
     69   char *c = strchr (*ptr, '.');
     70   if (c != NULL)
     71     {
     72       memcpy (dest, *ptr, c - *ptr);
     73       dest[c - *ptr] = '\0';
     74       *ptr = c + 1;
     75     }
     76   else
     77     {
     78       int l = strlen (*ptr);
     79       memcpy (dest, *ptr, l);
     80       dest[l] = '\0';
     81       *ptr += l;
     82     }
     83 }
     84 
     85 /* Find the index of the entry in the string table corresponding to
     87    STR; return -1 if one does not exist. */
     88 
     89 static short
     90 find_string_ent (const char *str)
     91 {
     92   short start = 0;
     93   short end = sizeof (ia64_strings) / sizeof (const char *);
     94   short i = (start + end) / 2;
     95 
     96   if (strcmp (str, ia64_strings[end - 1]) > 0)
     97     {
     98       return -1;
     99     }
    100   while (start <= end)
    101     {
    102       int c = strcmp (str, ia64_strings[i]);
    103       if (c < 0)
    104 	{
    105 	  end = i - 1;
    106 	}
    107       else if (c == 0)
    108 	{
    109 	  return i;
    110 	}
    111       else
    112 	{
    113 	  start = i + 1;
    114 	}
    115       i = (start + end) / 2;
    116     }
    117   return -1;
    118 }
    119 
    120 /* Find the opcode in the main opcode table whose name is STRINGINDEX, or
    122    return -1 if one does not exist. */
    123 
    124 static short
    125 find_main_ent (short nameindex)
    126 {
    127   short start = 0;
    128   short end = sizeof (main_table) / sizeof (struct ia64_main_table);
    129   short i = (start + end) / 2;
    130 
    131   if (nameindex < main_table[0].name_index
    132       || nameindex > main_table[end - 1].name_index)
    133     {
    134       return -1;
    135     }
    136   while (start <= end)
    137     {
    138       if (nameindex < main_table[i].name_index)
    139 	{
    140 	  end = i - 1;
    141 	}
    142       else if (nameindex == main_table[i].name_index)
    143 	{
    144 	  while (i > 0 && main_table[i - 1].name_index == nameindex)
    145 	    {
    146 	      i--;
    147 	    }
    148 	  return i;
    149 	}
    150       else
    151 	{
    152 	  start = i + 1;
    153 	}
    154       i = (start + end) / 2;
    155     }
    156   return -1;
    157 }
    158 
    159 /* Find the index of the entry in the completer table that is part of
    161    MAIN_ENT (starting from PREV_COMPLETER) that matches NAME, or
    162    return -1 if one does not exist. */
    163 
    164 static short
    165 find_completer (short main_ent, short prev_completer, const char *name)
    166 {
    167   short name_index = find_string_ent (name);
    168 
    169   if (name_index < 0)
    170     {
    171       return -1;
    172     }
    173 
    174   if (prev_completer == -1)
    175     {
    176       prev_completer = main_table[main_ent].completers;
    177     }
    178   else
    179     {
    180       prev_completer = completer_table[prev_completer].subentries;
    181     }
    182 
    183   while (prev_completer != -1)
    184     {
    185       if (completer_table[prev_completer].name_index == name_index)
    186 	{
    187 	  return prev_completer;
    188 	}
    189       prev_completer = completer_table[prev_completer].alternative;
    190     }
    191   return -1;
    192 }
    193 
    194 /* Apply the completer referred to by COMPLETER_INDEX to OPCODE, and
    196    return the result. */
    197 
    198 static ia64_insn
    199 apply_completer (ia64_insn opcode, int completer_index)
    200 {
    201   ia64_insn mask = completer_table[completer_index].mask;
    202   ia64_insn bits = completer_table[completer_index].bits;
    203   int shiftamt = (completer_table[completer_index].offset & 63);
    204 
    205   mask = mask << shiftamt;
    206   bits = bits << shiftamt;
    207   opcode = (opcode & ~mask) | bits;
    208   return opcode;
    209 }
    210 
    211 /* Extract BITS number of bits starting from OP_POINTER + BITOFFSET in
    213    the dis_table array, and return its value.  (BITOFFSET is numbered
    214    starting from MSB to LSB, so a BITOFFSET of 0 indicates the MSB of the
    215    first byte in OP_POINTER.) */
    216 
    217 static int
    218 extract_op_bits (int op_pointer, int bitoffset, int bits)
    219 {
    220   int res = 0;
    221 
    222   op_pointer += (bitoffset / 8);
    223 
    224   if (bitoffset % 8)
    225     {
    226       unsigned int op = dis_table[op_pointer++];
    227       int numb = 8 - (bitoffset % 8);
    228       int mask = (1 << numb) - 1;
    229       int bata = (bits < numb) ? bits : numb;
    230       int delta = numb - bata;
    231 
    232       res = (res << bata) | ((op & mask) >> delta);
    233       bitoffset += bata;
    234       bits -= bata;
    235     }
    236   while (bits >= 8)
    237     {
    238       res = (res << 8) | (dis_table[op_pointer++] & 255);
    239       bits -= 8;
    240     }
    241   if (bits > 0)
    242     {
    243       unsigned int op = (dis_table[op_pointer++] & 255);
    244       res = (res << bits) | (op >> (8 - bits));
    245     }
    246   return res;
    247 }
    248 
    249 /* Examine the state machine entry at OP_POINTER in the dis_table
    251    array, and extract its values into OPVAL and OP.  The length of the
    252    state entry in bits is returned. */
    253 
    254 static int
    255 extract_op (int op_pointer, int *opval, unsigned int *op)
    256 {
    257   int oplen = 5;
    258 
    259   *op = dis_table[op_pointer];
    260 
    261   if ((*op) & 0x40)
    262     {
    263       opval[0] = extract_op_bits (op_pointer, oplen, 5);
    264       oplen += 5;
    265     }
    266   switch ((*op) & 0x30)
    267     {
    268     case 0x10:
    269       {
    270 	opval[1] = extract_op_bits (op_pointer, oplen, 8);
    271 	oplen += 8;
    272 	opval[1] += op_pointer;
    273 	break;
    274       }
    275     case 0x20:
    276       {
    277 	opval[1] = extract_op_bits (op_pointer, oplen, 16);
    278 	if (! (opval[1] & 32768))
    279 	  {
    280 	    opval[1] += op_pointer;
    281 	  }
    282 	oplen += 16;
    283 	break;
    284       }
    285     case 0x30:
    286       {
    287 	oplen--;
    288 	opval[2] = extract_op_bits (op_pointer, oplen, 12);
    289 	oplen += 12;
    290 	opval[2] |= 32768;
    291 	break;
    292       }
    293     }
    294   if (((*op) & 0x08) && (((*op) & 0x30) != 0x30))
    295     {
    296       opval[2] = extract_op_bits (op_pointer, oplen, 16);
    297       oplen += 16;
    298       if (! (opval[2] & 32768))
    299 	{
    300 	  opval[2] += op_pointer;
    301 	}
    302     }
    303   return oplen;
    304 }
    305 
    306 /* Returns a non-zero value if the opcode in the main_table list at
    308    PLACE matches OPCODE and is of type TYPE. */
    309 
    310 static int
    311 opcode_verify (ia64_insn opcode, int place, enum ia64_insn_type type)
    312 {
    313   if (main_table[place].opcode_type != type)
    314     {
    315       return 0;
    316     }
    317   if (main_table[place].flags
    318       & (IA64_OPCODE_F2_EQ_F3 | IA64_OPCODE_LEN_EQ_64MCNT))
    319     {
    320       const struct ia64_operand *o1, *o2;
    321       ia64_insn f2, f3;
    322 
    323       if (main_table[place].flags & IA64_OPCODE_F2_EQ_F3)
    324 	{
    325 	  o1 = elf64_ia64_operands + IA64_OPND_F2;
    326 	  o2 = elf64_ia64_operands + IA64_OPND_F3;
    327 	  (*o1->extract) (o1, opcode, &f2);
    328 	  (*o2->extract) (o2, opcode, &f3);
    329 	  if (f2 != f3)
    330 	    return 0;
    331 	}
    332       else
    333 	{
    334 	  ia64_insn len, count;
    335 
    336 	  /* length must equal 64-count: */
    337 	  o1 = elf64_ia64_operands + IA64_OPND_LEN6;
    338 	  o2 = elf64_ia64_operands + main_table[place].operands[2];
    339 	  (*o1->extract) (o1, opcode, &len);
    340 	  (*o2->extract) (o2, opcode, &count);
    341 	  if (len != 64 - count)
    342 	    return 0;
    343 	}
    344     }
    345   return 1;
    346 }
    347 
    348 /* Find an instruction entry in the ia64_dis_names array that matches
    350    opcode OPCODE and is of type TYPE.  Returns either a positive index
    351    into the array, or a negative value if an entry for OPCODE could
    352    not be found.  Checks all matches and returns the one with the highest
    353    priority. */
    354 
    355 static int
    356 locate_opcode_ent (ia64_insn opcode, enum ia64_insn_type type)
    357 {
    358   int currtest[41];
    359   int bitpos[41];
    360   int op_ptr[41];
    361   int currstatenum = 0;
    362   short found_disent = -1;
    363   short found_priority = -1;
    364 
    365   currtest[currstatenum] = 0;
    366   op_ptr[currstatenum] = 0;
    367   bitpos[currstatenum] = 40;
    368 
    369   while (1)
    370     {
    371       int op_pointer = op_ptr[currstatenum];
    372       unsigned int op;
    373       int currbitnum = bitpos[currstatenum];
    374       int oplen;
    375       int opval[3] = {0};
    376       int next_op;
    377       int currbit;
    378 
    379       oplen = extract_op (op_pointer, opval, &op);
    380 
    381       bitpos[currstatenum] = currbitnum;
    382 
    383       /* Skip opval[0] bits in the instruction. */
    384       if (op & 0x40)
    385 	{
    386 	  currbitnum -= opval[0];
    387 	}
    388 
    389       /* The value of the current bit being tested. */
    390       currbit = opcode & (((ia64_insn) 1) << currbitnum) ? 1 : 0;
    391       next_op = -1;
    392 
    393       /* We always perform the tests specified in the current state in
    394 	 a particular order, falling through to the next test if the
    395 	 previous one failed. */
    396       switch (currtest[currstatenum])
    397 	{
    398 	case 0:
    399 	  currtest[currstatenum]++;
    400 	  if (currbit == 0 && (op & 0x80))
    401 	    {
    402 	      /* Check for a zero bit.  If this test solely checks for
    403 		 a zero bit, we can check for up to 8 consecutive zero
    404 		 bits (the number to check is specified by the lower 3
    405 		 bits in the state code.)
    406 
    407 		 If the state instruction matches, we go to the very
    408 		 next state instruction; otherwise, try the next test. */
    409 
    410 	      if ((op & 0xf8) == 0x80)
    411 		{
    412 		  int count = op & 0x7;
    413 		  int x;
    414 
    415 		  for (x = 0; x <= count; x++)
    416 		    {
    417 		      int i =
    418 			opcode & (((ia64_insn) 1) << (currbitnum - x)) ? 1 : 0;
    419 		      if (i)
    420 			{
    421 			  break;
    422 			}
    423 		    }
    424 		  if (x > count)
    425 		    {
    426 		      next_op = op_pointer + ((oplen + 7) / 8);
    427 		      currbitnum -= count;
    428 		      break;
    429 		    }
    430 		}
    431 	      else if (! currbit)
    432 		{
    433 		  next_op = op_pointer + ((oplen + 7) / 8);
    434 		  break;
    435 		}
    436 	    }
    437 	  /* FALLTHROUGH */
    438 	case 1:
    439 	  /* If the bit in the instruction is one, go to the state
    440 	     instruction specified by opval[1]. */
    441 	  currtest[currstatenum]++;
    442 	  if (currbit && (op & 0x30) != 0 && ((op & 0x30) != 0x30))
    443 	    {
    444 	      next_op = opval[1];
    445 	      break;
    446 	    }
    447 	  /* FALLTHROUGH */
    448 	case 2:
    449 	  /* Don't care.  Skip the current bit and go to the state
    450 	     instruction specified by opval[2].
    451 
    452 	     An encoding of 0x30 is special; this means that a 12-bit
    453 	     offset into the ia64_dis_names[] array is specified.  */
    454 	  currtest[currstatenum]++;
    455 	  if ((op & 0x08) || ((op & 0x30) == 0x30))
    456 	    {
    457 	      next_op = opval[2];
    458 	      break;
    459 	    }
    460 	}
    461 
    462       /* If bit 15 is set in the address of the next state, an offset
    463 	 in the ia64_dis_names array was specified instead.  We then
    464 	 check to see if an entry in the list of opcodes matches the
    465 	 opcode we were given; if so, we have succeeded.  */
    466 
    467       if ((next_op >= 0) && (next_op & 32768))
    468 	{
    469 	  short disent = next_op & 32767;
    470           short priority = -1;
    471 
    472 	  if (next_op > 65535)
    473 	    {
    474 	      abort ();
    475 	    }
    476 
    477 	  /* Run through the list of opcodes to check, trying to find
    478 	     one that matches.  */
    479 	  while (disent >= 0)
    480 	    {
    481 	      int place = ia64_dis_names[disent].insn_index;
    482 
    483               priority = ia64_dis_names[disent].priority;
    484 
    485 	      if (opcode_verify (opcode, place, type)
    486                   && priority > found_priority)
    487 		{
    488 		  break;
    489 		}
    490 	      if (ia64_dis_names[disent].next_flag)
    491 		{
    492 		  disent++;
    493 		}
    494 	      else
    495 		{
    496 		  disent = -1;
    497 		}
    498 	    }
    499 
    500 	  if (disent >= 0)
    501 	    {
    502               found_disent = disent;
    503               found_priority = priority;
    504 	    }
    505           /* Try the next test in this state, regardless of whether a match
    506              was found. */
    507           next_op = -2;
    508 	}
    509 
    510       /* next_op == -1 is "back up to the previous state".
    511 	 next_op == -2 is "stay in this state and try the next test".
    512 	 Otherwise, transition to the state indicated by next_op. */
    513 
    514       if (next_op == -1)
    515 	{
    516 	  currstatenum--;
    517 	  if (currstatenum < 0)
    518 	    {
    519               return found_disent;
    520 	    }
    521 	}
    522       else if (next_op >= 0)
    523 	{
    524 	  currstatenum++;
    525 	  bitpos[currstatenum] = currbitnum - 1;
    526 	  op_ptr[currstatenum] = next_op;
    527 	  currtest[currstatenum] = 0;
    528 	}
    529     }
    530 }
    531 
    532 /* Construct an ia64_opcode entry based on OPCODE, NAME and PLACE. */
    534 
    535 static struct ia64_opcode *
    536 make_ia64_opcode (ia64_insn opcode, const char *name, int place, int depind)
    537 {
    538   struct ia64_opcode *res =
    539     (struct ia64_opcode *) xmalloc (sizeof (struct ia64_opcode));
    540   res->name = xstrdup (name);
    541   res->type = main_table[place].opcode_type;
    542   res->num_outputs = main_table[place].num_outputs;
    543   res->opcode = opcode;
    544   res->mask = main_table[place].mask;
    545   res->operands[0] = main_table[place].operands[0];
    546   res->operands[1] = main_table[place].operands[1];
    547   res->operands[2] = main_table[place].operands[2];
    548   res->operands[3] = main_table[place].operands[3];
    549   res->operands[4] = main_table[place].operands[4];
    550   res->flags = main_table[place].flags;
    551   res->ent_index = place;
    552   res->dependencies = &op_dependencies[depind];
    553   return res;
    554 }
    555 
    556 /* Determine the ia64_opcode entry for the opcode specified by INSN
    558    and TYPE.  If a valid entry is not found, return NULL. */
    559 struct ia64_opcode *
    560 ia64_dis_opcode (ia64_insn insn, enum ia64_insn_type type)
    561 {
    562   int disent = locate_opcode_ent (insn, type);
    563 
    564   if (disent < 0)
    565     {
    566       return NULL;
    567     }
    568   else
    569     {
    570       unsigned int cb = ia64_dis_names[disent].completer_index;
    571       static char name[128];
    572       int place = ia64_dis_names[disent].insn_index;
    573       int ci = main_table[place].completers;
    574       ia64_insn tinsn = main_table[place].opcode;
    575 
    576       strcpy (name, ia64_strings [main_table[place].name_index]);
    577 
    578       while (cb)
    579 	{
    580 	  if (cb & 1)
    581 	    {
    582 	      int cname = completer_table[ci].name_index;
    583 
    584 	      tinsn = apply_completer (tinsn, ci);
    585 
    586 	      if (ia64_strings[cname][0] != '\0')
    587 		{
    588 		  strcat (name, ".");
    589 		  strcat (name, ia64_strings[cname]);
    590 		}
    591 	      if (cb != 1)
    592 		{
    593 		  ci = completer_table[ci].subentries;
    594 		}
    595 	    }
    596 	  else
    597 	    {
    598 	      ci = completer_table[ci].alternative;
    599 	    }
    600 	  if (ci < 0)
    601 	    {
    602 	      abort ();
    603 	    }
    604 	  cb = cb >> 1;
    605 	}
    606       if (tinsn != (insn & main_table[place].mask))
    607 	{
    608 	  abort ();
    609 	}
    610       return make_ia64_opcode (insn, name, place,
    611                                completer_table[ci].dependencies);
    612     }
    613 }
    614 
    615 /* Search the main_opcode table starting from PLACE for an opcode that
    617    matches NAME.  Return NULL if one is not found. */
    618 
    619 static struct ia64_opcode *
    620 ia64_find_matching_opcode (const char *name, short place)
    621 {
    622   char op[129];
    623   const char *suffix;
    624   short name_index;
    625 
    626   if (strlen (name) > 128)
    627     {
    628       return NULL;
    629     }
    630   suffix = name;
    631   get_opc_prefix (&suffix, op);
    632   name_index = find_string_ent (op);
    633   if (name_index < 0)
    634     {
    635       return NULL;
    636     }
    637 
    638   while (main_table[place].name_index == name_index)
    639     {
    640       const char *curr_suffix = suffix;
    641       ia64_insn curr_insn = main_table[place].opcode;
    642       short completer = -1;
    643 
    644       do {
    645 	if (suffix[0] == '\0')
    646 	  {
    647 	    completer = find_completer (place, completer, suffix);
    648 	  }
    649 	else
    650 	  {
    651 	    get_opc_prefix (&curr_suffix, op);
    652 	    completer = find_completer (place, completer, op);
    653 	  }
    654 	if (completer != -1)
    655 	  {
    656 	    curr_insn = apply_completer (curr_insn, completer);
    657 	  }
    658       } while (completer != -1 && curr_suffix[0] != '\0');
    659 
    660       if (completer != -1 && curr_suffix[0] == '\0'
    661 	  && completer_table[completer].terminal_completer)
    662 	{
    663           int depind = completer_table[completer].dependencies;
    664 	  return make_ia64_opcode (curr_insn, name, place, depind);
    665 	}
    666       else
    667 	{
    668 	  place++;
    669 	}
    670     }
    671   return NULL;
    672 }
    673 
    674 /* Find the next opcode after PREV_ENT that matches PREV_ENT, or return NULL
    676    if one does not exist.
    677 
    678    It is the caller's responsibility to invoke ia64_free_opcode () to
    679    release any resources used by the returned entry. */
    680 
    681 struct ia64_opcode *
    682 ia64_find_next_opcode (struct ia64_opcode *prev_ent)
    683 {
    684   return ia64_find_matching_opcode (prev_ent->name,
    685 				    prev_ent->ent_index + 1);
    686 }
    687 
    688 /* Find the first opcode that matches NAME, or return NULL if it does
    689    not exist.
    690 
    691    It is the caller's responsibility to invoke ia64_free_opcode () to
    692    release any resources used by the returned entry. */
    693 
    694 struct ia64_opcode *
    695 ia64_find_opcode (const char *name)
    696 {
    697   char op[129];
    698   const char *suffix;
    699   short place;
    700   short name_index;
    701 
    702   if (strlen (name) > 128)
    703     {
    704       return NULL;
    705     }
    706   suffix = name;
    707   get_opc_prefix (&suffix, op);
    708   name_index = find_string_ent (op);
    709   if (name_index < 0)
    710     {
    711       return NULL;
    712     }
    713 
    714   place = find_main_ent (name_index);
    715 
    716   if (place < 0)
    717     {
    718       return NULL;
    719     }
    720   return ia64_find_matching_opcode (name, place);
    721 }
    722 
    723 /* Free any resources used by ENT. */
    724 void
    725 ia64_free_opcode (struct ia64_opcode *ent)
    726 {
    727   free ((void *)ent->name);
    728   free (ent);
    729 }
    730 
    731 const struct ia64_dependency *
    732 ia64_find_dependency (int dep_index)
    733 {
    734   dep_index = DEP(dep_index);
    735 
    736   if (dep_index < 0
    737       || dep_index >= (int) ARRAY_SIZE (dependencies))
    738     return NULL;
    739 
    740   return &dependencies[dep_index];
    741 }
    742