1440a403fSchristos /* tc-h8300.c -- Assemble code for the Renesas H8/300
2*b88e3e88Schristos    Copyright (C) 1991-2020 Free Software Foundation, Inc.
3440a403fSchristos 
4440a403fSchristos    This file is part of GAS, the GNU Assembler.
5440a403fSchristos 
6440a403fSchristos    GAS is free software; you can redistribute it and/or modify
7440a403fSchristos    it under the terms of the GNU General Public License as published by
8440a403fSchristos    the Free Software Foundation; either version 3, or (at your option)
9440a403fSchristos    any later version.
10440a403fSchristos 
11440a403fSchristos    GAS is distributed in the hope that it will be useful,
12440a403fSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
13440a403fSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14440a403fSchristos    GNU General Public License for more details.
15440a403fSchristos 
16440a403fSchristos    You should have received a copy of the GNU General Public License
17440a403fSchristos    along with GAS; see the file COPYING.  If not, write to the Free
18440a403fSchristos    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
19440a403fSchristos    02110-1301, USA.  */
20440a403fSchristos 
21440a403fSchristos /* Written By Steve Chamberlain <sac@cygnus.com>.  */
22440a403fSchristos 
23440a403fSchristos #include "as.h"
24440a403fSchristos #include "subsegs.h"
25440a403fSchristos #include "dwarf2dbg.h"
26440a403fSchristos 
27440a403fSchristos #define DEFINE_TABLE
28440a403fSchristos #define h8_opcodes ops
29440a403fSchristos #include "opcode/h8300.h"
30440a403fSchristos #include "safe-ctype.h"
31440a403fSchristos #include "elf/h8.h"
32440a403fSchristos 
33440a403fSchristos const char comment_chars[] = ";";
34440a403fSchristos const char line_comment_chars[] = "#";
35440a403fSchristos #ifdef TE_LINUX
36440a403fSchristos const char line_separator_chars[] = "!";
37440a403fSchristos #else
38440a403fSchristos const char line_separator_chars[] = "";
39440a403fSchristos #endif
40440a403fSchristos 
41440a403fSchristos static void sbranch (int);
42440a403fSchristos static void h8300hmode (int);
43440a403fSchristos static void h8300smode (int);
44440a403fSchristos static void h8300hnmode (int);
45440a403fSchristos static void h8300snmode (int);
46440a403fSchristos static void h8300sxmode (int);
47440a403fSchristos static void h8300sxnmode (int);
48440a403fSchristos static void pint (int);
49440a403fSchristos 
50440a403fSchristos int Hmode;
51440a403fSchristos int Smode;
52440a403fSchristos int Nmode;
53440a403fSchristos int SXmode;
54440a403fSchristos 
55440a403fSchristos static int default_mach = bfd_mach_h8300;
56440a403fSchristos 
57440a403fSchristos #define PSIZE (Hmode && !Nmode ? L_32 : L_16)
58440a403fSchristos 
59440a403fSchristos static int bsize = L_8;		/* Default branch displacement.  */
60440a403fSchristos 
61440a403fSchristos struct h8_instruction
62440a403fSchristos {
63440a403fSchristos   int length;
64440a403fSchristos   int noperands;
65440a403fSchristos   int idx;
66440a403fSchristos   int size;
67440a403fSchristos   const struct h8_opcode *opcode;
68440a403fSchristos };
69440a403fSchristos 
70440a403fSchristos static struct h8_instruction *h8_instructions;
71440a403fSchristos 
72440a403fSchristos static void
h8300hmode(int arg ATTRIBUTE_UNUSED)73440a403fSchristos h8300hmode (int arg ATTRIBUTE_UNUSED)
74440a403fSchristos {
75440a403fSchristos   Hmode = 1;
76440a403fSchristos   Smode = 0;
77440a403fSchristos   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300h))
78440a403fSchristos     as_warn (_("could not set architecture and machine"));
79440a403fSchristos }
80440a403fSchristos 
81440a403fSchristos static void
h8300smode(int arg ATTRIBUTE_UNUSED)82440a403fSchristos h8300smode (int arg ATTRIBUTE_UNUSED)
83440a403fSchristos {
84440a403fSchristos   Smode = 1;
85440a403fSchristos   Hmode = 1;
86440a403fSchristos   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300s))
87440a403fSchristos     as_warn (_("could not set architecture and machine"));
88440a403fSchristos }
89440a403fSchristos 
90440a403fSchristos static void
h8300hnmode(int arg ATTRIBUTE_UNUSED)91440a403fSchristos h8300hnmode (int arg ATTRIBUTE_UNUSED)
92440a403fSchristos {
93440a403fSchristos   Hmode = 1;
94440a403fSchristos   Smode = 0;
95440a403fSchristos   Nmode = 1;
96440a403fSchristos   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300hn))
97440a403fSchristos     as_warn (_("could not set architecture and machine"));
98440a403fSchristos }
99440a403fSchristos 
100440a403fSchristos static void
h8300snmode(int arg ATTRIBUTE_UNUSED)101440a403fSchristos h8300snmode (int arg ATTRIBUTE_UNUSED)
102440a403fSchristos {
103440a403fSchristos   Smode = 1;
104440a403fSchristos   Hmode = 1;
105440a403fSchristos   Nmode = 1;
106440a403fSchristos   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300sn))
107440a403fSchristos     as_warn (_("could not set architecture and machine"));
108440a403fSchristos }
109440a403fSchristos 
110440a403fSchristos static void
h8300sxmode(int arg ATTRIBUTE_UNUSED)111440a403fSchristos h8300sxmode (int arg ATTRIBUTE_UNUSED)
112440a403fSchristos {
113440a403fSchristos   Smode = 1;
114440a403fSchristos   Hmode = 1;
115440a403fSchristos   SXmode = 1;
116440a403fSchristos   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300sx))
117440a403fSchristos     as_warn (_("could not set architecture and machine"));
118440a403fSchristos }
119440a403fSchristos 
120440a403fSchristos static void
h8300sxnmode(int arg ATTRIBUTE_UNUSED)121440a403fSchristos h8300sxnmode (int arg ATTRIBUTE_UNUSED)
122440a403fSchristos {
123440a403fSchristos   Smode = 1;
124440a403fSchristos   Hmode = 1;
125440a403fSchristos   SXmode = 1;
126440a403fSchristos   Nmode = 1;
127440a403fSchristos   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, bfd_mach_h8300sxn))
128440a403fSchristos     as_warn (_("could not set architecture and machine"));
129440a403fSchristos }
130440a403fSchristos 
131440a403fSchristos static void
sbranch(int size)132440a403fSchristos sbranch (int size)
133440a403fSchristos {
134440a403fSchristos   bsize = size;
135440a403fSchristos }
136440a403fSchristos 
137440a403fSchristos static void
pint(int arg ATTRIBUTE_UNUSED)138440a403fSchristos pint (int arg ATTRIBUTE_UNUSED)
139440a403fSchristos {
140440a403fSchristos   cons (Hmode ? 4 : 2);
141440a403fSchristos }
142440a403fSchristos 
143440a403fSchristos /* Like obj_elf_section, but issues a warning for new
144440a403fSchristos    sections which do not have an attribute specification.  */
145440a403fSchristos 
146440a403fSchristos static void
h8300_elf_section(int push)147440a403fSchristos h8300_elf_section (int push)
148440a403fSchristos {
149440a403fSchristos   static const char * known_data_sections [] = { ".rodata", ".tdata", ".tbss" };
150440a403fSchristos   static const char * known_data_prefixes [] = { ".debug", ".zdebug", ".gnu.warning" };
151440a403fSchristos   char * saved_ilp = input_line_pointer;
152440a403fSchristos   const char * name;
153440a403fSchristos 
154440a403fSchristos   name = obj_elf_section_name ();
155440a403fSchristos   if (name == NULL)
156440a403fSchristos     return;
157440a403fSchristos 
158440a403fSchristos   if (* input_line_pointer != ','
159440a403fSchristos       && bfd_get_section_by_name (stdoutput, name) == NULL)
160440a403fSchristos     {
161440a403fSchristos       signed int i;
162440a403fSchristos 
163440a403fSchristos       /* Ignore this warning for well known data sections.  */
164440a403fSchristos       for (i = ARRAY_SIZE (known_data_sections); i--;)
165440a403fSchristos 	if (strcmp (name, known_data_sections[i]) == 0)
166440a403fSchristos 	  break;
167440a403fSchristos 
168440a403fSchristos       if (i < 0)
169440a403fSchristos 	for (i = ARRAY_SIZE (known_data_prefixes); i--;)
170440a403fSchristos 	  if (strncmp (name, known_data_prefixes[i],
171440a403fSchristos 		       strlen (known_data_prefixes[i])) == 0)
172440a403fSchristos 	    break;
173440a403fSchristos 
174440a403fSchristos       if (i < 0)
175440a403fSchristos 	as_warn (_("new section '%s' defined without attributes - this might cause problems"), name);
176440a403fSchristos     }
177440a403fSchristos 
178440a403fSchristos   /* FIXME: We ought to free the memory allocated by obj_elf_section_name()
179440a403fSchristos      for 'name', but we do not know if it was taken from the obstack, via
180440a403fSchristos      demand_copy_C_string(), or xmalloc()ed.  */
181440a403fSchristos   input_line_pointer = saved_ilp;
182440a403fSchristos   obj_elf_section (push);
183440a403fSchristos }
184440a403fSchristos 
185440a403fSchristos /* This table describes all the machine specific pseudo-ops the assembler
186440a403fSchristos    has to support.  The fields are:
187440a403fSchristos    pseudo-op name without dot
188440a403fSchristos    function to call to execute this pseudo-op
189440a403fSchristos    Integer arg to pass to the function.  */
190440a403fSchristos 
191440a403fSchristos const pseudo_typeS md_pseudo_table[] =
192440a403fSchristos {
193440a403fSchristos   {"h8300h",  h8300hmode,  0},
194440a403fSchristos   {"h8300hn", h8300hnmode, 0},
195440a403fSchristos   {"h8300s",  h8300smode,  0},
196440a403fSchristos   {"h8300sn", h8300snmode, 0},
197440a403fSchristos   {"h8300sx", h8300sxmode, 0},
198440a403fSchristos   {"h8300sxn", h8300sxnmode, 0},
199440a403fSchristos   {"sbranch", sbranch, L_8},
200440a403fSchristos   {"lbranch", sbranch, L_16},
201440a403fSchristos 
202440a403fSchristos   {"int", pint, 0},
203440a403fSchristos   {"data.b", cons, 1},
204440a403fSchristos   {"data.w", cons, 2},
205440a403fSchristos   {"data.l", cons, 4},
206440a403fSchristos   {"form", listing_psize, 0},
207440a403fSchristos   {"heading", listing_title, 0},
208440a403fSchristos   {"import",  s_ignore, 0},
209440a403fSchristos   {"page",    listing_eject, 0},
210440a403fSchristos   {"program", s_ignore, 0},
211440a403fSchristos 
212440a403fSchristos   {"section",   h8300_elf_section, 0},
213440a403fSchristos   {"section.s", h8300_elf_section, 0},
214440a403fSchristos   {"sect",      h8300_elf_section, 0},
215440a403fSchristos   {"sect.s",    h8300_elf_section, 0},
216440a403fSchristos 
217440a403fSchristos   {0, 0, 0}
218440a403fSchristos };
219440a403fSchristos 
220440a403fSchristos const char EXP_CHARS[] = "eE";
221440a403fSchristos 
222440a403fSchristos /* Chars that mean this number is a floating point constant
223440a403fSchristos    As in 0f12.456
224440a403fSchristos    or    0d1.2345e12.  */
225440a403fSchristos const char FLT_CHARS[] = "rRsSfFdDxXpP";
226440a403fSchristos 
227440a403fSchristos static struct hash_control *opcode_hash_control;	/* Opcode mnemonics.  */
228440a403fSchristos 
229440a403fSchristos /* This function is called once, at assembler startup time.  This
230440a403fSchristos    should set up all the tables, etc. that the MD part of the assembler
231440a403fSchristos    needs.  */
232440a403fSchristos 
233440a403fSchristos void
md_begin(void)234440a403fSchristos md_begin (void)
235440a403fSchristos {
236440a403fSchristos   unsigned int nopcodes;
237440a403fSchristos   struct h8_opcode *p, *p1;
238440a403fSchristos   struct h8_instruction *pi;
239440a403fSchristos   char prev_buffer[100];
240440a403fSchristos   int idx = 0;
241440a403fSchristos 
242440a403fSchristos   if (!bfd_set_arch_mach (stdoutput, bfd_arch_h8300, default_mach))
243440a403fSchristos     as_warn (_("could not set architecture and machine"));
244440a403fSchristos 
245440a403fSchristos   opcode_hash_control = hash_new ();
246440a403fSchristos   prev_buffer[0] = 0;
247440a403fSchristos 
248440a403fSchristos   nopcodes = sizeof (h8_opcodes) / sizeof (struct h8_opcode);
249440a403fSchristos 
250440a403fSchristos   h8_instructions = XNEWVEC (struct h8_instruction, nopcodes);
251440a403fSchristos 
252440a403fSchristos   pi = h8_instructions;
253440a403fSchristos   p1 = h8_opcodes;
254440a403fSchristos   /* We do a minimum amount of sorting on the opcode table; this is to
255440a403fSchristos      make it easy to describe the mova instructions without unnecessary
256440a403fSchristos      code duplication.
257440a403fSchristos      Sorting only takes place inside blocks of instructions of the form
258440a403fSchristos      X/Y, so for example mova/b, mova/w and mova/l can be intermixed.  */
259440a403fSchristos   while (p1)
260440a403fSchristos     {
261440a403fSchristos       struct h8_opcode *first_skipped = 0;
262440a403fSchristos       int len, cmplen = 0;
263440a403fSchristos       const char *src = p1->name;
264440a403fSchristos       char *dst, *buffer;
265440a403fSchristos 
266440a403fSchristos       if (p1->name == 0)
267440a403fSchristos 	break;
268440a403fSchristos       /* Strip off any . part when inserting the opcode and only enter
269440a403fSchristos 	 unique codes into the hash table.  */
270440a403fSchristos       dst = buffer = XNEWVEC (char, strlen (src) + 1);
271440a403fSchristos       while (*src)
272440a403fSchristos 	{
273440a403fSchristos 	  if (*src == '.')
274440a403fSchristos 	    {
275440a403fSchristos 	      src++;
276440a403fSchristos 	      break;
277440a403fSchristos 	    }
278440a403fSchristos 	  if (*src == '/')
279440a403fSchristos 	    cmplen = src - p1->name + 1;
280440a403fSchristos 	  *dst++ = *src++;
281440a403fSchristos 	}
282440a403fSchristos       *dst = 0;
283440a403fSchristos       len = dst - buffer;
284440a403fSchristos       if (cmplen == 0)
285440a403fSchristos 	cmplen = len;
286440a403fSchristos       hash_insert (opcode_hash_control, buffer, (char *) pi);
287440a403fSchristos       strcpy (prev_buffer, buffer);
288440a403fSchristos       idx++;
289440a403fSchristos 
290440a403fSchristos       for (p = p1; p->name; p++)
291440a403fSchristos 	{
292440a403fSchristos 	  /* A negative TIME is used to indicate that we've added this opcode
293440a403fSchristos 	     already.  */
294440a403fSchristos 	  if (p->time == -1)
295440a403fSchristos 	    continue;
296440a403fSchristos 	  if (strncmp (p->name, buffer, cmplen) != 0
297440a403fSchristos 	      || (p->name[cmplen] != '\0' && p->name[cmplen] != '.'
298440a403fSchristos 		  && p->name[cmplen - 1] != '/'))
299440a403fSchristos 	    {
300440a403fSchristos 	      if (first_skipped == 0)
301440a403fSchristos 		first_skipped = p;
302440a403fSchristos 	      break;
303440a403fSchristos 	    }
304440a403fSchristos 	  if (strncmp (p->name, buffer, len) != 0)
305440a403fSchristos 	    {
306440a403fSchristos 	      if (first_skipped == 0)
307440a403fSchristos 		first_skipped = p;
308440a403fSchristos 	      continue;
309440a403fSchristos 	    }
310440a403fSchristos 
311440a403fSchristos 	  p->time = -1;
312440a403fSchristos 	  pi->size = p->name[len] == '.' ? p->name[len + 1] : 0;
313440a403fSchristos 	  pi->idx = idx;
314440a403fSchristos 
315440a403fSchristos 	  /* Find the number of operands.  */
316440a403fSchristos 	  pi->noperands = 0;
317440a403fSchristos 	  while (pi->noperands < 3 && p->args.nib[pi->noperands] != (op_type) E)
318440a403fSchristos 	    pi->noperands++;
319440a403fSchristos 
320440a403fSchristos 	  /* Find the length of the opcode in bytes.  */
321440a403fSchristos 	  pi->length = 0;
322440a403fSchristos 	  while (p->data.nib[pi->length * 2] != (op_type) E)
323440a403fSchristos 	    pi->length++;
324440a403fSchristos 
325440a403fSchristos 	  pi->opcode = p;
326440a403fSchristos 	  pi++;
327440a403fSchristos 	}
328440a403fSchristos       p1 = first_skipped;
329440a403fSchristos     }
330440a403fSchristos 
331440a403fSchristos   /* Add entry for the NULL vector terminator.  */
332440a403fSchristos   pi->length = 0;
333440a403fSchristos   pi->noperands = 0;
334440a403fSchristos   pi->idx = 0;
335440a403fSchristos   pi->size = 0;
336440a403fSchristos   pi->opcode = 0;
337440a403fSchristos 
338440a403fSchristos   linkrelax = 1;
339440a403fSchristos }
340440a403fSchristos 
341440a403fSchristos struct h8_op
342440a403fSchristos {
343440a403fSchristos   op_type mode;
344440a403fSchristos   unsigned reg;
345440a403fSchristos   expressionS exp;
346440a403fSchristos };
347440a403fSchristos 
348440a403fSchristos static void clever_message (const struct h8_instruction *, struct h8_op *);
349440a403fSchristos static void fix_operand_size (struct h8_op *, int);
350440a403fSchristos static void build_bytes (const struct h8_instruction *, struct h8_op *);
351440a403fSchristos static void do_a_fix_imm (int, int, struct h8_op *, int, const struct h8_instruction *);
352440a403fSchristos static void check_operand (struct h8_op *, unsigned int, const char *);
353440a403fSchristos static const struct h8_instruction * get_specific (const struct h8_instruction *, struct h8_op *, int) ;
354440a403fSchristos static char *get_operands (unsigned, char *, struct h8_op *);
355440a403fSchristos static void get_operand (char **, struct h8_op *, int);
356440a403fSchristos static int parse_reg (char *, op_type *, unsigned *, int);
357440a403fSchristos static char *skip_colonthing (char *, int *);
358440a403fSchristos static char *parse_exp (char *, struct h8_op *);
359440a403fSchristos 
360440a403fSchristos static int constant_fits_size_p (struct h8_op *, int, int);
361440a403fSchristos 
362440a403fSchristos /*
363440a403fSchristos   parse operands
364440a403fSchristos   WREG r0,r1,r2,r3,r4,r5,r6,r7,fp,sp
365440a403fSchristos   r0l,r0h,..r7l,r7h
366440a403fSchristos   @WREG
367440a403fSchristos   @WREG+
368440a403fSchristos   @-WREG
369440a403fSchristos   #const
370440a403fSchristos   ccr
371440a403fSchristos */
372440a403fSchristos 
373440a403fSchristos /* Try to parse a reg name.  Return the number of chars consumed.  */
374440a403fSchristos 
375440a403fSchristos static int
parse_reg(char * src,op_type * mode,unsigned int * reg,int direction)376440a403fSchristos parse_reg (char *src, op_type *mode, unsigned int *reg, int direction)
377440a403fSchristos {
378440a403fSchristos   char *end;
379440a403fSchristos   int len;
380440a403fSchristos 
381440a403fSchristos   /* Cribbed from get_symbol_name.  */
382440a403fSchristos   if (!is_name_beginner (*src) || *src == '\001')
383440a403fSchristos     return 0;
384440a403fSchristos   end = src + 1;
385440a403fSchristos   while ((is_part_of_name (*end) && *end != '.') || *end == '\001')
386440a403fSchristos     end++;
387440a403fSchristos   len = end - src;
388440a403fSchristos 
389440a403fSchristos   if (len == 2 && TOLOWER (src[0]) == 's' && TOLOWER (src[1]) == 'p')
390440a403fSchristos     {
391440a403fSchristos       *mode = PSIZE | REG | direction;
392440a403fSchristos       *reg = 7;
393440a403fSchristos       return len;
394440a403fSchristos     }
395440a403fSchristos   if (len == 3 &&
396440a403fSchristos       TOLOWER (src[0]) == 'c' &&
397440a403fSchristos       TOLOWER (src[1]) == 'c' &&
398440a403fSchristos       TOLOWER (src[2]) == 'r')
399440a403fSchristos     {
400440a403fSchristos       *mode = CCR;
401440a403fSchristos       *reg = 0;
402440a403fSchristos       return len;
403440a403fSchristos     }
404440a403fSchristos   if (len == 3 &&
405440a403fSchristos       TOLOWER (src[0]) == 'e' &&
406440a403fSchristos       TOLOWER (src[1]) == 'x' &&
407440a403fSchristos       TOLOWER (src[2]) == 'r')
408440a403fSchristos     {
409440a403fSchristos       *mode = EXR;
410440a403fSchristos       *reg = 1;
411440a403fSchristos       return len;
412440a403fSchristos     }
413440a403fSchristos   if (len == 3 &&
414440a403fSchristos       TOLOWER (src[0]) == 'v' &&
415440a403fSchristos       TOLOWER (src[1]) == 'b' &&
416440a403fSchristos       TOLOWER (src[2]) == 'r')
417440a403fSchristos     {
418440a403fSchristos       *mode = VBR;
419440a403fSchristos       *reg = 6;
420440a403fSchristos       return len;
421440a403fSchristos     }
422440a403fSchristos   if (len == 3 &&
423440a403fSchristos       TOLOWER (src[0]) == 's' &&
424440a403fSchristos       TOLOWER (src[1]) == 'b' &&
425440a403fSchristos       TOLOWER (src[2]) == 'r')
426440a403fSchristos     {
427440a403fSchristos       *mode = SBR;
428440a403fSchristos       *reg = 7;
429440a403fSchristos       return len;
430440a403fSchristos     }
431440a403fSchristos   if (len == 2 && TOLOWER (src[0]) == 'f' && TOLOWER (src[1]) == 'p')
432440a403fSchristos     {
433440a403fSchristos       *mode = PSIZE | REG | direction;
434440a403fSchristos       *reg = 6;
435440a403fSchristos       return len;
436440a403fSchristos     }
437440a403fSchristos   if (len == 3 && TOLOWER (src[0]) == 'e' && TOLOWER (src[1]) == 'r' &&
438440a403fSchristos       src[2] >= '0' && src[2] <= '7')
439440a403fSchristos     {
440440a403fSchristos       *mode = L_32 | REG | direction;
441440a403fSchristos       *reg = src[2] - '0';
442440a403fSchristos       if (!Hmode)
443440a403fSchristos 	as_warn (_("Reg not valid for H8/300"));
444440a403fSchristos       return len;
445440a403fSchristos     }
446440a403fSchristos   if (len == 2 && TOLOWER (src[0]) == 'e' && src[1] >= '0' && src[1] <= '7')
447440a403fSchristos     {
448440a403fSchristos       *mode = L_16 | REG | direction;
449440a403fSchristos       *reg = src[1] - '0' + 8;
450440a403fSchristos       if (!Hmode)
451440a403fSchristos 	as_warn (_("Reg not valid for H8/300"));
452440a403fSchristos       return len;
453440a403fSchristos     }
454440a403fSchristos 
455440a403fSchristos   if (TOLOWER (src[0]) == 'r')
456440a403fSchristos     {
457440a403fSchristos       if (src[1] >= '0' && src[1] <= '7')
458440a403fSchristos 	{
459440a403fSchristos 	  if (len == 3 && TOLOWER (src[2]) == 'l')
460440a403fSchristos 	    {
461440a403fSchristos 	      *mode = L_8 | REG | direction;
462440a403fSchristos 	      *reg = (src[1] - '0') + 8;
463440a403fSchristos 	      return len;
464440a403fSchristos 	    }
465440a403fSchristos 	  if (len == 3 && TOLOWER (src[2]) == 'h')
466440a403fSchristos 	    {
467440a403fSchristos 	      *mode = L_8 | REG | direction;
468440a403fSchristos 	      *reg = (src[1] - '0');
469440a403fSchristos 	      return len;
470440a403fSchristos 	    }
471440a403fSchristos 	  if (len == 2)
472440a403fSchristos 	    {
473440a403fSchristos 	      *mode = L_16 | REG | direction;
474440a403fSchristos 	      *reg = (src[1] - '0');
475440a403fSchristos 	      return len;
476440a403fSchristos 	    }
477440a403fSchristos 	}
478440a403fSchristos     }
479440a403fSchristos 
480440a403fSchristos   return 0;
481440a403fSchristos }
482440a403fSchristos 
483440a403fSchristos 
484440a403fSchristos /* Parse an immediate or address-related constant and store it in OP.
485440a403fSchristos    If the user also specifies the operand's size, store that size
486440a403fSchristos    in OP->MODE, otherwise leave it for later code to decide.  */
487440a403fSchristos 
488440a403fSchristos static char *
parse_exp(char * src,struct h8_op * op)489440a403fSchristos parse_exp (char *src, struct h8_op *op)
490440a403fSchristos {
491440a403fSchristos   char *save;
492440a403fSchristos 
493440a403fSchristos   save = input_line_pointer;
494440a403fSchristos   input_line_pointer = src;
495440a403fSchristos   expression (&op->exp);
496440a403fSchristos   if (op->exp.X_op == O_absent)
497440a403fSchristos     as_bad (_("missing operand"));
498440a403fSchristos   src = input_line_pointer;
499440a403fSchristos   input_line_pointer = save;
500440a403fSchristos 
501440a403fSchristos   return skip_colonthing (src, &op->mode);
502440a403fSchristos }
503440a403fSchristos 
504440a403fSchristos 
505440a403fSchristos /* If SRC starts with an explicit operand size, skip it and store the size
506440a403fSchristos    in *MODE.  Leave *MODE unchanged otherwise.  */
507440a403fSchristos 
508440a403fSchristos static char *
skip_colonthing(char * src,int * mode)509440a403fSchristos skip_colonthing (char *src, int *mode)
510440a403fSchristos {
511440a403fSchristos   if (*src == ':')
512440a403fSchristos     {
513440a403fSchristos       src++;
514440a403fSchristos       *mode &= ~SIZE;
515440a403fSchristos       if (src[0] == '8' && !ISDIGIT (src[1]))
516440a403fSchristos 	*mode |= L_8;
517440a403fSchristos       else if (src[0] == '2' && !ISDIGIT (src[1]))
518440a403fSchristos 	*mode |= L_2;
519440a403fSchristos       else if (src[0] == '3' && !ISDIGIT (src[1]))
520440a403fSchristos 	*mode |= L_3;
521440a403fSchristos       else if (src[0] == '4' && !ISDIGIT (src[1]))
522440a403fSchristos 	*mode |= L_4;
523440a403fSchristos       else if (src[0] == '5' && !ISDIGIT (src[1]))
524440a403fSchristos 	*mode |= L_5;
525440a403fSchristos       else if (src[0] == '2' && src[1] == '4' && !ISDIGIT (src[2]))
526440a403fSchristos 	*mode |= L_24;
527440a403fSchristos       else if (src[0] == '3' && src[1] == '2' && !ISDIGIT (src[2]))
528440a403fSchristos 	*mode |= L_32;
529440a403fSchristos       else if (src[0] == '1' && src[1] == '6' && !ISDIGIT (src[2]))
530440a403fSchristos 	*mode |= L_16;
531440a403fSchristos       else
532440a403fSchristos 	as_bad (_("invalid operand size requested"));
533440a403fSchristos 
534440a403fSchristos       while (ISDIGIT (*src))
535440a403fSchristos 	src++;
536440a403fSchristos     }
537440a403fSchristos   return src;
538440a403fSchristos }
539440a403fSchristos 
540440a403fSchristos /* The many forms of operand:
541440a403fSchristos 
542440a403fSchristos    Rn			Register direct
543440a403fSchristos    @Rn			Register indirect
544440a403fSchristos    @(exp[:16], Rn)	Register indirect with displacement
545440a403fSchristos    @Rn+
546440a403fSchristos    @-Rn
547440a403fSchristos    @aa:8		absolute 8 bit
548440a403fSchristos    @aa:16		absolute 16 bit
549440a403fSchristos    @aa			absolute 16 bit
550440a403fSchristos 
551440a403fSchristos    #xx[:size]		immediate data
552440a403fSchristos    @(exp:[8], pc)	pc rel
553440a403fSchristos    @@aa[:8]		memory indirect.  */
554440a403fSchristos 
555440a403fSchristos static int
constant_fits_width_p(struct h8_op * operand,offsetT width)556440a403fSchristos constant_fits_width_p (struct h8_op *operand, offsetT width)
557440a403fSchristos {
558440a403fSchristos   offsetT num;
559440a403fSchristos 
560440a403fSchristos   num = ((operand->exp.X_add_number & 0xffffffff) ^ 0x80000000) - 0x80000000;
561440a403fSchristos   return (num & ~width) == 0 || (num | width) == ~0;
562440a403fSchristos }
563440a403fSchristos 
564440a403fSchristos static int
constant_fits_size_p(struct h8_op * operand,int size,int no_symbols)565440a403fSchristos constant_fits_size_p (struct h8_op *operand, int size, int no_symbols)
566440a403fSchristos {
567440a403fSchristos   offsetT num;
568440a403fSchristos 
569440a403fSchristos   if (no_symbols
570440a403fSchristos       && (operand->exp.X_add_symbol != 0 || operand->exp.X_op_symbol != 0))
571440a403fSchristos     return 0;
572440a403fSchristos   num = operand->exp.X_add_number & 0xffffffff;
573440a403fSchristos   switch (size)
574440a403fSchristos     {
575440a403fSchristos     case L_2:
576440a403fSchristos       return (num & ~3) == 0;
577440a403fSchristos     case L_3:
578440a403fSchristos       return (num & ~7) == 0;
579440a403fSchristos     case L_3NZ:
580440a403fSchristos       return num >= 1 && num < 8;
581440a403fSchristos     case L_4:
582440a403fSchristos       return (num & ~15) == 0;
583440a403fSchristos     case L_5:
584440a403fSchristos       return num >= 1 && num < 32;
585440a403fSchristos     case L_8:
586440a403fSchristos       num = (num ^ 0x80000000) - 0x80000000;
587440a403fSchristos       return (num & ~0xFF) == 0 || (num | 0x7F) == ~0;
588440a403fSchristos     case L_8U:
589440a403fSchristos       return (num & ~0xFF) == 0;
590440a403fSchristos     case L_16:
591440a403fSchristos       num = (num ^ 0x80000000) - 0x80000000;
592440a403fSchristos       return (num & ~0xFFFF) == 0 || (num | 0x7FFF) == ~0;
593440a403fSchristos     case L_16U:
594440a403fSchristos       return (num & ~0xFFFF) == 0;
595440a403fSchristos     case L_32:
596440a403fSchristos       return 1;
597440a403fSchristos     default:
598440a403fSchristos       abort ();
599440a403fSchristos     }
600440a403fSchristos }
601440a403fSchristos 
602440a403fSchristos static void
get_operand(char ** ptr,struct h8_op * op,int direction)603440a403fSchristos get_operand (char **ptr, struct h8_op *op, int direction)
604440a403fSchristos {
605440a403fSchristos   char *src = *ptr;
606440a403fSchristos   op_type mode;
607440a403fSchristos   unsigned int num;
608440a403fSchristos   unsigned int len;
609440a403fSchristos 
610440a403fSchristos   op->mode = 0;
611440a403fSchristos 
612440a403fSchristos   /* Check for '(' and ')' for instructions ldm and stm.  */
613440a403fSchristos   if (src[0] == '(' && src[8] == ')')
614440a403fSchristos     ++ src;
615440a403fSchristos 
616440a403fSchristos   /* Gross.  Gross.  ldm and stm have a format not easily handled
617440a403fSchristos      by get_operand.  We deal with it explicitly here.  */
618440a403fSchristos   if (TOLOWER (src[0]) == 'e' && TOLOWER (src[1]) == 'r' &&
619440a403fSchristos       ISDIGIT (src[2]) && src[3] == '-' &&
620440a403fSchristos       TOLOWER (src[4]) == 'e' && TOLOWER (src[5]) == 'r' && ISDIGIT (src[6]))
621440a403fSchristos     {
622440a403fSchristos       int low, high;
623440a403fSchristos 
624440a403fSchristos       low = src[2] - '0';
625440a403fSchristos       high = src[6] - '0';
626440a403fSchristos 
627440a403fSchristos        /* Check register pair's validity as per tech note TN-H8*-193A/E
628440a403fSchristos 	  from Renesas for H8S and H8SX hardware manual.  */
629440a403fSchristos       if (   !(low == 0 && (high == 1 || high == 2 || high == 3))
630440a403fSchristos           && !(low == 1 && (high == 2 || high == 3 || high == 4) && SXmode)
631440a403fSchristos           && !(low == 2 && (high == 3 || ((high == 4 || high == 5) && SXmode)))
632440a403fSchristos           && !(low == 3 && (high == 4 || high == 5 || high == 6) && SXmode)
633440a403fSchristos           && !(low == 4 && (high == 5 || high == 6))
634440a403fSchristos           && !(low == 4 && high == 7 && SXmode)
635440a403fSchristos           && !(low == 5 && (high == 6 || high == 7) && SXmode)
636440a403fSchristos           && !(low == 6 && high == 7 && SXmode))
637440a403fSchristos 	as_bad (_("Invalid register list for ldm/stm\n"));
638440a403fSchristos 
639440a403fSchristos       /* Even sicker.  We encode two registers into op->reg.  One
640440a403fSchristos 	 for the low register to save, the other for the high
641440a403fSchristos 	 register to save;  we also set the high bit in op->reg
642440a403fSchristos 	 so we know this is "very special".  */
643440a403fSchristos       op->reg = 0x80000000 | (high << 8) | low;
644440a403fSchristos       op->mode = REG;
645440a403fSchristos       if (src[7] == ')')
646440a403fSchristos 	*ptr = src + 8;
647440a403fSchristos       else
648440a403fSchristos 	*ptr = src + 7;
649440a403fSchristos       return;
650440a403fSchristos     }
651440a403fSchristos 
652440a403fSchristos   len = parse_reg (src, &op->mode, &op->reg, direction);
653440a403fSchristos   if (len)
654440a403fSchristos     {
655440a403fSchristos       src += len;
656440a403fSchristos       if (*src == '.')
657440a403fSchristos 	{
658440a403fSchristos 	  int size = op->mode & SIZE;
659440a403fSchristos 	  switch (src[1])
660440a403fSchristos 	    {
661440a403fSchristos 	    case 'l': case 'L':
662440a403fSchristos 	      if (size != L_32)
663440a403fSchristos 		as_warn (_("mismatch between register and suffix"));
664440a403fSchristos 	      op->mode = (op->mode & ~MODE) | LOWREG;
665440a403fSchristos 	      break;
666440a403fSchristos 	    case 'w': case 'W':
667440a403fSchristos 	      if (size != L_32 && size != L_16)
668440a403fSchristos 		as_warn (_("mismatch between register and suffix"));
669440a403fSchristos 	      op->mode = (op->mode & ~MODE) | LOWREG;
670440a403fSchristos 	      op->mode = (op->mode & ~SIZE) | L_16;
671440a403fSchristos 	      break;
672440a403fSchristos 	    case 'b': case 'B':
673440a403fSchristos 	      op->mode = (op->mode & ~MODE) | LOWREG;
674440a403fSchristos 	      if (size != L_32 && size != L_8)
675440a403fSchristos 		as_warn (_("mismatch between register and suffix"));
676440a403fSchristos 	      op->mode = (op->mode & ~MODE) | LOWREG;
677440a403fSchristos 	      op->mode = (op->mode & ~SIZE) | L_8;
678440a403fSchristos 	      break;
679440a403fSchristos 	    default:
680440a403fSchristos 	      as_warn (_("invalid suffix after register."));
681440a403fSchristos 	      break;
682440a403fSchristos 	    }
683440a403fSchristos 	  src += 2;
684440a403fSchristos 	}
685440a403fSchristos       *ptr = src;
686440a403fSchristos       return;
687440a403fSchristos     }
688440a403fSchristos 
689440a403fSchristos   if (*src == '@')
690440a403fSchristos     {
691440a403fSchristos       src++;
692440a403fSchristos       if (*src == '@')
693440a403fSchristos 	{
694440a403fSchristos 	  *ptr = parse_exp (src + 1, op);
695440a403fSchristos 	  if (op->exp.X_add_number >= 0x100)
696440a403fSchristos 	    {
697440a403fSchristos 	      int divisor = 1;
698440a403fSchristos 
699440a403fSchristos 	      op->mode = VECIND;
700440a403fSchristos 	      /* FIXME : 2?  or 4?  */
701440a403fSchristos 	      if (op->exp.X_add_number >= 0x400)
702440a403fSchristos 		as_bad (_("address too high for vector table jmp/jsr"));
703440a403fSchristos 	      else if (op->exp.X_add_number >= 0x200)
704440a403fSchristos 		divisor = 4;
705440a403fSchristos 	      else
706440a403fSchristos 		divisor = 2;
707440a403fSchristos 
708440a403fSchristos 	      op->exp.X_add_number = op->exp.X_add_number / divisor - 0x80;
709440a403fSchristos 	    }
710440a403fSchristos 	  else
711440a403fSchristos 	    op->mode = MEMIND;
712440a403fSchristos 	  return;
713440a403fSchristos 	}
714440a403fSchristos 
715440a403fSchristos       if (*src == '-' || *src == '+')
716440a403fSchristos 	{
717440a403fSchristos 	  len = parse_reg (src + 1, &mode, &num, direction);
718440a403fSchristos 	  if (len == 0)
719440a403fSchristos 	    {
720440a403fSchristos 	      /* Oops, not a reg after all, must be ordinary exp.  */
721440a403fSchristos 	      op->mode = ABS | direction;
722440a403fSchristos 	      *ptr = parse_exp (src, op);
723440a403fSchristos 	      return;
724440a403fSchristos 	    }
725440a403fSchristos 
726440a403fSchristos 	  if (((mode & SIZE) != PSIZE)
727440a403fSchristos 	      /* For Normal mode accept 16 bit and 32 bit pointer registers.  */
728440a403fSchristos 	      && (!Nmode || ((mode & SIZE) != L_32)))
729440a403fSchristos 	    as_bad (_("Wrong size pointer register for architecture."));
730440a403fSchristos 
731440a403fSchristos 	  op->mode = src[0] == '-' ? RDPREDEC : RDPREINC;
732440a403fSchristos 	  op->reg = num;
733440a403fSchristos 	  *ptr = src + 1 + len;
734440a403fSchristos 	  return;
735440a403fSchristos 	}
736440a403fSchristos       if (*src == '(')
737440a403fSchristos 	{
738440a403fSchristos 	  src++;
739440a403fSchristos 
740440a403fSchristos 	  /* See if this is @(ERn.x, PC).  */
741440a403fSchristos 	  len = parse_reg (src, &mode, &op->reg, direction);
742440a403fSchristos 	  if (len != 0 && (mode & MODE) == REG && src[len] == '.')
743440a403fSchristos 	    {
744440a403fSchristos 	      switch (TOLOWER (src[len + 1]))
745440a403fSchristos 		{
746440a403fSchristos 		case 'b':
747440a403fSchristos 		  mode = PCIDXB | direction;
748440a403fSchristos 		  break;
749440a403fSchristos 		case 'w':
750440a403fSchristos 		  mode = PCIDXW | direction;
751440a403fSchristos 		  break;
752440a403fSchristos 		case 'l':
753440a403fSchristos 		  mode = PCIDXL | direction;
754440a403fSchristos 		  break;
755440a403fSchristos 		default:
756440a403fSchristos 		  mode = 0;
757440a403fSchristos 		  break;
758440a403fSchristos 		}
759440a403fSchristos 	      if (mode
760440a403fSchristos 		  && src[len + 2] == ','
761440a403fSchristos 		  && TOLOWER (src[len + 3]) != 'p'
762440a403fSchristos 		  && TOLOWER (src[len + 4]) != 'c'
763440a403fSchristos 		  && src[len + 5] != ')')
764440a403fSchristos 		{
765440a403fSchristos 		  *ptr = src + len + 6;
766440a403fSchristos 		  op->mode |= mode;
767440a403fSchristos 		  return;
768440a403fSchristos 		}
769440a403fSchristos 	      /* Fall through into disp case - the grammar is somewhat
770440a403fSchristos 		 ambiguous, so we should try whether it's a DISP operand
771440a403fSchristos 		 after all ("ER3.L" might be a poorly named label...).  */
772440a403fSchristos 	    }
773440a403fSchristos 
774440a403fSchristos 	  /* Disp.  */
775440a403fSchristos 
776440a403fSchristos 	  /* Start off assuming a 16 bit offset.  */
777440a403fSchristos 
778440a403fSchristos 	  src = parse_exp (src, op);
779440a403fSchristos 	  if (*src == ')')
780440a403fSchristos 	    {
781440a403fSchristos 	      op->mode |= ABS | direction;
782440a403fSchristos 	      *ptr = src + 1;
783440a403fSchristos 	      return;
784440a403fSchristos 	    }
785440a403fSchristos 
786440a403fSchristos 	  if (*src != ',')
787440a403fSchristos 	    {
788440a403fSchristos 	      as_bad (_("expected @(exp, reg16)"));
789440a403fSchristos 	      return;
790440a403fSchristos 	    }
791440a403fSchristos 	  src++;
792440a403fSchristos 
793440a403fSchristos 	  len = parse_reg (src, &mode, &op->reg, direction);
794440a403fSchristos 	  if (len == 0 || (mode & MODE) != REG)
795440a403fSchristos 	    {
796440a403fSchristos 	      as_bad (_("expected @(exp, reg16)"));
797440a403fSchristos 	      return;
798440a403fSchristos 	    }
799440a403fSchristos 	  src += len;
800440a403fSchristos 	  if (src[0] == '.')
801440a403fSchristos 	    {
802440a403fSchristos 	      switch (TOLOWER (src[1]))
803440a403fSchristos 		{
804440a403fSchristos 		case 'b':
805440a403fSchristos 		  op->mode |= INDEXB | direction;
806440a403fSchristos 		  break;
807440a403fSchristos 		case 'w':
808440a403fSchristos 		  op->mode |= INDEXW | direction;
809440a403fSchristos 		  break;
810440a403fSchristos 		case 'l':
811440a403fSchristos 		  op->mode |= INDEXL | direction;
812440a403fSchristos 		  break;
813440a403fSchristos 		default:
814440a403fSchristos 		  as_bad (_("expected .L, .W or .B for register in indexed addressing mode"));
815440a403fSchristos 		}
816440a403fSchristos 	      src += 2;
817440a403fSchristos 	      op->reg &= 7;
818440a403fSchristos 	    }
819440a403fSchristos 	  else
820440a403fSchristos 	    op->mode |= DISP | direction;
821440a403fSchristos 	  src = skip_colonthing (src, &op->mode);
822440a403fSchristos 
823440a403fSchristos 	  if (*src != ')')
824440a403fSchristos 	    {
825440a403fSchristos 	      as_bad (_("expected @(exp, reg16)"));
826440a403fSchristos 	      return;
827440a403fSchristos 	    }
828440a403fSchristos 	  *ptr = src + 1;
829440a403fSchristos 	  return;
830440a403fSchristos 	}
831440a403fSchristos       len = parse_reg (src, &mode, &num, direction);
832440a403fSchristos 
833440a403fSchristos       if (len)
834440a403fSchristos 	{
835440a403fSchristos 	  src += len;
836440a403fSchristos 	  if (*src == '+' || *src == '-')
837440a403fSchristos 	    {
838440a403fSchristos 	      if (((mode & SIZE) != PSIZE)
839440a403fSchristos 		  /* For Normal mode accept 16 bit and 32 bit pointer registers.  */
840440a403fSchristos 		  && (!Nmode || ((mode & SIZE) != L_32)))
841440a403fSchristos 		as_bad (_("Wrong size pointer register for architecture."));
842440a403fSchristos 	      op->mode = *src == '+' ? RSPOSTINC : RSPOSTDEC;
843440a403fSchristos 	      op->reg = num;
844440a403fSchristos 	      src++;
845440a403fSchristos 	      *ptr = src;
846440a403fSchristos 	      return;
847440a403fSchristos 	    }
848440a403fSchristos 	  if (((mode & SIZE) != PSIZE)
849440a403fSchristos 	      /* For Normal mode accept 16 bit and 32 bit pointer registers.  */
850440a403fSchristos 	      && (!Nmode || ((mode & SIZE) != L_32)))
851440a403fSchristos 	    as_bad (_("Wrong size pointer register for architecture."));
852440a403fSchristos 
853440a403fSchristos 	  op->mode = direction | IND | PSIZE;
854440a403fSchristos 	  op->reg = num;
855440a403fSchristos 	  *ptr = src;
856440a403fSchristos 
857440a403fSchristos 	  return;
858440a403fSchristos 	}
859440a403fSchristos       else
860440a403fSchristos 	{
861440a403fSchristos 	  /* must be a symbol */
862440a403fSchristos 
863440a403fSchristos 	  op->mode = ABS | direction;
864440a403fSchristos 	  *ptr = parse_exp (src, op);
865440a403fSchristos 	  return;
866440a403fSchristos 	}
867440a403fSchristos     }
868440a403fSchristos 
869440a403fSchristos   if (*src == '#')
870440a403fSchristos     {
871440a403fSchristos       op->mode = IMM;
872440a403fSchristos       *ptr = parse_exp (src + 1, op);
873440a403fSchristos       return;
874440a403fSchristos     }
875440a403fSchristos   else if (strncmp (src, "mach", 4) == 0 ||
876440a403fSchristos 	   strncmp (src, "macl", 4) == 0 ||
877440a403fSchristos 	   strncmp (src, "MACH", 4) == 0 ||
878440a403fSchristos 	   strncmp (src, "MACL", 4) == 0)
879440a403fSchristos     {
880440a403fSchristos       op->reg = TOLOWER (src[3]) == 'l';
881440a403fSchristos       op->mode = MACREG;
882440a403fSchristos       *ptr = src + 4;
883440a403fSchristos       return;
884440a403fSchristos     }
885440a403fSchristos   else
886440a403fSchristos     {
887440a403fSchristos       op->mode = PCREL;
888440a403fSchristos       *ptr = parse_exp (src, op);
889440a403fSchristos     }
890440a403fSchristos }
891440a403fSchristos 
892440a403fSchristos static char *
get_operands(unsigned int noperands,char * op_end,struct h8_op * operand)893440a403fSchristos get_operands (unsigned int noperands, char *op_end, struct h8_op *operand)
894440a403fSchristos {
895440a403fSchristos   char *ptr = op_end;
896440a403fSchristos 
897440a403fSchristos   switch (noperands)
898440a403fSchristos     {
899440a403fSchristos     case 0:
900440a403fSchristos       break;
901440a403fSchristos 
902440a403fSchristos     case 1:
903440a403fSchristos       ptr++;
904440a403fSchristos       get_operand (&ptr, operand + 0, SRC);
905440a403fSchristos       if (*ptr == ',')
906440a403fSchristos 	{
907440a403fSchristos 	  ptr++;
908440a403fSchristos 	  get_operand (&ptr, operand + 1, DST);
909440a403fSchristos 	}
910440a403fSchristos       break;
911440a403fSchristos 
912440a403fSchristos     case 2:
913440a403fSchristos       ptr++;
914440a403fSchristos       get_operand (&ptr, operand + 0, SRC);
915440a403fSchristos       if (*ptr == ',')
916440a403fSchristos 	ptr++;
917440a403fSchristos       get_operand (&ptr, operand + 1, DST);
918440a403fSchristos       break;
919440a403fSchristos 
920440a403fSchristos     case 3:
921440a403fSchristos       ptr++;
922440a403fSchristos       get_operand (&ptr, operand + 0, SRC);
923440a403fSchristos       if (*ptr == ',')
924440a403fSchristos 	ptr++;
925440a403fSchristos       get_operand (&ptr, operand + 1, DST);
926440a403fSchristos       if (*ptr == ',')
927440a403fSchristos 	ptr++;
928440a403fSchristos       get_operand (&ptr, operand + 2, OP3);
929440a403fSchristos       break;
930440a403fSchristos 
931440a403fSchristos     default:
932440a403fSchristos       abort ();
933440a403fSchristos     }
934440a403fSchristos 
935440a403fSchristos   return ptr;
936440a403fSchristos }
937440a403fSchristos 
938440a403fSchristos /* MOVA has special requirements.  Rather than adding twice the amount of
939440a403fSchristos    addressing modes, we simply special case it a bit.  */
940440a403fSchristos static void
get_mova_operands(char * op_end,struct h8_op * operand)941440a403fSchristos get_mova_operands (char *op_end, struct h8_op *operand)
942440a403fSchristos {
943440a403fSchristos   char *ptr = op_end;
944440a403fSchristos 
945440a403fSchristos   if (ptr[1] != '@' || ptr[2] != '(')
946440a403fSchristos     goto error;
947440a403fSchristos   ptr += 3;
948440a403fSchristos   operand[0].mode = 0;
949440a403fSchristos   ptr = parse_exp (ptr, &operand[0]);
950440a403fSchristos 
951440a403fSchristos   if (*ptr !=',')
952440a403fSchristos     goto error;
953440a403fSchristos   ptr++;
954440a403fSchristos   get_operand (&ptr, operand + 1, DST);
955440a403fSchristos 
956440a403fSchristos   if (*ptr =='.')
957440a403fSchristos     {
958440a403fSchristos       ptr++;
959440a403fSchristos       switch (*ptr++)
960440a403fSchristos 	{
961440a403fSchristos 	case 'b': case 'B':
962440a403fSchristos 	  operand[0].mode = (operand[0].mode & ~MODE) | INDEXB;
963440a403fSchristos 	  break;
964440a403fSchristos 	case 'w': case 'W':
965440a403fSchristos 	  operand[0].mode = (operand[0].mode & ~MODE) | INDEXW;
966440a403fSchristos 	  break;
967440a403fSchristos 	case 'l': case 'L':
968440a403fSchristos 	  operand[0].mode = (operand[0].mode & ~MODE) | INDEXL;
969440a403fSchristos 	  break;
970440a403fSchristos 	default:
971440a403fSchristos 	  goto error;
972440a403fSchristos 	}
973440a403fSchristos     }
974440a403fSchristos   else if ((operand[1].mode & MODE) == LOWREG)
975440a403fSchristos     {
976440a403fSchristos       switch (operand[1].mode & SIZE)
977440a403fSchristos 	{
978440a403fSchristos 	case L_8:
979440a403fSchristos 	  operand[0].mode = (operand[0].mode & ~MODE) | INDEXB;
980440a403fSchristos 	  break;
981440a403fSchristos 	case L_16:
982440a403fSchristos 	  operand[0].mode = (operand[0].mode & ~MODE) | INDEXW;
983440a403fSchristos 	  break;
984440a403fSchristos 	case L_32:
985440a403fSchristos 	  operand[0].mode = (operand[0].mode & ~MODE) | INDEXL;
986440a403fSchristos 	  break;
987440a403fSchristos 	default:
988440a403fSchristos 	  goto error;
989440a403fSchristos 	}
990440a403fSchristos     }
991440a403fSchristos   else
992440a403fSchristos     goto error;
993440a403fSchristos 
994440a403fSchristos   if (*ptr++ != ')' || *ptr++ != ',')
995440a403fSchristos     goto error;
996440a403fSchristos   get_operand (&ptr, operand + 2, OP3);
997440a403fSchristos   /* See if we can use the short form of MOVA.  */
998440a403fSchristos   if (((operand[1].mode & MODE) == REG || (operand[1].mode & MODE) == LOWREG)
999440a403fSchristos       && (operand[2].mode & MODE) == REG
1000440a403fSchristos       && (operand[1].reg & 7) == (operand[2].reg & 7))
1001440a403fSchristos     {
1002440a403fSchristos       operand[1].mode = operand[2].mode = 0;
1003440a403fSchristos       operand[0].reg = operand[2].reg & 7;
1004440a403fSchristos     }
1005440a403fSchristos   return;
1006440a403fSchristos 
1007440a403fSchristos  error:
1008440a403fSchristos   as_bad (_("expected valid addressing mode for mova: \"@(disp, ea.sz),ERn\""));
1009440a403fSchristos }
1010440a403fSchristos 
1011440a403fSchristos static void
get_rtsl_operands(char * ptr,struct h8_op * operand)1012440a403fSchristos get_rtsl_operands (char *ptr, struct h8_op *operand)
1013440a403fSchristos {
1014440a403fSchristos   int mode, len, type = 0;
1015440a403fSchristos   unsigned int num, num2;
1016440a403fSchristos 
1017440a403fSchristos   ptr++;
1018440a403fSchristos   if (*ptr == '(')
1019440a403fSchristos     {
1020440a403fSchristos       ptr++;
1021440a403fSchristos       type = 1;
1022440a403fSchristos     }
1023440a403fSchristos   len = parse_reg (ptr, &mode, &num, SRC);
1024440a403fSchristos   if (len == 0 || (mode & MODE) != REG)
1025440a403fSchristos     {
1026440a403fSchristos       as_bad (_("expected register"));
1027440a403fSchristos       return;
1028440a403fSchristos     }
1029440a403fSchristos   ptr += len;
1030440a403fSchristos   if (*ptr == '-')
1031440a403fSchristos     {
1032440a403fSchristos       len = parse_reg (++ptr, &mode, &num2, SRC);
1033440a403fSchristos       if (len == 0 || (mode & MODE) != REG)
1034440a403fSchristos 	{
1035440a403fSchristos 	  as_bad (_("expected register"));
1036440a403fSchristos 	  return;
1037440a403fSchristos 	}
1038440a403fSchristos       ptr += len;
1039440a403fSchristos       /* CONST_xxx are used as placeholders in the opcode table.  */
1040440a403fSchristos       num = num2 - num;
1041440a403fSchristos       if (num > 3)
1042440a403fSchristos 	{
1043440a403fSchristos 	  as_bad (_("invalid register list"));
1044440a403fSchristos 	  return;
1045440a403fSchristos 	}
1046440a403fSchristos     }
1047440a403fSchristos   else
1048440a403fSchristos     num2 = num, num = 0;
1049440a403fSchristos   if (type == 1 && *ptr++ != ')')
1050440a403fSchristos     {
1051440a403fSchristos       as_bad (_("expected closing paren"));
1052440a403fSchristos       return;
1053440a403fSchristos     }
1054440a403fSchristos   operand[0].mode = RS32;
1055440a403fSchristos   operand[1].mode = RD32;
1056440a403fSchristos   operand[0].reg = num;
1057440a403fSchristos   operand[1].reg = num2;
1058440a403fSchristos }
1059440a403fSchristos 
1060440a403fSchristos /* Passed a pointer to a list of opcodes which use different
1061440a403fSchristos    addressing modes, return the opcode which matches the opcodes
1062440a403fSchristos    provided.  */
1063440a403fSchristos 
1064440a403fSchristos static const struct h8_instruction *
get_specific(const struct h8_instruction * instruction,struct h8_op * operands,int size)1065440a403fSchristos get_specific (const struct h8_instruction *instruction,
1066440a403fSchristos 	      struct h8_op *operands, int size)
1067440a403fSchristos {
1068440a403fSchristos   const struct h8_instruction *this_try = instruction;
1069440a403fSchristos   const struct h8_instruction *found_other = 0, *found_mismatched = 0;
1070440a403fSchristos   int found = 0;
1071440a403fSchristos   int this_index = instruction->idx;
1072440a403fSchristos   int noperands = 0;
1073440a403fSchristos 
1074440a403fSchristos   /* There's only one ldm/stm and it's easier to just
1075440a403fSchristos      get out quick for them.  */
1076440a403fSchristos   if (OP_KIND (instruction->opcode->how) == O_LDM
1077440a403fSchristos       || OP_KIND (instruction->opcode->how) == O_STM)
1078440a403fSchristos     return this_try;
1079440a403fSchristos 
1080440a403fSchristos   while (noperands < 3 && operands[noperands].mode != 0)
1081440a403fSchristos     noperands++;
1082440a403fSchristos 
1083440a403fSchristos   while (this_index == instruction->idx && !found)
1084440a403fSchristos     {
1085440a403fSchristos       int this_size;
1086440a403fSchristos 
1087440a403fSchristos       found = 1;
1088440a403fSchristos       this_try = instruction++;
1089440a403fSchristos       this_size = this_try->opcode->how & SN;
1090440a403fSchristos 
1091440a403fSchristos       if (this_try->noperands != noperands)
1092440a403fSchristos 	found = 0;
1093440a403fSchristos       else if (this_try->noperands > 0)
1094440a403fSchristos 	{
1095440a403fSchristos 	  int i;
1096440a403fSchristos 
1097440a403fSchristos 	  for (i = 0; i < this_try->noperands && found; i++)
1098440a403fSchristos 	    {
1099440a403fSchristos 	      op_type op = this_try->opcode->args.nib[i];
1100440a403fSchristos 	      int op_mode = op & MODE;
1101440a403fSchristos 	      int op_size = op & SIZE;
1102440a403fSchristos 	      int x = operands[i].mode;
1103440a403fSchristos 	      int x_mode = x & MODE;
1104440a403fSchristos 	      int x_size = x & SIZE;
1105440a403fSchristos 
1106440a403fSchristos 	      if (op_mode == LOWREG && (x_mode == REG || x_mode == LOWREG))
1107440a403fSchristos 		{
1108440a403fSchristos 		  if ((x_size == L_8 && (operands[i].reg & 8) == 0)
1109440a403fSchristos 		      || (x_size == L_16 && (operands[i].reg & 8) == 8))
1110440a403fSchristos 		    as_warn (_("can't use high part of register in operand %d"), i);
1111440a403fSchristos 
1112440a403fSchristos 		  if (x_size != op_size)
1113440a403fSchristos 		    found = 0;
1114440a403fSchristos 		}
1115440a403fSchristos 	      else if (op_mode == REG)
1116440a403fSchristos 		{
1117440a403fSchristos 		  if (x_mode == LOWREG)
1118440a403fSchristos 		    x_mode = REG;
1119440a403fSchristos 		  if (x_mode != REG)
1120440a403fSchristos 		    found = 0;
1121440a403fSchristos 
1122440a403fSchristos 		  if (x_size == L_P)
1123440a403fSchristos 		    x_size = (Hmode ? L_32 : L_16);
1124440a403fSchristos 		  if (op_size == L_P)
1125440a403fSchristos 		    op_size = (Hmode ? L_32 : L_16);
1126440a403fSchristos 
1127440a403fSchristos 		  /* The size of the reg is v important.  */
1128440a403fSchristos 		  if (op_size != x_size)
1129440a403fSchristos 		    found = 0;
1130440a403fSchristos 		}
1131440a403fSchristos 	      else if (op_mode & CTRL)	/* control register */
1132440a403fSchristos 		{
1133440a403fSchristos 		  if (!(x_mode & CTRL))
1134440a403fSchristos 		    found = 0;
1135440a403fSchristos 
1136440a403fSchristos 		  switch (x_mode)
1137440a403fSchristos 		    {
1138440a403fSchristos 		    case CCR:
1139440a403fSchristos 		      if (op_mode != CCR &&
1140440a403fSchristos 			  op_mode != CCR_EXR &&
1141440a403fSchristos 			  op_mode != CC_EX_VB_SB)
1142440a403fSchristos 			found = 0;
1143440a403fSchristos 		      break;
1144440a403fSchristos 		    case EXR:
1145440a403fSchristos 		      if (op_mode != EXR &&
1146440a403fSchristos 			  op_mode != CCR_EXR &&
1147440a403fSchristos 			  op_mode != CC_EX_VB_SB)
1148440a403fSchristos 			found = 0;
1149440a403fSchristos 		      break;
1150440a403fSchristos 		    case MACH:
1151440a403fSchristos 		      if (op_mode != MACH &&
1152440a403fSchristos 			  op_mode != MACREG)
1153440a403fSchristos 			found = 0;
1154440a403fSchristos 		      break;
1155440a403fSchristos 		    case MACL:
1156440a403fSchristos 		      if (op_mode != MACL &&
1157440a403fSchristos 			  op_mode != MACREG)
1158440a403fSchristos 			found = 0;
1159440a403fSchristos 		      break;
1160440a403fSchristos 		    case VBR:
1161440a403fSchristos 		      if (op_mode != VBR &&
1162440a403fSchristos 			  op_mode != VBR_SBR &&
1163440a403fSchristos 			  op_mode != CC_EX_VB_SB)
1164440a403fSchristos 			found = 0;
1165440a403fSchristos 		      break;
1166440a403fSchristos 		    case SBR:
1167440a403fSchristos 		      if (op_mode != SBR &&
1168440a403fSchristos 			  op_mode != VBR_SBR &&
1169440a403fSchristos 			  op_mode != CC_EX_VB_SB)
1170440a403fSchristos 			found = 0;
1171440a403fSchristos 		      break;
1172440a403fSchristos 		    }
1173440a403fSchristos 		}
1174440a403fSchristos 	      else if ((op & ABSJMP) && (x_mode == ABS || x_mode == PCREL))
1175440a403fSchristos 		{
1176440a403fSchristos 		  operands[i].mode &= ~MODE;
1177440a403fSchristos 		  operands[i].mode |= ABSJMP;
1178440a403fSchristos 		  /* But it may not be 24 bits long.  */
1179440a403fSchristos 		  if (x_mode == ABS && !Hmode)
1180440a403fSchristos 		    {
1181440a403fSchristos 		      operands[i].mode &= ~SIZE;
1182440a403fSchristos 		      operands[i].mode |= L_16;
1183440a403fSchristos 		    }
1184440a403fSchristos 		  if ((operands[i].mode & SIZE) == L_32
1185440a403fSchristos 		      && (op_mode & SIZE) != L_32)
1186440a403fSchristos 		   found = 0;
1187440a403fSchristos 		}
1188440a403fSchristos 	      else if (x_mode == IMM && op_mode != IMM)
1189440a403fSchristos 		{
1190440a403fSchristos 		  offsetT num = operands[i].exp.X_add_number & 0xffffffff;
1191440a403fSchristos 		  if (op_mode == KBIT || op_mode == DBIT)
1192440a403fSchristos 		    /* This is ok if the immediate value is sensible.  */;
1193440a403fSchristos 		  else if (op_mode == CONST_2)
1194440a403fSchristos 		    found = num == 2;
1195440a403fSchristos 		  else if (op_mode == CONST_4)
1196440a403fSchristos 		    found = num == 4;
1197440a403fSchristos 		  else if (op_mode == CONST_8)
1198440a403fSchristos 		    found = num == 8;
1199440a403fSchristos 		  else if (op_mode == CONST_16)
1200440a403fSchristos 		    found = num == 16;
1201440a403fSchristos 		  else
1202440a403fSchristos 		    found = 0;
1203440a403fSchristos 		}
1204440a403fSchristos 	      else if (op_mode == PCREL && op_mode == x_mode)
1205440a403fSchristos 		{
1206440a403fSchristos 		  /* movsd, bsr/bc and bsr/bs only come in PCREL16 flavour:
1207440a403fSchristos 		     If x_size is L_8, promote it.  */
1208440a403fSchristos 		  if (OP_KIND (this_try->opcode->how) == O_MOVSD
1209440a403fSchristos 		      || OP_KIND (this_try->opcode->how) == O_BSRBC
1210440a403fSchristos 		      || OP_KIND (this_try->opcode->how) == O_BSRBS)
1211440a403fSchristos 		    if (x_size == L_8)
1212440a403fSchristos 		      x_size = L_16;
1213440a403fSchristos 
1214440a403fSchristos 		  /* The size of the displacement is important.  */
1215440a403fSchristos 		  if (op_size != x_size)
1216440a403fSchristos 		    found = 0;
1217440a403fSchristos 		}
1218440a403fSchristos 	      else if ((op_mode == DISP || op_mode == IMM || op_mode == ABS
1219440a403fSchristos 			|| op_mode == INDEXB || op_mode == INDEXW
1220440a403fSchristos 			|| op_mode == INDEXL)
1221440a403fSchristos 		       && op_mode == x_mode)
1222440a403fSchristos 		{
1223440a403fSchristos 		  /* Promote a L_24 to L_32 if it makes us match.  */
1224440a403fSchristos 		  if (x_size == L_24 && op_size == L_32)
1225440a403fSchristos 		    {
1226440a403fSchristos 		      x &= ~SIZE;
1227440a403fSchristos 		      x |= x_size = L_32;
1228440a403fSchristos 		    }
1229440a403fSchristos 
1230440a403fSchristos 		  if (((x_size == L_16 && op_size == L_16U)
1231440a403fSchristos 		       || (x_size == L_8 && op_size == L_8U)
1232440a403fSchristos 		       || (x_size == L_3 && op_size == L_3NZ))
1233440a403fSchristos 		      /* We're deliberately more permissive for ABS modes.  */
1234440a403fSchristos 		      && (op_mode == ABS
1235440a403fSchristos 			  || constant_fits_size_p (operands + i, op_size,
1236440a403fSchristos 						   op & NO_SYMBOLS)))
1237440a403fSchristos 		    x_size = op_size;
1238440a403fSchristos 
1239440a403fSchristos 		  if (x_size != 0 && op_size != x_size)
1240440a403fSchristos 		    found = 0;
1241440a403fSchristos 		  else if (x_size == 0
1242440a403fSchristos 			   && ! constant_fits_size_p (operands + i, op_size,
1243440a403fSchristos 						      op & NO_SYMBOLS))
1244440a403fSchristos 		    found = 0;
1245440a403fSchristos 		}
1246440a403fSchristos 	      else if (op_mode != x_mode)
1247440a403fSchristos 		{
1248440a403fSchristos 		  found = 0;
1249440a403fSchristos 		}
1250440a403fSchristos 	    }
1251440a403fSchristos 	}
1252440a403fSchristos       if (found)
1253440a403fSchristos 	{
1254440a403fSchristos 	  if ((this_try->opcode->available == AV_H8SX && ! SXmode)
1255440a403fSchristos 	      || (this_try->opcode->available == AV_H8S && ! Smode)
1256440a403fSchristos 	      || (this_try->opcode->available == AV_H8H && ! Hmode))
1257440a403fSchristos 	    found = 0, found_other = this_try;
1258440a403fSchristos 	  else if (this_size != size && (this_size != SN && size != SN))
1259440a403fSchristos 	    found_mismatched = this_try, found = 0;
1260440a403fSchristos 
1261440a403fSchristos 	}
1262440a403fSchristos     }
1263440a403fSchristos   if (found)
1264440a403fSchristos     return this_try;
1265440a403fSchristos   if (found_other)
1266440a403fSchristos     {
1267440a403fSchristos       as_warn (_("Opcode `%s' with these operand types not available in %s mode"),
1268440a403fSchristos 	       found_other->opcode->name,
1269440a403fSchristos 	       (! Hmode && ! Smode ? "H8/300"
1270440a403fSchristos 		: SXmode ? "H8sx"
1271440a403fSchristos 		: Smode ? "H8/300S"
1272440a403fSchristos 		: "H8/300H"));
1273440a403fSchristos     }
1274440a403fSchristos   else if (found_mismatched)
1275440a403fSchristos     {
1276440a403fSchristos       as_warn (_("mismatch between opcode size and operand size"));
1277440a403fSchristos       return found_mismatched;
1278440a403fSchristos     }
1279440a403fSchristos   return 0;
1280440a403fSchristos }
1281440a403fSchristos 
1282440a403fSchristos static void
check_operand(struct h8_op * operand,unsigned int width,const char * string)1283440a403fSchristos check_operand (struct h8_op *operand, unsigned int width, const char *string)
1284440a403fSchristos {
1285440a403fSchristos   if (operand->exp.X_add_symbol == 0
1286440a403fSchristos       && operand->exp.X_op_symbol == 0)
1287440a403fSchristos     {
1288440a403fSchristos       /* No symbol involved, let's look at offset, it's dangerous if
1289440a403fSchristos 	 any of the high bits are not 0 or ff's, find out by oring or
1290440a403fSchristos 	 anding with the width and seeing if the answer is 0 or all
1291440a403fSchristos 	 fs.  */
1292440a403fSchristos 
1293440a403fSchristos       if (! constant_fits_width_p (operand, width))
1294440a403fSchristos 	{
1295440a403fSchristos 	  if (width == 255
1296440a403fSchristos 	      && (operand->exp.X_add_number & 0xff00) == 0xff00)
1297440a403fSchristos 	    {
1298440a403fSchristos 	      /* Just ignore this one - which happens when trying to
1299440a403fSchristos 		 fit a 16 bit address truncated into an 8 bit address
1300440a403fSchristos 		 of something like bset.  */
1301440a403fSchristos 	    }
1302440a403fSchristos 	  else if (strcmp (string, "@") == 0
1303440a403fSchristos 		   && width == 0xffff
1304440a403fSchristos 		   && (operand->exp.X_add_number & 0xff8000) == 0xff8000)
1305440a403fSchristos 	    {
1306440a403fSchristos 	      /* Just ignore this one - which happens when trying to
1307440a403fSchristos 		 fit a 24 bit address truncated into a 16 bit address
1308440a403fSchristos 		 of something like mov.w.  */
1309440a403fSchristos 	    }
1310440a403fSchristos 	  else
1311440a403fSchristos 	    {
1312440a403fSchristos 	      as_warn (_("operand %s0x%lx out of range."), string,
1313440a403fSchristos 		       (unsigned long) operand->exp.X_add_number);
1314440a403fSchristos 	    }
1315440a403fSchristos 	}
1316440a403fSchristos     }
1317440a403fSchristos }
1318440a403fSchristos 
1319440a403fSchristos /* RELAXMODE has one of 3 values:
1320440a403fSchristos 
1321440a403fSchristos    0 Output a "normal" reloc, no relaxing possible for this insn/reloc
1322440a403fSchristos 
1323440a403fSchristos    1 Output a relaxable 24bit absolute mov.w address relocation
1324440a403fSchristos      (may relax into a 16bit absolute address).
1325440a403fSchristos 
1326440a403fSchristos    2 Output a relaxable 16/24 absolute mov.b address relocation
1327440a403fSchristos      (may relax into an 8bit absolute address).  */
1328440a403fSchristos 
1329440a403fSchristos static void
do_a_fix_imm(int offset,int nibble,struct h8_op * operand,int relaxmode,const struct h8_instruction * this_try)1330440a403fSchristos do_a_fix_imm (int offset, int nibble, struct h8_op *operand, int relaxmode, const struct h8_instruction *this_try)
1331440a403fSchristos {
1332440a403fSchristos   int idx;
1333440a403fSchristos   int size;
1334440a403fSchristos   int where;
1335440a403fSchristos   char *bytes = frag_now->fr_literal + offset;
1336440a403fSchristos 
1337440a403fSchristos   const char *t = ((operand->mode & MODE) == IMM) ? "#" : "@";
1338440a403fSchristos 
1339440a403fSchristos   if (operand->exp.X_add_symbol == 0)
1340440a403fSchristos     {
1341440a403fSchristos       switch (operand->mode & SIZE)
1342440a403fSchristos 	{
1343440a403fSchristos 	case L_2:
1344440a403fSchristos 	  check_operand (operand, 0x3, t);
1345440a403fSchristos 	  bytes[0] |= (operand->exp.X_add_number & 3) << (nibble ? 0 : 4);
1346440a403fSchristos 	  break;
1347440a403fSchristos 	case L_3:
1348440a403fSchristos 	case L_3NZ:
1349440a403fSchristos 	  check_operand (operand, 0x7, t);
1350440a403fSchristos 	  bytes[0] |= (operand->exp.X_add_number & 7) << (nibble ? 0 : 4);
1351440a403fSchristos 	  break;
1352440a403fSchristos 	case L_4:
1353440a403fSchristos 	  check_operand (operand, 0xF, t);
1354440a403fSchristos 	  bytes[0] |= (operand->exp.X_add_number & 15) << (nibble ? 0 : 4);
1355440a403fSchristos 	  break;
1356440a403fSchristos 	case L_5:
1357440a403fSchristos 	  check_operand (operand, 0x1F, t);
1358440a403fSchristos 	  bytes[0] |= operand->exp.X_add_number & 31;
1359440a403fSchristos 	  break;
1360440a403fSchristos 	case L_8:
1361440a403fSchristos 	case L_8U:
1362440a403fSchristos 	  check_operand (operand, 0xff, t);
1363440a403fSchristos 	  bytes[0] |= operand->exp.X_add_number;
1364440a403fSchristos 	  break;
1365440a403fSchristos 	case L_16:
1366440a403fSchristos 	case L_16U:
1367440a403fSchristos 	  check_operand (operand, 0xffff, t);
1368440a403fSchristos 	  bytes[0] |= operand->exp.X_add_number >> 8;
1369440a403fSchristos 	  bytes[1] |= operand->exp.X_add_number >> 0;
1370440a403fSchristos 	  /* MOVA needs both relocs to relax the second operand properly.  */
1371440a403fSchristos 	  if (relaxmode != 0
1372440a403fSchristos 	      && (OP_KIND(this_try->opcode->how) == O_MOVAB
1373440a403fSchristos 		  || OP_KIND(this_try->opcode->how) == O_MOVAW
1374440a403fSchristos 		  || OP_KIND(this_try->opcode->how) == O_MOVAL))
1375440a403fSchristos 	    {
1376440a403fSchristos 	      idx = BFD_RELOC_16;
1377440a403fSchristos 	      fix_new_exp (frag_now, offset, 2, &operand->exp, 0, idx);
1378440a403fSchristos 	    }
1379440a403fSchristos 	  break;
1380440a403fSchristos 	case L_24:
1381440a403fSchristos 	  check_operand (operand, 0xffffff, t);
1382440a403fSchristos 	  bytes[0] |= operand->exp.X_add_number >> 16;
1383440a403fSchristos 	  bytes[1] |= operand->exp.X_add_number >> 8;
1384440a403fSchristos 	  bytes[2] |= operand->exp.X_add_number >> 0;
1385440a403fSchristos 	  break;
1386440a403fSchristos 
1387440a403fSchristos 	case L_32:
1388440a403fSchristos 	  /* This should be done with bfd.  */
1389440a403fSchristos 	  bytes[0] |= operand->exp.X_add_number >> 24;
1390440a403fSchristos 	  bytes[1] |= operand->exp.X_add_number >> 16;
1391440a403fSchristos 	  bytes[2] |= operand->exp.X_add_number >> 8;
1392440a403fSchristos 	  bytes[3] |= operand->exp.X_add_number >> 0;
1393440a403fSchristos 	  if (relaxmode != 0)
1394440a403fSchristos 	    {
1395440a403fSchristos 	      if ((operand->mode & MODE) == DISP && relaxmode == 1)
1396440a403fSchristos 		idx = BFD_RELOC_H8_DISP32A16;
1397440a403fSchristos 	      else
1398440a403fSchristos 		idx = (relaxmode == 2) ? R_MOV24B1 : R_MOVL1;
1399440a403fSchristos 	      fix_new_exp (frag_now, offset, 4, &operand->exp, 0, idx);
1400440a403fSchristos 	    }
1401440a403fSchristos 	  break;
1402440a403fSchristos 	}
1403440a403fSchristos     }
1404440a403fSchristos   else
1405440a403fSchristos     {
1406440a403fSchristos       switch (operand->mode & SIZE)
1407440a403fSchristos 	{
1408440a403fSchristos 	case L_24:
1409440a403fSchristos 	case L_32:
1410440a403fSchristos 	  size = 4;
1411440a403fSchristos 	  where = (operand->mode & SIZE) == L_24 ? -1 : 0;
1412440a403fSchristos 	  if ((operand->mode & MODE) == DISP && relaxmode == 1)
1413440a403fSchristos 	    idx = BFD_RELOC_H8_DISP32A16;
141406324dcfSchristos 	  else if (relaxmode == 2)
1415440a403fSchristos 	    idx = R_MOV24B1;
1416440a403fSchristos 	  else if (relaxmode == 1)
1417440a403fSchristos 	    idx = R_MOVL1;
1418440a403fSchristos 	  else
1419440a403fSchristos 	    idx = R_RELLONG;
1420440a403fSchristos 	  break;
1421440a403fSchristos 	default:
1422440a403fSchristos 	  as_bad (_("Can't work out size of operand.\n"));
142306324dcfSchristos 	  /* Fall through.  */
1424440a403fSchristos 	case L_16:
1425440a403fSchristos 	case L_16U:
1426440a403fSchristos 	  size = 2;
1427440a403fSchristos 	  where = 0;
1428440a403fSchristos 	  if (relaxmode == 2)
1429440a403fSchristos 	    idx = R_MOV16B1;
1430440a403fSchristos 	  else
1431440a403fSchristos 	    idx = R_RELWORD;
1432440a403fSchristos 	  operand->exp.X_add_number =
1433440a403fSchristos 	    ((operand->exp.X_add_number & 0xffff) ^ 0x8000) - 0x8000;
1434440a403fSchristos 	  operand->exp.X_add_number |= (bytes[0] << 8) | bytes[1];
1435440a403fSchristos 	  break;
1436440a403fSchristos 	case L_8:
1437440a403fSchristos 	  size = 1;
1438440a403fSchristos 	  where = 0;
1439440a403fSchristos 	  idx = R_RELBYTE;
1440440a403fSchristos 	  operand->exp.X_add_number =
1441440a403fSchristos 	    ((operand->exp.X_add_number & 0xff) ^ 0x80) - 0x80;
1442440a403fSchristos 	  operand->exp.X_add_number |= bytes[0];
1443440a403fSchristos 	}
1444440a403fSchristos 
1445440a403fSchristos       fix_new_exp (frag_now,
1446440a403fSchristos 		   offset + where,
1447440a403fSchristos 		   size,
1448440a403fSchristos 		   &operand->exp,
1449440a403fSchristos 		   0,
1450440a403fSchristos 		   idx);
1451440a403fSchristos     }
1452440a403fSchristos }
1453440a403fSchristos 
1454440a403fSchristos /* Now we know what sort of opcodes it is, let's build the bytes.  */
1455440a403fSchristos 
1456440a403fSchristos static void
build_bytes(const struct h8_instruction * this_try,struct h8_op * operand)1457440a403fSchristos build_bytes (const struct h8_instruction *this_try, struct h8_op *operand)
1458440a403fSchristos {
1459440a403fSchristos   int i;
1460440a403fSchristos   char *output = frag_more (this_try->length);
1461440a403fSchristos   const op_type *nibble_ptr = this_try->opcode->data.nib;
1462440a403fSchristos   op_type c;
1463440a403fSchristos   unsigned int nibble_count = 0;
1464440a403fSchristos   int op_at[3];
1465440a403fSchristos   int nib = 0;
1466440a403fSchristos   int movb = 0;
1467440a403fSchristos   char asnibbles[100];
1468440a403fSchristos   char *p = asnibbles;
1469440a403fSchristos   int high, low;
1470440a403fSchristos 
1471440a403fSchristos   if (!Hmode && this_try->opcode->available != AV_H8)
1472440a403fSchristos     as_warn (_("Opcode `%s' with these operand types not available in H8/300 mode"),
1473440a403fSchristos 	     this_try->opcode->name);
1474440a403fSchristos   else if (!Smode
1475440a403fSchristos 	   && this_try->opcode->available != AV_H8
1476440a403fSchristos 	   && this_try->opcode->available != AV_H8H)
1477440a403fSchristos     as_warn (_("Opcode `%s' with these operand types not available in H8/300H mode"),
1478440a403fSchristos 	     this_try->opcode->name);
1479440a403fSchristos   else if (!SXmode
1480440a403fSchristos 	   && this_try->opcode->available != AV_H8
1481440a403fSchristos 	   && this_try->opcode->available != AV_H8H
1482440a403fSchristos 	   && this_try->opcode->available != AV_H8S)
1483440a403fSchristos     as_warn (_("Opcode `%s' with these operand types not available in H8/300S mode"),
1484440a403fSchristos 	     this_try->opcode->name);
1485440a403fSchristos 
1486440a403fSchristos   while (*nibble_ptr != (op_type) E)
1487440a403fSchristos     {
1488440a403fSchristos       int d;
1489440a403fSchristos 
1490440a403fSchristos       nib = 0;
1491440a403fSchristos       c = *nibble_ptr++;
1492440a403fSchristos 
1493440a403fSchristos       d = (c & OP3) == OP3 ? 2 : (c & DST) == DST ? 1 : 0;
1494440a403fSchristos 
1495440a403fSchristos       if (c < 16)
1496440a403fSchristos 	nib = c;
1497440a403fSchristos       else
1498440a403fSchristos 	{
1499440a403fSchristos 	  int c2 = c & MODE;
1500440a403fSchristos 
1501440a403fSchristos 	  if (c2 == REG || c2 == LOWREG
1502440a403fSchristos 	      || c2 == IND || c2 == PREINC || c2 == PREDEC
1503440a403fSchristos 	      || c2 == POSTINC || c2 == POSTDEC)
1504440a403fSchristos 	    {
1505440a403fSchristos 	      nib = operand[d].reg;
1506440a403fSchristos 	      if (c2 == LOWREG)
1507440a403fSchristos 		nib &= 7;
1508440a403fSchristos 	    }
1509440a403fSchristos 
1510440a403fSchristos 	  else if (c & CTRL)	/* Control reg operand.  */
1511440a403fSchristos 	    nib = operand[d].reg;
1512440a403fSchristos 
1513440a403fSchristos 	  else if ((c & DISPREG) == (DISPREG))
1514440a403fSchristos 	    {
1515440a403fSchristos 	      nib = operand[d].reg;
1516440a403fSchristos 	    }
1517440a403fSchristos 	  else if (c2 == ABS)
1518440a403fSchristos 	    {
1519440a403fSchristos 	      operand[d].mode = c;
1520440a403fSchristos 	      op_at[d] = nibble_count;
1521440a403fSchristos 	      nib = 0;
1522440a403fSchristos 	    }
1523440a403fSchristos 	  else if (c2 == IMM || c2 == PCREL || c2 == ABS
1524440a403fSchristos 		   || (c & ABSJMP) || c2 == DISP)
1525440a403fSchristos 	    {
1526440a403fSchristos 	      operand[d].mode = c;
1527440a403fSchristos 	      op_at[d] = nibble_count;
1528440a403fSchristos 	      nib = 0;
1529440a403fSchristos 	    }
1530440a403fSchristos 	  else if ((c & IGNORE) || (c & DATA))
1531440a403fSchristos 	    nib = 0;
1532440a403fSchristos 
1533440a403fSchristos 	  else if (c2 == DBIT)
1534440a403fSchristos 	    {
1535440a403fSchristos 	      switch (operand[0].exp.X_add_number)
1536440a403fSchristos 		{
1537440a403fSchristos 		case 1:
1538440a403fSchristos 		  nib = c;
1539440a403fSchristos 		  break;
1540440a403fSchristos 		case 2:
1541440a403fSchristos 		  nib = 0x8 | c;
1542440a403fSchristos 		  break;
1543440a403fSchristos 		default:
1544440a403fSchristos 		  as_bad (_("Need #1 or #2 here"));
1545440a403fSchristos 		}
1546440a403fSchristos 	    }
1547440a403fSchristos 	  else if (c2 == KBIT)
1548440a403fSchristos 	    {
1549440a403fSchristos 	      switch (operand[0].exp.X_add_number)
1550440a403fSchristos 		{
1551440a403fSchristos 		case 1:
1552440a403fSchristos 		  nib = 0;
1553440a403fSchristos 		  break;
1554440a403fSchristos 		case 2:
1555440a403fSchristos 		  nib = 8;
1556440a403fSchristos 		  break;
1557440a403fSchristos 		case 4:
1558440a403fSchristos 		  if (!Hmode)
1559440a403fSchristos 		    as_warn (_("#4 not valid on H8/300."));
1560440a403fSchristos 		  nib = 9;
1561440a403fSchristos 		  break;
1562440a403fSchristos 
1563440a403fSchristos 		default:
1564440a403fSchristos 		  as_bad (_("Need #1 or #2 here"));
1565440a403fSchristos 		  break;
1566440a403fSchristos 		}
1567440a403fSchristos 	      /* Stop it making a fix.  */
1568440a403fSchristos 	      operand[0].mode = 0;
1569440a403fSchristos 	    }
1570440a403fSchristos 
1571440a403fSchristos 	  if (c & MEMRELAX)
1572440a403fSchristos 	    operand[d].mode |= MEMRELAX;
1573440a403fSchristos 
1574440a403fSchristos 	  if (c & B31)
1575440a403fSchristos 	    nib |= 0x8;
1576440a403fSchristos 
1577440a403fSchristos 	  if (c & B21)
1578440a403fSchristos 	    nib |= 0x4;
1579440a403fSchristos 
1580440a403fSchristos 	  if (c & B11)
1581440a403fSchristos 	    nib |= 0x2;
1582440a403fSchristos 
1583440a403fSchristos 	  if (c & B01)
1584440a403fSchristos 	    nib |= 0x1;
1585440a403fSchristos 
1586440a403fSchristos 	  if (c2 == MACREG)
1587440a403fSchristos 	    {
1588440a403fSchristos 	      if (operand[0].mode == MACREG)
1589440a403fSchristos 		/* stmac has mac[hl] as the first operand.  */
1590440a403fSchristos 		nib = 2 + operand[0].reg;
1591440a403fSchristos 	      else
1592440a403fSchristos 		/* ldmac has mac[hl] as the second operand.  */
1593440a403fSchristos 		nib = 2 + operand[1].reg;
1594440a403fSchristos 	    }
1595440a403fSchristos 	}
1596440a403fSchristos       nibble_count++;
1597440a403fSchristos 
1598440a403fSchristos       *p++ = nib;
1599440a403fSchristos     }
1600440a403fSchristos 
1601440a403fSchristos   /* Disgusting.  Why, oh why didn't someone ask us for advice
1602440a403fSchristos      on the assembler format.  */
1603440a403fSchristos   if (OP_KIND (this_try->opcode->how) == O_LDM)
1604440a403fSchristos     {
1605440a403fSchristos       high = (operand[1].reg >> 8) & 0xf;
1606440a403fSchristos       low  = (operand[1].reg) & 0xf;
1607440a403fSchristos       asnibbles[2] = high - low;
1608440a403fSchristos       asnibbles[7] = high;
1609440a403fSchristos     }
1610440a403fSchristos   else if (OP_KIND (this_try->opcode->how) == O_STM)
1611440a403fSchristos     {
1612440a403fSchristos       high = (operand[0].reg >> 8) & 0xf;
1613440a403fSchristos       low  = (operand[0].reg) & 0xf;
1614440a403fSchristos       asnibbles[2] = high - low;
1615440a403fSchristos       asnibbles[7] = low;
1616440a403fSchristos     }
1617440a403fSchristos 
1618440a403fSchristos   for (i = 0; i < this_try->length; i++)
1619440a403fSchristos     output[i] = (asnibbles[i * 2] << 4) | asnibbles[i * 2 + 1];
1620440a403fSchristos 
1621440a403fSchristos   /* Note if this is a mov.b or a bit manipulation instruction
1622440a403fSchristos      there is a special relaxation which only applies.  */
1623440a403fSchristos   if (   this_try->opcode->how == O (O_MOV,   SB)
1624440a403fSchristos       || this_try->opcode->how == O (O_BCLR,  SB)
1625440a403fSchristos       || this_try->opcode->how == O (O_BAND,  SB)
1626440a403fSchristos       || this_try->opcode->how == O (O_BIAND, SB)
1627440a403fSchristos       || this_try->opcode->how == O (O_BILD,  SB)
1628440a403fSchristos       || this_try->opcode->how == O (O_BIOR,  SB)
1629440a403fSchristos       || this_try->opcode->how == O (O_BIST,  SB)
1630440a403fSchristos       || this_try->opcode->how == O (O_BIXOR, SB)
1631440a403fSchristos       || this_try->opcode->how == O (O_BLD,   SB)
1632440a403fSchristos       || this_try->opcode->how == O (O_BNOT,  SB)
1633440a403fSchristos       || this_try->opcode->how == O (O_BOR,   SB)
1634440a403fSchristos       || this_try->opcode->how == O (O_BSET,  SB)
1635440a403fSchristos       || this_try->opcode->how == O (O_BST,   SB)
1636440a403fSchristos       || this_try->opcode->how == O (O_BTST,  SB)
1637440a403fSchristos       || this_try->opcode->how == O (O_BXOR,  SB))
1638440a403fSchristos     movb = 1;
1639440a403fSchristos 
1640440a403fSchristos   /* Output any fixes.  */
1641440a403fSchristos   for (i = 0; i < this_try->noperands; i++)
1642440a403fSchristos     {
1643440a403fSchristos       int x = operand[i].mode;
1644440a403fSchristos       int x_mode = x & MODE;
1645440a403fSchristos 
1646440a403fSchristos       if (x_mode == IMM || x_mode == DISP)
1647440a403fSchristos 	do_a_fix_imm (output - frag_now->fr_literal + op_at[i] / 2,
1648440a403fSchristos 		      op_at[i] & 1, operand + i, (x & MEMRELAX) != 0,
1649440a403fSchristos 		      this_try);
1650440a403fSchristos       else if (x_mode == ABS)
1651440a403fSchristos 	do_a_fix_imm (output - frag_now->fr_literal + op_at[i] / 2,
1652440a403fSchristos 		      op_at[i] & 1, operand + i,
1653440a403fSchristos 		      (x & MEMRELAX) ? movb + 1 : 0,
1654440a403fSchristos 		      this_try);
1655440a403fSchristos 
1656440a403fSchristos       else if (x_mode == PCREL)
1657440a403fSchristos 	{
1658440a403fSchristos 	  int size16 = (x & SIZE) == L_16;
1659440a403fSchristos 	  int size = size16 ? 2 : 1;
1660440a403fSchristos 	  int type = size16 ? R_PCRWORD : R_PCRBYTE;
1661440a403fSchristos 	  fixS *fixP;
1662440a403fSchristos 
1663440a403fSchristos 	  check_operand (operand + i, size16 ? 0x7fff : 0x7f, "@");
1664440a403fSchristos 
1665440a403fSchristos 	  if (operand[i].exp.X_add_number & 1)
1666440a403fSchristos 	    as_warn (_("branch operand has odd offset (%lx)\n"),
1667440a403fSchristos 		     (unsigned long) operand->exp.X_add_number);
1668440a403fSchristos 	  if (size16)
1669440a403fSchristos 	    {
1670440a403fSchristos 	      operand[i].exp.X_add_number =
1671440a403fSchristos 		((operand[i].exp.X_add_number & 0xffff) ^ 0x8000) - 0x8000;
1672440a403fSchristos 	    }
1673440a403fSchristos 	  else
1674440a403fSchristos 	    {
1675440a403fSchristos 	      operand[i].exp.X_add_number =
1676440a403fSchristos 		((operand[i].exp.X_add_number & 0xff) ^ 0x80) - 0x80;
1677440a403fSchristos 	    }
1678440a403fSchristos 
1679440a403fSchristos 	  /* For BRA/S.  */
1680440a403fSchristos 	  if (! size16)
1681440a403fSchristos 	    operand[i].exp.X_add_number |= output[op_at[i] / 2];
1682440a403fSchristos 
1683440a403fSchristos 	  fixP = fix_new_exp (frag_now,
1684440a403fSchristos 			      output - frag_now->fr_literal + op_at[i] / 2,
1685440a403fSchristos 			      size,
1686440a403fSchristos 			      &operand[i].exp,
1687440a403fSchristos 			      1,
1688440a403fSchristos 			      type);
1689440a403fSchristos 	  fixP->fx_signed = 1;
1690440a403fSchristos 	}
1691440a403fSchristos       else if (x_mode == MEMIND)
1692440a403fSchristos 	{
1693440a403fSchristos 	  check_operand (operand + i, 0xff, "@@");
1694440a403fSchristos 	  fix_new_exp (frag_now,
1695440a403fSchristos 		       output - frag_now->fr_literal + 1,
1696440a403fSchristos 		       1,
1697440a403fSchristos 		       &operand[i].exp,
1698440a403fSchristos 		       0,
1699440a403fSchristos 		       R_MEM_INDIRECT);
1700440a403fSchristos 	}
1701440a403fSchristos       else if (x_mode == VECIND)
1702440a403fSchristos 	{
1703440a403fSchristos 	  check_operand (operand + i, 0x7f, "@@");
1704440a403fSchristos 	  /* FIXME: approximating the effect of "B31" here...
1705440a403fSchristos 	     This is very hackish, and ought to be done a better way.  */
1706440a403fSchristos 	  operand[i].exp.X_add_number |= 0x80;
1707440a403fSchristos 	  fix_new_exp (frag_now,
1708440a403fSchristos 		       output - frag_now->fr_literal + 1,
1709440a403fSchristos 		       1,
1710440a403fSchristos 		       &operand[i].exp,
1711440a403fSchristos 		       0,
1712440a403fSchristos 		       R_MEM_INDIRECT);
1713440a403fSchristos 	}
1714440a403fSchristos       else if (x & ABSJMP)
1715440a403fSchristos 	{
1716440a403fSchristos 	  int where = 0;
1717440a403fSchristos 	  bfd_reloc_code_real_type reloc_type = R_JMPL1;
1718440a403fSchristos 
1719440a403fSchristos 	  /* To be compatible with the proposed H8 ELF format, we
1720440a403fSchristos 	     want the relocation's offset to point to the first byte
1721440a403fSchristos 	     that will be modified, not to the start of the instruction.  */
1722440a403fSchristos 
1723440a403fSchristos 	  if ((operand->mode & SIZE) == L_32)
1724440a403fSchristos 	    {
1725440a403fSchristos 	      where = 2;
1726440a403fSchristos 	      reloc_type = R_RELLONG;
1727440a403fSchristos 	    }
1728440a403fSchristos 	  else
1729440a403fSchristos 	    where = 1;
1730440a403fSchristos 
1731440a403fSchristos 	  /* This jmp may be a jump or a branch.  */
1732440a403fSchristos 
1733440a403fSchristos 	  check_operand (operand + i,
1734440a403fSchristos 			 SXmode ? 0xffffffff : Hmode ? 0xffffff : 0xffff,
1735440a403fSchristos 			 "@");
1736440a403fSchristos 
1737440a403fSchristos 	  if (operand[i].exp.X_add_number & 1)
1738440a403fSchristos 	    as_warn (_("branch operand has odd offset (%lx)\n"),
1739440a403fSchristos 		     (unsigned long) operand->exp.X_add_number);
1740440a403fSchristos 
1741440a403fSchristos 	  if (!Hmode)
1742440a403fSchristos 	    operand[i].exp.X_add_number =
1743440a403fSchristos 	      ((operand[i].exp.X_add_number & 0xffff) ^ 0x8000) - 0x8000;
1744440a403fSchristos 	  fix_new_exp (frag_now,
1745440a403fSchristos 		       output - frag_now->fr_literal + where,
1746440a403fSchristos 		       4,
1747440a403fSchristos 		       &operand[i].exp,
1748440a403fSchristos 		       0,
1749440a403fSchristos 		       reloc_type);
1750440a403fSchristos 	}
1751440a403fSchristos     }
1752440a403fSchristos }
1753440a403fSchristos 
1754440a403fSchristos /* Try to give an intelligent error message for common and simple to
1755440a403fSchristos    detect errors.  */
1756440a403fSchristos 
1757440a403fSchristos static void
clever_message(const struct h8_instruction * instruction,struct h8_op * operand)1758440a403fSchristos clever_message (const struct h8_instruction *instruction,
1759440a403fSchristos 		struct h8_op *operand)
1760440a403fSchristos {
1761440a403fSchristos   /* Find out if there was more than one possible opcode.  */
1762440a403fSchristos 
1763440a403fSchristos   if ((instruction + 1)->idx != instruction->idx)
1764440a403fSchristos     {
1765440a403fSchristos       int argn;
1766440a403fSchristos 
1767440a403fSchristos       /* Only one opcode of this flavour, try to guess which operand
1768440a403fSchristos          didn't match.  */
1769440a403fSchristos       for (argn = 0; argn < instruction->noperands; argn++)
1770440a403fSchristos 	{
1771440a403fSchristos 	  switch (instruction->opcode->args.nib[argn])
1772440a403fSchristos 	    {
1773440a403fSchristos 	    case RD16:
1774440a403fSchristos 	      if (operand[argn].mode != RD16)
1775440a403fSchristos 		{
1776440a403fSchristos 		  as_bad (_("destination operand must be 16 bit register"));
1777440a403fSchristos 		  return;
1778440a403fSchristos 
1779440a403fSchristos 		}
1780440a403fSchristos 	      break;
1781440a403fSchristos 
1782440a403fSchristos 	    case RS8:
1783440a403fSchristos 	      if (operand[argn].mode != RS8)
1784440a403fSchristos 		{
1785440a403fSchristos 		  as_bad (_("source operand must be 8 bit register"));
1786440a403fSchristos 		  return;
1787440a403fSchristos 		}
1788440a403fSchristos 	      break;
1789440a403fSchristos 
1790440a403fSchristos 	    case ABS16DST:
1791440a403fSchristos 	      if (operand[argn].mode != ABS16DST)
1792440a403fSchristos 		{
1793440a403fSchristos 		  as_bad (_("destination operand must be 16bit absolute address"));
1794440a403fSchristos 		  return;
1795440a403fSchristos 		}
1796440a403fSchristos 	      break;
1797440a403fSchristos 	    case RD8:
1798440a403fSchristos 	      if (operand[argn].mode != RD8)
1799440a403fSchristos 		{
1800440a403fSchristos 		  as_bad (_("destination operand must be 8 bit register"));
1801440a403fSchristos 		  return;
1802440a403fSchristos 		}
1803440a403fSchristos 	      break;
1804440a403fSchristos 
1805440a403fSchristos 	    case ABS16SRC:
1806440a403fSchristos 	      if (operand[argn].mode != ABS16SRC)
1807440a403fSchristos 		{
1808440a403fSchristos 		  as_bad (_("source operand must be 16bit absolute address"));
1809440a403fSchristos 		  return;
1810440a403fSchristos 		}
1811440a403fSchristos 	      break;
1812440a403fSchristos 
1813440a403fSchristos 	    }
1814440a403fSchristos 	}
1815440a403fSchristos     }
1816440a403fSchristos   as_bad (_("invalid operands"));
1817440a403fSchristos }
1818440a403fSchristos 
1819440a403fSchristos 
1820440a403fSchristos /* If OPERAND is part of an address, adjust its size and value given
1821440a403fSchristos    that it addresses SIZE bytes.
1822440a403fSchristos 
1823440a403fSchristos    This function decides how big non-immediate constants are when no
1824440a403fSchristos    size was explicitly given.  It also scales down the assembly-level
1825440a403fSchristos    displacement in an @(d:2,ERn) operand.  */
1826440a403fSchristos 
1827440a403fSchristos static void
fix_operand_size(struct h8_op * operand,int size)1828440a403fSchristos fix_operand_size (struct h8_op *operand, int size)
1829440a403fSchristos {
1830440a403fSchristos   if (SXmode && (operand->mode & MODE) == DISP)
1831440a403fSchristos     {
1832440a403fSchristos       /* If the user didn't specify an operand width, see if we
1833440a403fSchristos 	 can use @(d:2,ERn).  */
1834440a403fSchristos       if ((operand->mode & SIZE) == 0
1835440a403fSchristos 	  && operand->exp.X_add_symbol == 0
1836440a403fSchristos 	  && operand->exp.X_op_symbol == 0
1837440a403fSchristos 	  && (operand->exp.X_add_number == size
1838440a403fSchristos 	      || operand->exp.X_add_number == size * 2
1839440a403fSchristos 	      || operand->exp.X_add_number == size * 3))
1840440a403fSchristos 	operand->mode |= L_2;
1841440a403fSchristos 
1842440a403fSchristos       /* Scale down the displacement in an @(d:2,ERn) operand.
1843440a403fSchristos 	 X_add_number then contains the desired field value.  */
1844440a403fSchristos       if ((operand->mode & SIZE) == L_2)
1845440a403fSchristos 	{
1846440a403fSchristos 	  if (operand->exp.X_add_number % size != 0)
1847440a403fSchristos 	    as_warn (_("operand/size mis-match"));
1848440a403fSchristos 	  operand->exp.X_add_number /= size;
1849440a403fSchristos 	}
1850440a403fSchristos     }
1851440a403fSchristos 
1852440a403fSchristos   if ((operand->mode & SIZE) == 0)
1853440a403fSchristos     switch (operand->mode & MODE)
1854440a403fSchristos       {
1855440a403fSchristos       case DISP:
1856440a403fSchristos       case INDEXB:
1857440a403fSchristos       case INDEXW:
1858440a403fSchristos       case INDEXL:
1859440a403fSchristos       case ABS:
1860440a403fSchristos 	/* Pick a 24-bit address unless we know that a 16-bit address
1861440a403fSchristos 	   is safe.  get_specific() will relax L_24 into L_32 where
1862440a403fSchristos 	   necessary.  */
1863440a403fSchristos 	if (Hmode
1864440a403fSchristos 	    && !Nmode
1865440a403fSchristos 	    && ((((addressT) operand->exp.X_add_number + 0x8000)
1866440a403fSchristos 		 & 0xffffffff) > 0xffff
1867440a403fSchristos 		|| operand->exp.X_add_symbol != 0
1868440a403fSchristos 		|| operand->exp.X_op_symbol != 0))
1869440a403fSchristos 	  operand->mode |= L_24;
1870440a403fSchristos 	else
1871440a403fSchristos 	  operand->mode |= L_16;
1872440a403fSchristos 	break;
1873440a403fSchristos 
1874440a403fSchristos       case PCREL:
1875440a403fSchristos 	if ((((addressT) operand->exp.X_add_number + 0x80)
1876440a403fSchristos 	     & 0xffffffff) <= 0xff)
1877440a403fSchristos 	  {
1878440a403fSchristos 	    if (operand->exp.X_add_symbol != NULL)
1879440a403fSchristos 	      operand->mode |= bsize;
1880440a403fSchristos 	    else
1881440a403fSchristos 	      operand->mode |= L_8;
1882440a403fSchristos 	  }
1883440a403fSchristos 	else
1884440a403fSchristos 	  operand->mode |= L_16;
1885440a403fSchristos 	break;
1886440a403fSchristos       }
1887440a403fSchristos }
1888440a403fSchristos 
1889440a403fSchristos 
1890440a403fSchristos /* This is the guts of the machine-dependent assembler.  STR points to
1891440a403fSchristos    a machine dependent instruction.  This function is supposed to emit
1892440a403fSchristos    the frags/bytes it assembles.  */
1893440a403fSchristos 
1894440a403fSchristos void
md_assemble(char * str)1895440a403fSchristos md_assemble (char *str)
1896440a403fSchristos {
1897440a403fSchristos   char *op_start;
1898440a403fSchristos   char *op_end;
1899440a403fSchristos   struct h8_op operand[3];
1900440a403fSchristos   const struct h8_instruction *instruction;
1901440a403fSchristos   const struct h8_instruction *prev_instruction;
1902440a403fSchristos 
1903440a403fSchristos   char *dot = 0;
1904440a403fSchristos   char *slash = 0;
1905440a403fSchristos   char c;
1906440a403fSchristos   int size, i;
1907440a403fSchristos 
1908440a403fSchristos   /* Drop leading whitespace.  */
1909440a403fSchristos   while (*str == ' ')
1910440a403fSchristos     str++;
1911440a403fSchristos 
1912440a403fSchristos   /* Find the op code end.  */
1913440a403fSchristos   for (op_start = op_end = str;
1914440a403fSchristos        *op_end != 0 && *op_end != ' ';
1915440a403fSchristos        op_end++)
1916440a403fSchristos     {
1917440a403fSchristos       if (*op_end == '.')
1918440a403fSchristos 	{
1919440a403fSchristos 	  dot = op_end + 1;
1920440a403fSchristos 	  *op_end = 0;
1921440a403fSchristos 	  op_end += 2;
1922440a403fSchristos 	  break;
1923440a403fSchristos 	}
1924440a403fSchristos       else if (*op_end == '/' && ! slash)
1925440a403fSchristos 	slash = op_end;
1926440a403fSchristos     }
1927440a403fSchristos 
1928440a403fSchristos   if (op_end == op_start)
1929440a403fSchristos     {
1930440a403fSchristos       as_bad (_("can't find opcode "));
1931440a403fSchristos     }
1932440a403fSchristos   c = *op_end;
1933440a403fSchristos 
1934440a403fSchristos   *op_end = 0;
1935440a403fSchristos 
1936440a403fSchristos   /* The assembler stops scanning the opcode at slashes, so it fails
1937440a403fSchristos      to make characters following them lower case.  Fix them.  */
1938440a403fSchristos   if (slash)
1939440a403fSchristos     while (*++slash)
1940440a403fSchristos       *slash = TOLOWER (*slash);
1941440a403fSchristos 
1942440a403fSchristos   instruction = (const struct h8_instruction *)
1943440a403fSchristos     hash_find (opcode_hash_control, op_start);
1944440a403fSchristos 
1945440a403fSchristos   if (instruction == NULL)
1946440a403fSchristos     {
1947440a403fSchristos       as_bad (_("unknown opcode"));
1948440a403fSchristos       return;
1949440a403fSchristos     }
1950440a403fSchristos 
1951440a403fSchristos   /* We used to set input_line_pointer to the result of get_operands,
1952440a403fSchristos      but that is wrong.  Our caller assumes we don't change it.  */
1953440a403fSchristos 
1954440a403fSchristos   operand[0].mode = 0;
1955440a403fSchristos   operand[1].mode = 0;
1956440a403fSchristos   operand[2].mode = 0;
1957440a403fSchristos 
1958440a403fSchristos   if (OP_KIND (instruction->opcode->how) == O_MOVAB
1959440a403fSchristos       || OP_KIND (instruction->opcode->how) == O_MOVAW
1960440a403fSchristos       || OP_KIND (instruction->opcode->how) == O_MOVAL)
1961440a403fSchristos     get_mova_operands (op_end, operand);
1962440a403fSchristos   else if (OP_KIND (instruction->opcode->how) == O_RTEL
1963440a403fSchristos 	   || OP_KIND (instruction->opcode->how) == O_RTSL)
1964440a403fSchristos     get_rtsl_operands (op_end, operand);
1965440a403fSchristos   else
1966440a403fSchristos     get_operands (instruction->noperands, op_end, operand);
1967440a403fSchristos 
1968440a403fSchristos   *op_end = c;
1969440a403fSchristos   prev_instruction = instruction;
1970440a403fSchristos 
1971440a403fSchristos   /* Now we have operands from instruction.
1972440a403fSchristos      Let's check them out for ldm and stm.  */
1973440a403fSchristos   if (OP_KIND (instruction->opcode->how) == O_LDM)
1974440a403fSchristos     {
1975440a403fSchristos       /* The first operand must be @er7+, and the
1976440a403fSchristos 	 second operand must be a register pair.  */
1977440a403fSchristos       if ((operand[0].mode != RSINC)
1978440a403fSchristos            || (operand[0].reg != 7)
1979440a403fSchristos            || ((operand[1].reg & 0x80000000) == 0))
1980440a403fSchristos 	as_bad (_("invalid operand in ldm"));
1981440a403fSchristos     }
1982440a403fSchristos   else if (OP_KIND (instruction->opcode->how) == O_STM)
1983440a403fSchristos     {
1984440a403fSchristos       /* The first operand must be a register pair,
1985440a403fSchristos 	 and the second operand must be @-er7.  */
1986440a403fSchristos       if (((operand[0].reg & 0x80000000) == 0)
1987440a403fSchristos             || (operand[1].mode != RDDEC)
1988440a403fSchristos             || (operand[1].reg != 7))
1989440a403fSchristos 	as_bad (_("invalid operand in stm"));
1990440a403fSchristos     }
1991440a403fSchristos 
1992440a403fSchristos   size = SN;
1993440a403fSchristos   if (dot)
1994440a403fSchristos     {
1995440a403fSchristos       switch (TOLOWER (*dot))
1996440a403fSchristos 	{
1997440a403fSchristos 	case 'b':
1998440a403fSchristos 	  size = SB;
1999440a403fSchristos 	  break;
2000440a403fSchristos 
2001440a403fSchristos 	case 'w':
2002440a403fSchristos 	  size = SW;
2003440a403fSchristos 	  break;
2004440a403fSchristos 
2005440a403fSchristos 	case 'l':
2006440a403fSchristos 	  size = SL;
2007440a403fSchristos 	  break;
2008440a403fSchristos 	}
2009440a403fSchristos     }
2010440a403fSchristos   if (OP_KIND (instruction->opcode->how) == O_MOVAB ||
2011440a403fSchristos       OP_KIND (instruction->opcode->how) == O_MOVAW ||
2012440a403fSchristos       OP_KIND (instruction->opcode->how) == O_MOVAL)
2013440a403fSchristos     {
2014440a403fSchristos       switch (operand[0].mode & MODE)
2015440a403fSchristos 	{
2016440a403fSchristos 	case INDEXB:
2017440a403fSchristos 	default:
2018440a403fSchristos 	  fix_operand_size (&operand[1], 1);
2019440a403fSchristos 	  break;
2020440a403fSchristos 	case INDEXW:
2021440a403fSchristos 	  fix_operand_size (&operand[1], 2);
2022440a403fSchristos 	  break;
2023440a403fSchristos 	case INDEXL:
2024440a403fSchristos 	  fix_operand_size (&operand[1], 4);
2025440a403fSchristos 	  break;
2026440a403fSchristos 	}
2027440a403fSchristos     }
2028440a403fSchristos   else
2029440a403fSchristos     {
2030440a403fSchristos       for (i = 0; i < 3 && operand[i].mode != 0; i++)
2031440a403fSchristos 	switch (size)
2032440a403fSchristos 	  {
2033440a403fSchristos 	  case SN:
2034440a403fSchristos 	  case SB:
2035440a403fSchristos 	  default:
2036440a403fSchristos 	    fix_operand_size (&operand[i], 1);
2037440a403fSchristos 	    break;
2038440a403fSchristos 	  case SW:
2039440a403fSchristos 	    fix_operand_size (&operand[i], 2);
2040440a403fSchristos 	    break;
2041440a403fSchristos 	  case SL:
2042440a403fSchristos 	    fix_operand_size (&operand[i], 4);
2043440a403fSchristos 	    break;
2044440a403fSchristos 	  }
2045440a403fSchristos     }
2046440a403fSchristos 
2047440a403fSchristos   instruction = get_specific (instruction, operand, size);
2048440a403fSchristos 
2049440a403fSchristos   if (instruction == 0)
2050440a403fSchristos     {
2051440a403fSchristos       /* Couldn't find an opcode which matched the operands.  */
2052440a403fSchristos       char *where = frag_more (2);
2053440a403fSchristos 
2054440a403fSchristos       where[0] = 0x0;
2055440a403fSchristos       where[1] = 0x0;
2056440a403fSchristos       clever_message (prev_instruction, operand);
2057440a403fSchristos 
2058440a403fSchristos       return;
2059440a403fSchristos     }
2060440a403fSchristos 
2061440a403fSchristos   build_bytes (instruction, operand);
2062440a403fSchristos 
2063440a403fSchristos   dwarf2_emit_insn (instruction->length);
2064440a403fSchristos }
2065440a403fSchristos 
2066440a403fSchristos symbolS *
md_undefined_symbol(char * name ATTRIBUTE_UNUSED)2067440a403fSchristos md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
2068440a403fSchristos {
2069440a403fSchristos   return 0;
2070440a403fSchristos }
2071440a403fSchristos 
2072440a403fSchristos /* Various routines to kill one day.  */
2073440a403fSchristos 
2074440a403fSchristos const char *
md_atof(int type,char * litP,int * sizeP)2075440a403fSchristos md_atof (int type, char *litP, int *sizeP)
2076440a403fSchristos {
2077440a403fSchristos   return ieee_md_atof (type, litP, sizeP, TRUE);
2078440a403fSchristos }
2079440a403fSchristos 
2080440a403fSchristos #define OPTION_H_TICK_HEX      (OPTION_MD_BASE)
2081440a403fSchristos #define OPTION_MACH            (OPTION_MD_BASE+1)
2082440a403fSchristos 
2083440a403fSchristos const char *md_shortopts = "";
2084440a403fSchristos struct option md_longopts[] =
2085440a403fSchristos {
2086440a403fSchristos   { "h-tick-hex", no_argument,	      NULL, OPTION_H_TICK_HEX  },
2087440a403fSchristos   { "mach", required_argument, NULL, OPTION_MACH },
2088440a403fSchristos   {NULL, no_argument, NULL, 0}
2089440a403fSchristos };
2090440a403fSchristos 
2091440a403fSchristos size_t md_longopts_size = sizeof (md_longopts);
2092440a403fSchristos 
2093440a403fSchristos struct mach_func
2094440a403fSchristos {
2095440a403fSchristos   const char *name;
2096440a403fSchristos   void (*func) (void);
2097440a403fSchristos };
2098440a403fSchristos 
2099440a403fSchristos static void
mach_h8300h(void)2100440a403fSchristos mach_h8300h (void)
2101440a403fSchristos {
2102440a403fSchristos   Hmode = 1;
2103440a403fSchristos   Smode = 0;
2104440a403fSchristos   Nmode = 0;
2105440a403fSchristos   SXmode = 0;
2106440a403fSchristos   default_mach = bfd_mach_h8300h;
2107440a403fSchristos }
2108440a403fSchristos 
2109440a403fSchristos static void
mach_h8300hn(void)2110440a403fSchristos mach_h8300hn (void)
2111440a403fSchristos {
2112440a403fSchristos   Hmode = 1;
2113440a403fSchristos   Smode = 0;
2114440a403fSchristos   Nmode = 1;
2115440a403fSchristos   SXmode = 0;
2116440a403fSchristos   default_mach = bfd_mach_h8300hn;
2117440a403fSchristos }
2118440a403fSchristos 
2119440a403fSchristos static void
mach_h8300s(void)2120440a403fSchristos mach_h8300s (void)
2121440a403fSchristos {
2122440a403fSchristos   Hmode = 1;
2123440a403fSchristos   Smode = 1;
2124440a403fSchristos   Nmode = 0;
2125440a403fSchristos   SXmode = 0;
2126440a403fSchristos   default_mach = bfd_mach_h8300s;
2127440a403fSchristos }
2128440a403fSchristos 
2129440a403fSchristos static void
mach_h8300sn(void)2130440a403fSchristos mach_h8300sn (void)
2131440a403fSchristos {
2132440a403fSchristos   Hmode = 1;
2133440a403fSchristos   Smode = 1;
2134440a403fSchristos   Nmode = 1;
2135440a403fSchristos   SXmode = 0;
2136440a403fSchristos   default_mach = bfd_mach_h8300sn;
2137440a403fSchristos }
2138440a403fSchristos 
2139440a403fSchristos static void
mach_h8300sx(void)2140440a403fSchristos mach_h8300sx (void)
2141440a403fSchristos {
2142440a403fSchristos   Hmode = 1;
2143440a403fSchristos   Smode = 1;
2144440a403fSchristos   Nmode = 0;
2145440a403fSchristos   SXmode = 1;
2146440a403fSchristos   default_mach = bfd_mach_h8300sx;
2147440a403fSchristos }
2148440a403fSchristos 
2149440a403fSchristos static void
mach_h8300sxn(void)2150440a403fSchristos mach_h8300sxn (void)
2151440a403fSchristos {
2152440a403fSchristos   Hmode = 1;
2153440a403fSchristos   Smode = 1;
2154440a403fSchristos   Nmode = 1;
2155440a403fSchristos   SXmode = 1;
2156440a403fSchristos   default_mach = bfd_mach_h8300sxn;
2157440a403fSchristos }
2158440a403fSchristos 
2159440a403fSchristos const struct mach_func mach_table[] =
2160440a403fSchristos {
2161440a403fSchristos   {"h8300h",  mach_h8300h},
2162440a403fSchristos   {"h8300hn", mach_h8300hn},
2163440a403fSchristos   {"h8300s",  mach_h8300s},
2164440a403fSchristos   {"h8300sn", mach_h8300sn},
2165440a403fSchristos   {"h8300sx", mach_h8300sx},
2166440a403fSchristos   {"h8300sxn", mach_h8300sxn}
2167440a403fSchristos };
2168440a403fSchristos 
2169440a403fSchristos int
md_parse_option(int c ATTRIBUTE_UNUSED,const char * arg ATTRIBUTE_UNUSED)2170440a403fSchristos md_parse_option (int c ATTRIBUTE_UNUSED, const char *arg ATTRIBUTE_UNUSED)
2171440a403fSchristos {
2172440a403fSchristos   unsigned int i;
2173440a403fSchristos   switch (c)
2174440a403fSchristos     {
2175440a403fSchristos     case OPTION_H_TICK_HEX:
2176440a403fSchristos       enable_h_tick_hex = 1;
2177440a403fSchristos       break;
2178440a403fSchristos     case OPTION_MACH:
2179440a403fSchristos       for (i = 0; i < sizeof(mach_table) / sizeof(struct mach_func); i++)
2180440a403fSchristos 	{
2181440a403fSchristos 	  if (strcasecmp (arg, mach_table[i].name) == 0)
2182440a403fSchristos 	    {
2183440a403fSchristos 	      mach_table[i].func();
2184440a403fSchristos 	      break;
2185440a403fSchristos 	    }
2186440a403fSchristos 	}
2187440a403fSchristos       if (i >= sizeof(mach_table) / sizeof(struct mach_func))
2188440a403fSchristos 	as_bad (_("Invalid argument to --mach option: %s"), arg);
2189440a403fSchristos       break;
2190440a403fSchristos     default:
2191440a403fSchristos       return 0;
2192440a403fSchristos     }
2193440a403fSchristos   return 1;
2194440a403fSchristos }
2195440a403fSchristos 
2196440a403fSchristos void
md_show_usage(FILE * stream)2197440a403fSchristos md_show_usage (FILE *stream)
2198440a403fSchristos {
2199440a403fSchristos   fprintf (stream, _(" H8300-specific assembler options:\n"));
2200440a403fSchristos   fprintf (stream, _("\
2201440a403fSchristos   -mach=<name>             Set the H8300 machine type to one of:\n\
2202440a403fSchristos                            h8300h, h8300hn, h8300s, h8300sn, h8300sx, h8300sxn\n"));
2203440a403fSchristos   fprintf (stream, _("\
2204440a403fSchristos   -h-tick-hex              Support H'00 style hex constants\n"));
2205440a403fSchristos }
2206440a403fSchristos 
2207440a403fSchristos void tc_aout_fix_to_chars (void);
2208440a403fSchristos 
2209440a403fSchristos void
tc_aout_fix_to_chars(void)2210440a403fSchristos tc_aout_fix_to_chars (void)
2211440a403fSchristos {
2212440a403fSchristos   printf (_("call to tc_aout_fix_to_chars \n"));
2213440a403fSchristos   abort ();
2214440a403fSchristos }
2215440a403fSchristos 
2216440a403fSchristos void
md_convert_frag(bfd * headers ATTRIBUTE_UNUSED,segT seg ATTRIBUTE_UNUSED,fragS * fragP ATTRIBUTE_UNUSED)2217440a403fSchristos md_convert_frag (bfd *headers ATTRIBUTE_UNUSED,
2218440a403fSchristos 		 segT seg ATTRIBUTE_UNUSED,
2219440a403fSchristos 		 fragS *fragP ATTRIBUTE_UNUSED)
2220440a403fSchristos {
2221440a403fSchristos   printf (_("call to md_convert_frag \n"));
2222440a403fSchristos   abort ();
2223440a403fSchristos }
2224440a403fSchristos 
2225440a403fSchristos valueT
md_section_align(segT segment,valueT size)2226440a403fSchristos md_section_align (segT segment, valueT size)
2227440a403fSchristos {
2228*b88e3e88Schristos   int align = bfd_section_alignment (segment);
2229440a403fSchristos   return ((size + (1 << align) - 1) & (-1U << align));
2230440a403fSchristos }
2231440a403fSchristos 
2232440a403fSchristos void
md_apply_fix(fixS * fixP,valueT * valP,segT seg ATTRIBUTE_UNUSED)2233440a403fSchristos md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
2234440a403fSchristos {
2235440a403fSchristos   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
2236440a403fSchristos   long val = *valP;
2237440a403fSchristos 
2238440a403fSchristos   switch (fixP->fx_size)
2239440a403fSchristos     {
2240440a403fSchristos     case 1:
2241440a403fSchristos       *buf++ = val;
2242440a403fSchristos       break;
2243440a403fSchristos     case 2:
2244440a403fSchristos       *buf++ = (val >> 8);
2245440a403fSchristos       *buf++ = val;
2246440a403fSchristos       break;
2247440a403fSchristos     case 4:
2248440a403fSchristos       *buf++ = (val >> 24);
2249440a403fSchristos       *buf++ = (val >> 16);
2250440a403fSchristos       *buf++ = (val >> 8);
2251440a403fSchristos       *buf++ = val;
2252440a403fSchristos       break;
2253440a403fSchristos     case 8:
2254440a403fSchristos       /* This can arise when the .quad or .8byte pseudo-ops are used.
2255440a403fSchristos 	 Returning here (without setting fx_done) will cause the code
2256440a403fSchristos 	 to attempt to generate a reloc which will then fail with the
2257440a403fSchristos 	 slightly more helpful error message: "Cannot represent
2258440a403fSchristos 	 relocation type BFD_RELOC_64".  */
2259440a403fSchristos       return;
2260440a403fSchristos     default:
2261440a403fSchristos       abort ();
2262440a403fSchristos     }
2263440a403fSchristos 
2264440a403fSchristos   if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
2265440a403fSchristos     fixP->fx_done = 1;
2266440a403fSchristos }
2267440a403fSchristos 
2268440a403fSchristos int
md_estimate_size_before_relax(fragS * fragP ATTRIBUTE_UNUSED,segT segment_type ATTRIBUTE_UNUSED)2269440a403fSchristos md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
2270440a403fSchristos 			       segT segment_type ATTRIBUTE_UNUSED)
2271440a403fSchristos {
2272440a403fSchristos   printf (_("call to md_estimate_size_before_relax \n"));
2273440a403fSchristos   abort ();
2274440a403fSchristos }
2275440a403fSchristos 
2276440a403fSchristos /* Put number into target byte order.  */
2277440a403fSchristos void
md_number_to_chars(char * ptr,valueT use,int nbytes)2278440a403fSchristos md_number_to_chars (char *ptr, valueT use, int nbytes)
2279440a403fSchristos {
2280440a403fSchristos   number_to_chars_bigendian (ptr, use, nbytes);
2281440a403fSchristos }
2282440a403fSchristos 
2283440a403fSchristos long
md_pcrel_from(fixS * fixp)2284440a403fSchristos md_pcrel_from (fixS *fixp)
2285440a403fSchristos {
2286440a403fSchristos   as_bad_where (fixp->fx_file, fixp->fx_line,
2287440a403fSchristos 		_("Unexpected reference to a symbol in a non-code section"));
2288440a403fSchristos   return 0;
2289440a403fSchristos }
2290440a403fSchristos 
2291440a403fSchristos arelent *
tc_gen_reloc(asection * section ATTRIBUTE_UNUSED,fixS * fixp)2292440a403fSchristos tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixp)
2293440a403fSchristos {
2294440a403fSchristos   arelent *rel;
2295440a403fSchristos   bfd_reloc_code_real_type r_type;
2296440a403fSchristos 
2297440a403fSchristos   if (fixp->fx_addsy && fixp->fx_subsy)
2298440a403fSchristos     {
2299440a403fSchristos       if ((S_GET_SEGMENT (fixp->fx_addsy) != S_GET_SEGMENT (fixp->fx_subsy))
2300440a403fSchristos 	  || S_GET_SEGMENT (fixp->fx_addsy) == undefined_section)
2301440a403fSchristos 	{
2302440a403fSchristos 	  as_bad_where (fixp->fx_file, fixp->fx_line,
2303440a403fSchristos 			_("Difference of symbols in different sections is not supported"));
2304440a403fSchristos 	  return NULL;
2305440a403fSchristos 	}
2306440a403fSchristos     }
2307440a403fSchristos 
2308440a403fSchristos   rel = XNEW (arelent);
2309440a403fSchristos   rel->sym_ptr_ptr = XNEW (asymbol *);
2310440a403fSchristos   *rel->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
2311440a403fSchristos   rel->address = fixp->fx_frag->fr_address + fixp->fx_where;
2312440a403fSchristos   rel->addend = fixp->fx_offset;
2313440a403fSchristos 
2314440a403fSchristos   r_type = fixp->fx_r_type;
2315440a403fSchristos 
2316440a403fSchristos #define DEBUG 0
2317440a403fSchristos #if DEBUG
2318440a403fSchristos   fprintf (stderr, "%s\n", bfd_get_reloc_code_name (r_type));
2319440a403fSchristos   fflush (stderr);
2320440a403fSchristos #endif
2321440a403fSchristos   rel->howto = bfd_reloc_type_lookup (stdoutput, r_type);
2322440a403fSchristos   if (rel->howto == NULL)
2323440a403fSchristos     {
2324440a403fSchristos       as_bad_where (fixp->fx_file, fixp->fx_line,
2325440a403fSchristos 		    _("Cannot represent relocation type %s"),
2326440a403fSchristos 		    bfd_get_reloc_code_name (r_type));
2327440a403fSchristos       return NULL;
2328440a403fSchristos     }
2329440a403fSchristos 
2330440a403fSchristos   return rel;
2331440a403fSchristos }
2332