1*3d8817e4Smiod /* Disassemble SH64 instructions.
2*3d8817e4Smiod    Copyright 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
3*3d8817e4Smiod 
4*3d8817e4Smiod    This program is free software; you can redistribute it and/or modify
5*3d8817e4Smiod    it under the terms of the GNU General Public License as published by
6*3d8817e4Smiod    the Free Software Foundation; either version 2 of the License, or
7*3d8817e4Smiod    (at your option) any later version.
8*3d8817e4Smiod 
9*3d8817e4Smiod    This program is distributed in the hope that it will be useful,
10*3d8817e4Smiod    but WITHOUT ANY WARRANTY; without even the implied warranty of
11*3d8817e4Smiod    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12*3d8817e4Smiod    GNU General Public License for more details.
13*3d8817e4Smiod 
14*3d8817e4Smiod    You should have received a copy of the GNU General Public License
15*3d8817e4Smiod    along with this program; if not, write to the Free Software
16*3d8817e4Smiod    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
17*3d8817e4Smiod 
18*3d8817e4Smiod #include <stdio.h>
19*3d8817e4Smiod 
20*3d8817e4Smiod #include "dis-asm.h"
21*3d8817e4Smiod #include "sysdep.h"
22*3d8817e4Smiod #include "sh64-opc.h"
23*3d8817e4Smiod #include "libiberty.h"
24*3d8817e4Smiod /* We need to refer to the ELF header structure.  */
25*3d8817e4Smiod #include "elf-bfd.h"
26*3d8817e4Smiod #include "elf/sh.h"
27*3d8817e4Smiod #include "elf32-sh64.h"
28*3d8817e4Smiod 
29*3d8817e4Smiod #define ELF_MODE32_CODE_LABEL_P(SYM) \
30*3d8817e4Smiod  (((elf_symbol_type *) (SYM))->internal_elf_sym.st_other & STO_SH5_ISA32)
31*3d8817e4Smiod 
32*3d8817e4Smiod #define SAVED_MOVI_R(INFO) \
33*3d8817e4Smiod  (((struct sh64_disassemble_info *) ((INFO)->private_data))->address_reg)
34*3d8817e4Smiod 
35*3d8817e4Smiod #define SAVED_MOVI_IMM(INFO) \
36*3d8817e4Smiod  (((struct sh64_disassemble_info *) ((INFO)->private_data))->built_address)
37*3d8817e4Smiod 
38*3d8817e4Smiod struct sh64_disassemble_info
39*3d8817e4Smiod  {
40*3d8817e4Smiod    /* When we see a MOVI, we save the register and the value, and merge a
41*3d8817e4Smiod       subsequent SHORI and display the address, if there is one.  */
42*3d8817e4Smiod    unsigned int address_reg;
43*3d8817e4Smiod    bfd_signed_vma built_address;
44*3d8817e4Smiod 
45*3d8817e4Smiod    /* This is the range decriptor for the current address.  It is kept
46*3d8817e4Smiod       around for the next call.  */
47*3d8817e4Smiod    sh64_elf_crange crange;
48*3d8817e4Smiod  };
49*3d8817e4Smiod 
50*3d8817e4Smiod /* Each item in the table is a mask to indicate which bits to be set
51*3d8817e4Smiod    to determine an instruction's operator.
52*3d8817e4Smiod    The index is as same as the instruction in the opcode table.
53*3d8817e4Smiod    Note that some archs have this as a field in the opcode table.  */
54*3d8817e4Smiod static unsigned long *shmedia_opcode_mask_table;
55*3d8817e4Smiod 
56*3d8817e4Smiod /* Initialize the SH64 opcode mask table for each instruction in SHmedia
57*3d8817e4Smiod    mode.  */
58*3d8817e4Smiod 
59*3d8817e4Smiod static void
initialize_shmedia_opcode_mask_table(void)60*3d8817e4Smiod initialize_shmedia_opcode_mask_table (void)
61*3d8817e4Smiod {
62*3d8817e4Smiod   int n_opc;
63*3d8817e4Smiod   int n;
64*3d8817e4Smiod 
65*3d8817e4Smiod   /* Calculate number of opcodes.  */
66*3d8817e4Smiod   for (n_opc = 0; shmedia_table[n_opc].name != NULL; n_opc++)
67*3d8817e4Smiod     ;
68*3d8817e4Smiod 
69*3d8817e4Smiod   shmedia_opcode_mask_table
70*3d8817e4Smiod     = xmalloc (sizeof (shmedia_opcode_mask_table[0]) * n_opc);
71*3d8817e4Smiod 
72*3d8817e4Smiod   for (n = 0; n < n_opc; n++)
73*3d8817e4Smiod     {
74*3d8817e4Smiod       int i;
75*3d8817e4Smiod 
76*3d8817e4Smiod       unsigned long mask = 0;
77*3d8817e4Smiod 
78*3d8817e4Smiod       for (i = 0; shmedia_table[n].arg[i] != A_NONE; i++)
79*3d8817e4Smiod 	{
80*3d8817e4Smiod 	  int offset = shmedia_table[n].nibbles[i];
81*3d8817e4Smiod 	  int length;
82*3d8817e4Smiod 
83*3d8817e4Smiod 	  switch (shmedia_table[n].arg[i])
84*3d8817e4Smiod 	    {
85*3d8817e4Smiod 	    case A_GREG_M:
86*3d8817e4Smiod 	    case A_GREG_N:
87*3d8817e4Smiod 	    case A_GREG_D:
88*3d8817e4Smiod 	    case A_CREG_K:
89*3d8817e4Smiod 	    case A_CREG_J:
90*3d8817e4Smiod 	    case A_FREG_G:
91*3d8817e4Smiod 	    case A_FREG_H:
92*3d8817e4Smiod 	    case A_FREG_F:
93*3d8817e4Smiod 	    case A_DREG_G:
94*3d8817e4Smiod 	    case A_DREG_H:
95*3d8817e4Smiod 	    case A_DREG_F:
96*3d8817e4Smiod 	    case A_FMREG_G:
97*3d8817e4Smiod 	    case A_FMREG_H:
98*3d8817e4Smiod 	    case A_FMREG_F:
99*3d8817e4Smiod 	    case A_FPREG_G:
100*3d8817e4Smiod 	    case A_FPREG_H:
101*3d8817e4Smiod 	    case A_FPREG_F:
102*3d8817e4Smiod 	    case A_FVREG_G:
103*3d8817e4Smiod 	    case A_FVREG_H:
104*3d8817e4Smiod 	    case A_FVREG_F:
105*3d8817e4Smiod 	    case A_REUSE_PREV:
106*3d8817e4Smiod 	      length = 6;
107*3d8817e4Smiod 	      break;
108*3d8817e4Smiod 
109*3d8817e4Smiod 	    case A_TREG_A:
110*3d8817e4Smiod 	    case A_TREG_B:
111*3d8817e4Smiod 	      length = 3;
112*3d8817e4Smiod 	      break;
113*3d8817e4Smiod 
114*3d8817e4Smiod 	    case A_IMMM:
115*3d8817e4Smiod 	      abort ();
116*3d8817e4Smiod 	      break;
117*3d8817e4Smiod 
118*3d8817e4Smiod 	    case A_IMMU5:
119*3d8817e4Smiod 	      length = 5;
120*3d8817e4Smiod 	      break;
121*3d8817e4Smiod 
122*3d8817e4Smiod 	    case A_IMMS6:
123*3d8817e4Smiod 	    case A_IMMU6:
124*3d8817e4Smiod 	    case A_IMMS6BY32:
125*3d8817e4Smiod 	      length = 6;
126*3d8817e4Smiod 	      break;
127*3d8817e4Smiod 
128*3d8817e4Smiod 	    case A_IMMS10:
129*3d8817e4Smiod 	    case A_IMMS10BY1:
130*3d8817e4Smiod 	    case A_IMMS10BY2:
131*3d8817e4Smiod 	    case A_IMMS10BY4:
132*3d8817e4Smiod 	    case A_IMMS10BY8:
133*3d8817e4Smiod 	      length = 10;
134*3d8817e4Smiod 	      break;
135*3d8817e4Smiod 
136*3d8817e4Smiod 	    case A_IMMU16:
137*3d8817e4Smiod 	    case A_IMMS16:
138*3d8817e4Smiod 	    case A_PCIMMS16BY4:
139*3d8817e4Smiod 	    case A_PCIMMS16BY4_PT:
140*3d8817e4Smiod 	      length = 16;
141*3d8817e4Smiod 	      break;
142*3d8817e4Smiod 
143*3d8817e4Smiod 	    default:
144*3d8817e4Smiod 	      abort ();
145*3d8817e4Smiod 	      length = 0;
146*3d8817e4Smiod 	      break;
147*3d8817e4Smiod 	    }
148*3d8817e4Smiod 
149*3d8817e4Smiod 	  if (length != 0)
150*3d8817e4Smiod 	    mask |= (0xffffffff >> (32 - length)) << offset;
151*3d8817e4Smiod 	}
152*3d8817e4Smiod       shmedia_opcode_mask_table[n] = 0xffffffff & ~mask;
153*3d8817e4Smiod     }
154*3d8817e4Smiod }
155*3d8817e4Smiod 
156*3d8817e4Smiod /* Get a predefined control-register-name, or return NULL.  */
157*3d8817e4Smiod 
158*3d8817e4Smiod static const char *
creg_name(int cregno)159*3d8817e4Smiod creg_name (int cregno)
160*3d8817e4Smiod {
161*3d8817e4Smiod   const shmedia_creg_info *cregp;
162*3d8817e4Smiod 
163*3d8817e4Smiod   /* If control register usage is common enough, change this to search a
164*3d8817e4Smiod      hash-table.  */
165*3d8817e4Smiod   for (cregp = shmedia_creg_table; cregp->name != NULL; cregp++)
166*3d8817e4Smiod     if (cregp->cregno == cregno)
167*3d8817e4Smiod       return cregp->name;
168*3d8817e4Smiod 
169*3d8817e4Smiod   return NULL;
170*3d8817e4Smiod }
171*3d8817e4Smiod 
172*3d8817e4Smiod /* Main function to disassemble SHmedia instructions.  */
173*3d8817e4Smiod 
174*3d8817e4Smiod static int
print_insn_shmedia(bfd_vma memaddr,struct disassemble_info * info)175*3d8817e4Smiod print_insn_shmedia (bfd_vma memaddr, struct disassemble_info *info)
176*3d8817e4Smiod {
177*3d8817e4Smiod   fprintf_ftype fprintf_fn = info->fprintf_func;
178*3d8817e4Smiod   void *stream = info->stream;
179*3d8817e4Smiod   unsigned char insn[4];
180*3d8817e4Smiod   unsigned long instruction;
181*3d8817e4Smiod   int status;
182*3d8817e4Smiod   int n;
183*3d8817e4Smiod   const shmedia_opcode_info *op;
184*3d8817e4Smiod   int i;
185*3d8817e4Smiod   unsigned int r = 0;
186*3d8817e4Smiod   long imm = 0;
187*3d8817e4Smiod   bfd_vma disp_pc_addr;
188*3d8817e4Smiod 
189*3d8817e4Smiod   status = info->read_memory_func (memaddr, insn, 4, info);
190*3d8817e4Smiod 
191*3d8817e4Smiod   /* If we can't read four bytes, something is wrong.  Display any data we
192*3d8817e4Smiod      can get as .byte:s.  */
193*3d8817e4Smiod   if (status != 0)
194*3d8817e4Smiod     {
195*3d8817e4Smiod       int i;
196*3d8817e4Smiod 
197*3d8817e4Smiod       for (i = 0; i < 3; i++)
198*3d8817e4Smiod 	{
199*3d8817e4Smiod 	  status = info->read_memory_func (memaddr + i, insn, 1, info);
200*3d8817e4Smiod 	  if (status != 0)
201*3d8817e4Smiod 	    break;
202*3d8817e4Smiod 	  (*fprintf_fn) (stream, "%s0x%02x",
203*3d8817e4Smiod 			 i == 0 ? ".byte " : ", ",
204*3d8817e4Smiod 			 insn[0]);
205*3d8817e4Smiod 	}
206*3d8817e4Smiod 
207*3d8817e4Smiod       return i ? i : -1;
208*3d8817e4Smiod     }
209*3d8817e4Smiod 
210*3d8817e4Smiod   /* Rearrange the bytes to make up an instruction.  */
211*3d8817e4Smiod   if (info->endian == BFD_ENDIAN_LITTLE)
212*3d8817e4Smiod     instruction = bfd_getl32 (insn);
213*3d8817e4Smiod   else
214*3d8817e4Smiod     instruction = bfd_getb32 (insn);
215*3d8817e4Smiod 
216*3d8817e4Smiod   /* FIXME: Searching could be implemented using a hash on relevant
217*3d8817e4Smiod      fields.  */
218*3d8817e4Smiod   for (n = 0, op = shmedia_table;
219*3d8817e4Smiod        op->name != NULL
220*3d8817e4Smiod        && ((instruction & shmedia_opcode_mask_table[n]) != op->opcode_base);
221*3d8817e4Smiod        n++, op++)
222*3d8817e4Smiod     ;
223*3d8817e4Smiod 
224*3d8817e4Smiod   /* FIXME: We should also check register number constraints.  */
225*3d8817e4Smiod   if (op->name == NULL)
226*3d8817e4Smiod     {
227*3d8817e4Smiod       fprintf_fn (stream, ".long 0x%08lx", instruction);
228*3d8817e4Smiod       return 4;
229*3d8817e4Smiod     }
230*3d8817e4Smiod 
231*3d8817e4Smiod   fprintf_fn (stream, "%s\t", op->name);
232*3d8817e4Smiod 
233*3d8817e4Smiod   for (i = 0; i < 3 && op->arg[i] != A_NONE; i++)
234*3d8817e4Smiod     {
235*3d8817e4Smiod       unsigned long temp = instruction >> op->nibbles[i];
236*3d8817e4Smiod       int by_number = 0;
237*3d8817e4Smiod 
238*3d8817e4Smiod       if (i > 0 && op->arg[i] != A_REUSE_PREV)
239*3d8817e4Smiod 	fprintf_fn (stream, ",");
240*3d8817e4Smiod 
241*3d8817e4Smiod       switch (op->arg[i])
242*3d8817e4Smiod 	{
243*3d8817e4Smiod 	case A_REUSE_PREV:
244*3d8817e4Smiod 	  continue;
245*3d8817e4Smiod 
246*3d8817e4Smiod 	case A_GREG_M:
247*3d8817e4Smiod 	case A_GREG_N:
248*3d8817e4Smiod 	case A_GREG_D:
249*3d8817e4Smiod 	  r = temp & 0x3f;
250*3d8817e4Smiod 	  fprintf_fn (stream, "r%d", r);
251*3d8817e4Smiod 	  break;
252*3d8817e4Smiod 
253*3d8817e4Smiod 	case A_FVREG_F:
254*3d8817e4Smiod 	case A_FVREG_G:
255*3d8817e4Smiod 	case A_FVREG_H:
256*3d8817e4Smiod 	  r = temp & 0x3f;
257*3d8817e4Smiod 	  fprintf_fn (stream, "fv%d", r);
258*3d8817e4Smiod 	  break;
259*3d8817e4Smiod 
260*3d8817e4Smiod 	case A_FPREG_F:
261*3d8817e4Smiod 	case A_FPREG_G:
262*3d8817e4Smiod 	case A_FPREG_H:
263*3d8817e4Smiod 	  r = temp & 0x3f;
264*3d8817e4Smiod 	  fprintf_fn (stream, "fp%d", r);
265*3d8817e4Smiod 	  break;
266*3d8817e4Smiod 
267*3d8817e4Smiod 	case A_FMREG_F:
268*3d8817e4Smiod 	case A_FMREG_G:
269*3d8817e4Smiod 	case A_FMREG_H:
270*3d8817e4Smiod 	  r = temp & 0x3f;
271*3d8817e4Smiod 	  fprintf_fn (stream, "mtrx%d", r);
272*3d8817e4Smiod 	  break;
273*3d8817e4Smiod 
274*3d8817e4Smiod 	case A_CREG_K:
275*3d8817e4Smiod 	case A_CREG_J:
276*3d8817e4Smiod 	  {
277*3d8817e4Smiod 	    const char *name;
278*3d8817e4Smiod 
279*3d8817e4Smiod 	    r = temp & 0x3f;
280*3d8817e4Smiod 
281*3d8817e4Smiod 	    name = creg_name (r);
282*3d8817e4Smiod 
283*3d8817e4Smiod 	    if (name != NULL)
284*3d8817e4Smiod 	      fprintf_fn (stream, "%s", name);
285*3d8817e4Smiod 	    else
286*3d8817e4Smiod 	      fprintf_fn (stream, "cr%d", r);
287*3d8817e4Smiod 	  }
288*3d8817e4Smiod 	  break;
289*3d8817e4Smiod 
290*3d8817e4Smiod 	case A_FREG_G:
291*3d8817e4Smiod 	case A_FREG_H:
292*3d8817e4Smiod 	case A_FREG_F:
293*3d8817e4Smiod 	  r = temp & 0x3f;
294*3d8817e4Smiod 	  fprintf_fn (stream, "fr%d", r);
295*3d8817e4Smiod 	  break;
296*3d8817e4Smiod 
297*3d8817e4Smiod 	case A_DREG_G:
298*3d8817e4Smiod 	case A_DREG_H:
299*3d8817e4Smiod 	case A_DREG_F:
300*3d8817e4Smiod 	  r = temp & 0x3f;
301*3d8817e4Smiod 	  fprintf_fn (stream, "dr%d", r);
302*3d8817e4Smiod 	  break;
303*3d8817e4Smiod 
304*3d8817e4Smiod 	case A_TREG_A:
305*3d8817e4Smiod 	case A_TREG_B:
306*3d8817e4Smiod 	  r = temp & 0x7;
307*3d8817e4Smiod 	  fprintf_fn (stream, "tr%d", r);
308*3d8817e4Smiod 	  break;
309*3d8817e4Smiod 
310*3d8817e4Smiod 	  /* A signed 6-bit number.  */
311*3d8817e4Smiod 	case A_IMMS6:
312*3d8817e4Smiod 	  imm = temp & 0x3f;
313*3d8817e4Smiod 	  if (imm & (unsigned long) 0x20)
314*3d8817e4Smiod 	    imm |= ~(unsigned long) 0x3f;
315*3d8817e4Smiod 	  fprintf_fn (stream, "%ld", imm);
316*3d8817e4Smiod 	  break;
317*3d8817e4Smiod 
318*3d8817e4Smiod 	  /* A signed 6-bit number, multiplied by 32 when used.  */
319*3d8817e4Smiod 	case A_IMMS6BY32:
320*3d8817e4Smiod 	  imm = temp & 0x3f;
321*3d8817e4Smiod 	  if (imm & (unsigned long) 0x20)
322*3d8817e4Smiod 	    imm |= ~(unsigned long) 0x3f;
323*3d8817e4Smiod 	  fprintf_fn (stream, "%ld", imm * 32);
324*3d8817e4Smiod 	  break;
325*3d8817e4Smiod 
326*3d8817e4Smiod 	  /* A signed 10-bit number, multiplied by 8 when used.  */
327*3d8817e4Smiod 	case A_IMMS10BY8:
328*3d8817e4Smiod 	  by_number++;
329*3d8817e4Smiod 	  /* Fall through.  */
330*3d8817e4Smiod 
331*3d8817e4Smiod 	  /* A signed 10-bit number, multiplied by 4 when used.  */
332*3d8817e4Smiod 	case A_IMMS10BY4:
333*3d8817e4Smiod 	  by_number++;
334*3d8817e4Smiod 	  /* Fall through.  */
335*3d8817e4Smiod 
336*3d8817e4Smiod 	  /* A signed 10-bit number, multiplied by 2 when used.  */
337*3d8817e4Smiod 	case A_IMMS10BY2:
338*3d8817e4Smiod 	  by_number++;
339*3d8817e4Smiod 	  /* Fall through.  */
340*3d8817e4Smiod 
341*3d8817e4Smiod 	  /* A signed 10-bit number.  */
342*3d8817e4Smiod 	case A_IMMS10:
343*3d8817e4Smiod 	case A_IMMS10BY1:
344*3d8817e4Smiod 	  imm = temp & 0x3ff;
345*3d8817e4Smiod 	  if (imm & (unsigned long) 0x200)
346*3d8817e4Smiod 	    imm |= ~(unsigned long) 0x3ff;
347*3d8817e4Smiod 	  imm <<= by_number;
348*3d8817e4Smiod 	  fprintf_fn (stream, "%ld", imm);
349*3d8817e4Smiod 	  break;
350*3d8817e4Smiod 
351*3d8817e4Smiod 	  /* A signed 16-bit number.  */
352*3d8817e4Smiod 	case A_IMMS16:
353*3d8817e4Smiod 	  imm = temp & 0xffff;
354*3d8817e4Smiod 	  if (imm & (unsigned long) 0x8000)
355*3d8817e4Smiod 	    imm |= ~((unsigned long) 0xffff);
356*3d8817e4Smiod 	  fprintf_fn (stream, "%ld", imm);
357*3d8817e4Smiod 	  break;
358*3d8817e4Smiod 
359*3d8817e4Smiod 	  /* A PC-relative signed 16-bit number, multiplied by 4 when
360*3d8817e4Smiod 	     used.  */
361*3d8817e4Smiod 	case A_PCIMMS16BY4:
362*3d8817e4Smiod 	  imm = temp & 0xffff;	/* 16 bits */
363*3d8817e4Smiod 	  if (imm & (unsigned long) 0x8000)
364*3d8817e4Smiod 	    imm |= ~(unsigned long) 0xffff;
365*3d8817e4Smiod 	  imm <<= 2;
366*3d8817e4Smiod 	  disp_pc_addr = (bfd_vma) imm + memaddr;
367*3d8817e4Smiod 	  (*info->print_address_func) (disp_pc_addr, info);
368*3d8817e4Smiod 	  break;
369*3d8817e4Smiod 
370*3d8817e4Smiod 	  /* An unsigned 5-bit number.  */
371*3d8817e4Smiod 	case A_IMMU5:
372*3d8817e4Smiod 	  imm = temp & 0x1f;
373*3d8817e4Smiod 	  fprintf_fn (stream, "%ld", imm);
374*3d8817e4Smiod 	  break;
375*3d8817e4Smiod 
376*3d8817e4Smiod 	  /* An unsigned 6-bit number.  */
377*3d8817e4Smiod 	case A_IMMU6:
378*3d8817e4Smiod 	  imm = temp & 0x3f;
379*3d8817e4Smiod 	  fprintf_fn (stream, "%ld", imm);
380*3d8817e4Smiod 	  break;
381*3d8817e4Smiod 
382*3d8817e4Smiod 	  /* An unsigned 16-bit number.  */
383*3d8817e4Smiod 	case A_IMMU16:
384*3d8817e4Smiod 	  imm = temp & 0xffff;
385*3d8817e4Smiod 	  fprintf_fn (stream, "%ld", imm);
386*3d8817e4Smiod 	  break;
387*3d8817e4Smiod 
388*3d8817e4Smiod 	default:
389*3d8817e4Smiod 	  abort ();
390*3d8817e4Smiod 	  break;
391*3d8817e4Smiod 	}
392*3d8817e4Smiod     }
393*3d8817e4Smiod 
394*3d8817e4Smiod   /* FIXME: Looks like 32-bit values only are handled.
395*3d8817e4Smiod      FIXME: PC-relative numbers aren't handled correctly.  */
396*3d8817e4Smiod   if (op->opcode_base == (unsigned long) SHMEDIA_SHORI_OPC
397*3d8817e4Smiod       && SAVED_MOVI_R (info) == r)
398*3d8817e4Smiod     {
399*3d8817e4Smiod       asection *section = info->section;
400*3d8817e4Smiod 
401*3d8817e4Smiod       /* Most callers do not set the section field correctly yet.  Revert
402*3d8817e4Smiod 	 to getting the section from symbols, if any. */
403*3d8817e4Smiod       if (section == NULL
404*3d8817e4Smiod 	  && info->symbols != NULL
405*3d8817e4Smiod 	  && bfd_asymbol_flavour (info->symbols[0]) == bfd_target_elf_flavour
406*3d8817e4Smiod 	  && ! bfd_is_und_section (bfd_get_section (info->symbols[0]))
407*3d8817e4Smiod 	  && ! bfd_is_abs_section (bfd_get_section (info->symbols[0])))
408*3d8817e4Smiod 	section = bfd_get_section (info->symbols[0]);
409*3d8817e4Smiod 
410*3d8817e4Smiod       /* Only guess addresses when the contents of this section is fully
411*3d8817e4Smiod 	 relocated.  Otherwise, the value will be zero or perhaps even
412*3d8817e4Smiod 	 bogus.  */
413*3d8817e4Smiod       if (section == NULL
414*3d8817e4Smiod 	  || section->owner == NULL
415*3d8817e4Smiod 	  || elf_elfheader (section->owner)->e_type == ET_EXEC)
416*3d8817e4Smiod 	{
417*3d8817e4Smiod 	  bfd_signed_vma shori_addr;
418*3d8817e4Smiod 
419*3d8817e4Smiod 	  shori_addr = SAVED_MOVI_IMM (info) << 16;
420*3d8817e4Smiod 	  shori_addr |= imm;
421*3d8817e4Smiod 
422*3d8817e4Smiod 	  fprintf_fn (stream, "\t! 0x");
423*3d8817e4Smiod 	  (*info->print_address_func) (shori_addr, info);
424*3d8817e4Smiod 	}
425*3d8817e4Smiod     }
426*3d8817e4Smiod 
427*3d8817e4Smiod   if (op->opcode_base == SHMEDIA_MOVI_OPC)
428*3d8817e4Smiod     {
429*3d8817e4Smiod       SAVED_MOVI_IMM (info) = imm;
430*3d8817e4Smiod       SAVED_MOVI_R (info) = r;
431*3d8817e4Smiod     }
432*3d8817e4Smiod   else
433*3d8817e4Smiod     {
434*3d8817e4Smiod       SAVED_MOVI_IMM (info) = 0;
435*3d8817e4Smiod       SAVED_MOVI_R (info) = 255;
436*3d8817e4Smiod     }
437*3d8817e4Smiod 
438*3d8817e4Smiod   return 4;
439*3d8817e4Smiod }
440*3d8817e4Smiod 
441*3d8817e4Smiod /* Check the type of contents about to be disassembled.  This is like
442*3d8817e4Smiod    sh64_get_contents_type (which may be called from here), except that it
443*3d8817e4Smiod    takes the same arguments as print_insn_* and does what can be done if
444*3d8817e4Smiod    no section is available.  */
445*3d8817e4Smiod 
446*3d8817e4Smiod static enum sh64_elf_cr_type
sh64_get_contents_type_disasm(bfd_vma memaddr,struct disassemble_info * info)447*3d8817e4Smiod sh64_get_contents_type_disasm (bfd_vma memaddr, struct disassemble_info *info)
448*3d8817e4Smiod {
449*3d8817e4Smiod   struct sh64_disassemble_info *sh64_infop = info->private_data;
450*3d8817e4Smiod 
451*3d8817e4Smiod   /* Perhaps we have a region from a previous probe and it still counts
452*3d8817e4Smiod      for this address?  */
453*3d8817e4Smiod   if (sh64_infop->crange.cr_type != CRT_NONE
454*3d8817e4Smiod       && memaddr >= sh64_infop->crange.cr_addr
455*3d8817e4Smiod       && memaddr < sh64_infop->crange.cr_addr + sh64_infop->crange.cr_size)
456*3d8817e4Smiod     return sh64_infop->crange.cr_type;
457*3d8817e4Smiod 
458*3d8817e4Smiod   /* If we have a section, try and use it.  */
459*3d8817e4Smiod   if (info->section
460*3d8817e4Smiod       && bfd_get_flavour (info->section->owner) == bfd_target_elf_flavour)
461*3d8817e4Smiod     {
462*3d8817e4Smiod       enum sh64_elf_cr_type cr_type
463*3d8817e4Smiod 	= sh64_get_contents_type (info->section, memaddr,
464*3d8817e4Smiod 				  &sh64_infop->crange);
465*3d8817e4Smiod 
466*3d8817e4Smiod       if (cr_type != CRT_NONE)
467*3d8817e4Smiod 	return cr_type;
468*3d8817e4Smiod     }
469*3d8817e4Smiod 
470*3d8817e4Smiod   /* If we have symbols, we can try and get at a section from *that*.  */
471*3d8817e4Smiod   if (info->symbols != NULL
472*3d8817e4Smiod       && bfd_asymbol_flavour (info->symbols[0]) == bfd_target_elf_flavour
473*3d8817e4Smiod       && ! bfd_is_und_section (bfd_get_section (info->symbols[0]))
474*3d8817e4Smiod       && ! bfd_is_abs_section (bfd_get_section (info->symbols[0])))
475*3d8817e4Smiod     {
476*3d8817e4Smiod       enum sh64_elf_cr_type cr_type
477*3d8817e4Smiod 	= sh64_get_contents_type (bfd_get_section (info->symbols[0]),
478*3d8817e4Smiod 				  memaddr, &sh64_infop->crange);
479*3d8817e4Smiod 
480*3d8817e4Smiod       if (cr_type != CRT_NONE)
481*3d8817e4Smiod 	return cr_type;
482*3d8817e4Smiod     }
483*3d8817e4Smiod 
484*3d8817e4Smiod   /* We can make a reasonable guess based on the st_other field of a
485*3d8817e4Smiod      symbol; for a BranchTarget this is marked as STO_SH5_ISA32 and then
486*3d8817e4Smiod      it's most probably code there.  */
487*3d8817e4Smiod   if (info->symbols
488*3d8817e4Smiod       && bfd_asymbol_flavour (info->symbols[0]) == bfd_target_elf_flavour
489*3d8817e4Smiod       && elf_symbol_from (bfd_asymbol_bfd (info->symbols[0]),
490*3d8817e4Smiod 			  info->symbols[0])->internal_elf_sym.st_other
491*3d8817e4Smiod       == STO_SH5_ISA32)
492*3d8817e4Smiod     return CRT_SH5_ISA32;
493*3d8817e4Smiod 
494*3d8817e4Smiod   /* If all else fails, guess this is code and guess on the low bit set.  */
495*3d8817e4Smiod   return (memaddr & 1) == 1 ? CRT_SH5_ISA32 : CRT_SH5_ISA16;
496*3d8817e4Smiod }
497*3d8817e4Smiod 
498*3d8817e4Smiod /* Initialize static and dynamic disassembly state.  */
499*3d8817e4Smiod 
500*3d8817e4Smiod static bfd_boolean
init_sh64_disasm_info(struct disassemble_info * info)501*3d8817e4Smiod init_sh64_disasm_info (struct disassemble_info *info)
502*3d8817e4Smiod {
503*3d8817e4Smiod   struct sh64_disassemble_info *sh64_infop
504*3d8817e4Smiod     = calloc (sizeof (*sh64_infop), 1);
505*3d8817e4Smiod 
506*3d8817e4Smiod   if (sh64_infop == NULL)
507*3d8817e4Smiod     return FALSE;
508*3d8817e4Smiod 
509*3d8817e4Smiod   info->private_data = sh64_infop;
510*3d8817e4Smiod 
511*3d8817e4Smiod   SAVED_MOVI_IMM (info) = 0;
512*3d8817e4Smiod   SAVED_MOVI_R (info) = 255;
513*3d8817e4Smiod 
514*3d8817e4Smiod   if (shmedia_opcode_mask_table == NULL)
515*3d8817e4Smiod     initialize_shmedia_opcode_mask_table ();
516*3d8817e4Smiod 
517*3d8817e4Smiod   return TRUE;
518*3d8817e4Smiod }
519*3d8817e4Smiod 
520*3d8817e4Smiod /* Main entry to disassemble SHmedia instructions, given an endian set in
521*3d8817e4Smiod    INFO.  Note that the simulator uses this as the main entry and does not
522*3d8817e4Smiod    use any of the functions further below.  */
523*3d8817e4Smiod 
524*3d8817e4Smiod int
print_insn_sh64x_media(bfd_vma memaddr,struct disassemble_info * info)525*3d8817e4Smiod print_insn_sh64x_media (bfd_vma memaddr, struct disassemble_info *info)
526*3d8817e4Smiod {
527*3d8817e4Smiod   if (info->private_data == NULL && ! init_sh64_disasm_info (info))
528*3d8817e4Smiod     return -1;
529*3d8817e4Smiod 
530*3d8817e4Smiod   /* Make reasonable output.  */
531*3d8817e4Smiod   info->bytes_per_line = 4;
532*3d8817e4Smiod   info->bytes_per_chunk = 4;
533*3d8817e4Smiod 
534*3d8817e4Smiod   return print_insn_shmedia (memaddr, info);
535*3d8817e4Smiod }
536*3d8817e4Smiod 
537*3d8817e4Smiod /* Main entry to disassemble SHmedia insns.
538*3d8817e4Smiod    If we see an SHcompact instruction, return -2.  */
539*3d8817e4Smiod 
540*3d8817e4Smiod int
print_insn_sh64(bfd_vma memaddr,struct disassemble_info * info)541*3d8817e4Smiod print_insn_sh64 (bfd_vma memaddr, struct disassemble_info *info)
542*3d8817e4Smiod {
543*3d8817e4Smiod   enum bfd_endian endian = info->endian;
544*3d8817e4Smiod   enum sh64_elf_cr_type cr_type;
545*3d8817e4Smiod 
546*3d8817e4Smiod   if (info->private_data == NULL && ! init_sh64_disasm_info (info))
547*3d8817e4Smiod     return -1;
548*3d8817e4Smiod 
549*3d8817e4Smiod   cr_type = sh64_get_contents_type_disasm (memaddr, info);
550*3d8817e4Smiod   if (cr_type != CRT_SH5_ISA16)
551*3d8817e4Smiod     {
552*3d8817e4Smiod       int length = 4 - (memaddr % 4);
553*3d8817e4Smiod       info->display_endian = endian;
554*3d8817e4Smiod 
555*3d8817e4Smiod       /* If we got an uneven address to indicate SHmedia, adjust it.  */
556*3d8817e4Smiod       if (cr_type == CRT_SH5_ISA32 && length == 3)
557*3d8817e4Smiod 	memaddr--, length = 4;
558*3d8817e4Smiod 
559*3d8817e4Smiod       /* Only disassemble on four-byte boundaries.  Addresses that are not
560*3d8817e4Smiod 	 a multiple of four can happen after a data region.  */
561*3d8817e4Smiod       if (cr_type == CRT_SH5_ISA32 && length == 4)
562*3d8817e4Smiod 	return print_insn_sh64x_media (memaddr, info);
563*3d8817e4Smiod 
564*3d8817e4Smiod       /* We get CRT_DATA *only* for data regions in a mixed-contents
565*3d8817e4Smiod 	 section.  For sections with data only, we get indication of one
566*3d8817e4Smiod 	 of the ISA:s.  You may think that we shouldn't disassemble
567*3d8817e4Smiod 	 section with only data if we can figure that out.  However, the
568*3d8817e4Smiod 	 disassembly function is by default not called for data-only
569*3d8817e4Smiod 	 sections, so if the user explicitly specified disassembly of a
570*3d8817e4Smiod 	 data section, that's what we should do.  */
571*3d8817e4Smiod       if (cr_type == CRT_DATA || length != 4)
572*3d8817e4Smiod 	{
573*3d8817e4Smiod 	  int status;
574*3d8817e4Smiod 	  unsigned char data[4];
575*3d8817e4Smiod 	  struct sh64_disassemble_info *sh64_infop = info->private_data;
576*3d8817e4Smiod 
577*3d8817e4Smiod 	  if (length == 4
578*3d8817e4Smiod 	      && sh64_infop->crange.cr_type != CRT_NONE
579*3d8817e4Smiod 	      && memaddr >= sh64_infop->crange.cr_addr
580*3d8817e4Smiod 	      && memaddr < (sh64_infop->crange.cr_addr
581*3d8817e4Smiod 			    + sh64_infop->crange.cr_size))
582*3d8817e4Smiod 	    length
583*3d8817e4Smiod 	      = (sh64_infop->crange.cr_addr
584*3d8817e4Smiod 		 + sh64_infop->crange.cr_size - memaddr);
585*3d8817e4Smiod 
586*3d8817e4Smiod 	  status
587*3d8817e4Smiod 	    = (*info->read_memory_func) (memaddr, data,
588*3d8817e4Smiod 					 length >= 4 ? 4 : length, info);
589*3d8817e4Smiod 
590*3d8817e4Smiod 	  if (status == 0 && length >= 4)
591*3d8817e4Smiod 	    {
592*3d8817e4Smiod 	      (*info->fprintf_func) (info->stream, ".long 0x%08lx",
593*3d8817e4Smiod 				     endian == BFD_ENDIAN_BIG
594*3d8817e4Smiod 				     ? (long) (bfd_getb32 (data))
595*3d8817e4Smiod 				     : (long) (bfd_getl32 (data)));
596*3d8817e4Smiod 	      return 4;
597*3d8817e4Smiod 	    }
598*3d8817e4Smiod 	  else
599*3d8817e4Smiod 	    {
600*3d8817e4Smiod 	      int i;
601*3d8817e4Smiod 
602*3d8817e4Smiod 	      for (i = 0; i < length; i++)
603*3d8817e4Smiod 		{
604*3d8817e4Smiod 		  status = info->read_memory_func (memaddr + i, data, 1, info);
605*3d8817e4Smiod 		  if (status != 0)
606*3d8817e4Smiod 		    break;
607*3d8817e4Smiod 		  (*info->fprintf_func) (info->stream, "%s0x%02x",
608*3d8817e4Smiod 					 i == 0 ? ".byte " : ", ",
609*3d8817e4Smiod 					 data[0]);
610*3d8817e4Smiod 		}
611*3d8817e4Smiod 
612*3d8817e4Smiod 	      return i ? i : -1;
613*3d8817e4Smiod 	    }
614*3d8817e4Smiod 	}
615*3d8817e4Smiod     }
616*3d8817e4Smiod 
617*3d8817e4Smiod   /* SH1 .. SH4 instruction, let caller handle it.  */
618*3d8817e4Smiod   return -2;
619*3d8817e4Smiod }
620