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