Fix seg fault in linker when performing garbage collection on COFF based targets.
[external/binutils.git] / opcodes / h8500-dis.c
1 /* Disassemble h8500 instructions.
2    Copyright (C) 1993-2016 Free Software Foundation, Inc.
3
4    This file is part of the GNU opcodes library.
5
6    This library is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3, or (at your option)
9    any later version.
10
11    It is distributed in the hope that it will be useful, but WITHOUT
12    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
14    License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20
21 #include "sysdep.h"
22 #include <stdio.h>
23
24 #define DISASSEMBLER_TABLE
25 #define DEFINE_TABLE
26
27 #include "h8500-opc.h"
28 #include "dis-asm.h"
29 #include "opintl.h"
30
31 /* Maximum length of an instruction.  */
32 #define MAXLEN 8
33
34 #include <setjmp.h>
35
36 struct private
37 {
38   /* Points to first byte not fetched.  */
39   bfd_byte *max_fetched;
40   bfd_byte the_buffer[MAXLEN];
41   bfd_vma insn_start;
42   OPCODES_SIGJMP_BUF bailout;
43 };
44
45 /* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
46    to ADDR (exclusive) are valid.  Returns 1 for success, longjmps
47    on error.  */
48 #define FETCH_DATA(info, addr) \
49   ((addr) <= ((struct private *)(info->private_data))->max_fetched \
50    ? 1 : fetch_data ((info), (addr)))
51
52 static int
53 fetch_data (struct disassemble_info *info, bfd_byte *addr)
54 {
55   int status;
56   struct private *priv = (struct private *) info->private_data;
57   bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
58
59   status = (*info->read_memory_func) (start,
60                                       priv->max_fetched,
61                                       addr - priv->max_fetched,
62                                       info);
63   if (status != 0)
64     {
65       (*info->memory_error_func) (status, start, info);
66       OPCODES_SIGLONGJMP (priv->bailout, 1);
67     }
68   else
69     priv->max_fetched = addr;
70   return 1;
71 }
72
73 static char *crname[] = { "sr", "ccr", "*", "br", "ep", "dp", "*", "tp" };
74
75 int
76 print_insn_h8500 (bfd_vma addr, disassemble_info *info)
77 {
78   const h8500_opcode_info *opcode;
79   void *stream = info->stream;
80   fprintf_ftype func = info->fprintf_func;
81   struct private priv;
82   bfd_byte *buffer = priv.the_buffer;
83
84   info->private_data = (PTR) & priv;
85   priv.max_fetched = priv.the_buffer;
86   priv.insn_start = addr;
87   if (OPCODES_SIGSETJMP (priv.bailout) != 0)
88     /* Error return.  */
89     return -1;
90
91   /* Run down the table to find the one which matches.  */
92   for (opcode = h8500_table; opcode->name; opcode++)
93     {
94       int byte;
95       int rn = 0;
96       int rd = 0;
97       int rs = 0;
98       int disp = 0;
99       int abs_val = 0;
100       int imm = 0;
101       int pcrel = 0;
102       int qim = 0;
103       int i;
104       int cr = 0;
105
106       for (byte = 0; byte < opcode->length; byte++)
107         {
108           FETCH_DATA (info, buffer + byte + 1);
109           if ((buffer[byte] & opcode->bytes[byte].mask)
110               != (opcode->bytes[byte].contents))
111             goto next;
112
113           else
114             {
115               /* Extract any info parts.  */
116               switch (opcode->bytes[byte].insert)
117                 {
118                 case 0:
119                 case FP:
120                   break;
121                 default:
122                   /* xgettext:c-format */
123                   func (stream, _("can't cope with insert %d\n"),
124                         opcode->bytes[byte].insert);
125                   break;
126                 case RN:
127                   rn = buffer[byte] & 0x7;
128                   break;
129                 case RS:
130                   rs = buffer[byte] & 0x7;
131                   break;
132                 case CRB:
133                   cr = buffer[byte] & 0x7;
134                   if (cr == 0)
135                     goto next;
136                   break;
137                 case CRW:
138                   cr = buffer[byte] & 0x7;
139                   if (cr != 0)
140                     goto next;
141                   break;
142                 case DISP16:
143                   FETCH_DATA (info, buffer + byte + 2);
144                   disp = (buffer[byte] << 8) | (buffer[byte + 1]);
145                   break;
146                 case FPIND_D8:
147                 case DISP8:
148                   disp = ((char) (buffer[byte]));
149                   break;
150                 case RD:
151                 case RDIND:
152                   rd = buffer[byte] & 0x7;
153                   break;
154                 case ABS24:
155                   FETCH_DATA (info, buffer + byte + 3);
156                   abs_val =
157                     (buffer[byte] << 16)
158                     | (buffer[byte + 1] << 8)
159                     | (buffer[byte + 2]);
160                   break;
161                 case ABS16:
162                   FETCH_DATA (info, buffer + byte + 2);
163                   abs_val = (buffer[byte] << 8) | (buffer[byte + 1]);
164                   break;
165                 case ABS8:
166                   abs_val = (buffer[byte]);
167                   break;
168                 case IMM16:
169                   FETCH_DATA (info, buffer + byte + 2);
170                   imm = (buffer[byte] << 8) | (buffer[byte + 1]);
171                   break;
172                 case IMM4:
173                   imm = (buffer[byte]) & 0xf;
174                   break;
175                 case IMM8:
176                 case RLIST:
177                   imm = (buffer[byte]);
178                   break;
179                 case PCREL16:
180                   FETCH_DATA (info, buffer + byte + 2);
181                   pcrel = (buffer[byte] << 8) | (buffer[byte + 1]);
182                   break;
183                 case PCREL8:
184                   pcrel = (buffer[byte]);
185                   break;
186                 case QIM:
187                   switch (buffer[byte] & 0x7)
188                     {
189                     case 0:
190                       qim = 1;
191                       break;
192                     case 1:
193                       qim = 2;
194                       break;
195                     case 4:
196                       qim = -1;
197                       break;
198                     case 5:
199                       qim = -2;
200                       break;
201                     }
202                   break;
203
204                 }
205             }
206         }
207       /* We get here when all the masks have passed so we can output
208          the operands.  */
209       FETCH_DATA (info, buffer + opcode->length);
210       (func) (stream, "%s\t", opcode->name);
211       for (i = 0; i < opcode->nargs; i++)
212         {
213           if (i)
214             (func) (stream, ",");
215           switch (opcode->arg_type[i])
216             {
217             case FP:
218               func (stream, "fp");
219               break;
220             case RNIND_D16:
221               func (stream, "@(0x%x:16,r%d)", disp, rn);
222               break;
223             case RNIND_D8:
224               func (stream, "@(0x%x:8 (%d),r%d)", disp & 0xff, disp, rn);
225               break;
226             case RDIND_D16:
227               func (stream, "@(0x%x:16,r%d)", disp, rd);
228               break;
229             case RDIND_D8:
230               func (stream, "@(0x%x:8 (%d), r%d)", disp & 0xff, disp, rd);
231               break;
232             case FPIND_D8:
233               func (stream, "@(0x%x:8 (%d), fp)", disp & 0xff, disp);
234               break;
235             case CRB:
236             case CRW:
237               func (stream, "%s", crname[cr]);
238               break;
239             case RN:
240               func (stream, "r%d", rn);
241               break;
242             case RD:
243               func (stream, "r%d", rd);
244               break;
245             case RS:
246               func (stream, "r%d", rs);
247               break;
248             case RNDEC:
249               func (stream, "@-r%d", rn);
250               break;
251             case RNINC:
252               func (stream, "@r%d+", rn);
253               break;
254             case RNIND:
255               func (stream, "@r%d", rn);
256               break;
257             case RDIND:
258               func (stream, "@r%d", rd);
259               break;
260             case SPINC:
261               func (stream, "@sp+");
262               break;
263             case SPDEC:
264               func (stream, "@-sp");
265               break;
266             case ABS24:
267               func (stream, "@0x%0x:24", abs_val);
268               break;
269             case ABS16:
270               func (stream, "@0x%0x:16", abs_val & 0xffff);
271               break;
272             case ABS8:
273               func (stream, "@0x%0x:8", abs_val & 0xff);
274               break;
275             case IMM16:
276               func (stream, "#0x%0x:16", imm & 0xffff);
277               break;
278             case RLIST:
279               {
280                 int j;
281                 int nc = 0;
282
283                 func (stream, "(");
284                 for (j = 0; j < 8; j++)
285                   {
286                     if (imm & (1 << j))
287                       {
288                         func (stream, "r%d", j);
289                         if (nc)
290                           func (stream, ",");
291                         nc = 1;
292                       }
293                   }
294                 func (stream, ")");
295               }
296               break;
297             case IMM8:
298               func (stream, "#0x%0x:8", imm & 0xff);
299               break;
300             case PCREL16:
301               func (stream, "0x%0x:16",
302                     (int)(pcrel + addr + opcode->length) & 0xffff);
303               break;
304             case PCREL8:
305               func (stream, "#0x%0x:8",
306                     (int)((char) pcrel + addr + opcode->length) & 0xffff);
307               break;
308             case QIM:
309               func (stream, "#%d:q", qim);
310               break;
311             case IMM4:
312               func (stream, "#%d:4", imm);
313               break;
314             }
315         }
316       return opcode->length;
317     next:
318       ;
319     }
320
321   /* Couldn't understand anything.  */
322   /* xgettext:c-format */
323   func (stream, _("%02x\t\t*unknown*"), buffer[0]);
324   return 1;
325 }