1 | /* tc-m68hc11.c -- Assembler code for the Motorola 68HC11 & 68HC12.
|
---|
2 | Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
---|
3 | Written by Stephane Carrez (stcarrez@nerim.fr)
|
---|
4 |
|
---|
5 | This file is part of GAS, the GNU Assembler.
|
---|
6 |
|
---|
7 | GAS is free software; you can redistribute it and/or modify
|
---|
8 | it under the terms of the GNU General Public License as published by
|
---|
9 | the Free Software Foundation; either version 2, or (at your option)
|
---|
10 | any later version.
|
---|
11 |
|
---|
12 | GAS is distributed in the hope that it will be useful,
|
---|
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
15 | GNU General Public License for more details.
|
---|
16 |
|
---|
17 | You should have received a copy of the GNU General Public License
|
---|
18 | along with GAS; see the file COPYING. If not, write to
|
---|
19 | the Free Software Foundation, 59 Temple Place - Suite 330,
|
---|
20 | Boston, MA 02111-1307, USA. */
|
---|
21 |
|
---|
22 | #include "as.h"
|
---|
23 | #include "safe-ctype.h"
|
---|
24 | #include "subsegs.h"
|
---|
25 | #include "opcode/m68hc11.h"
|
---|
26 | #include "dwarf2dbg.h"
|
---|
27 | #include "elf/m68hc11.h"
|
---|
28 |
|
---|
29 | const char comment_chars[] = ";!";
|
---|
30 | const char line_comment_chars[] = "#*";
|
---|
31 | const char line_separator_chars[] = "";
|
---|
32 |
|
---|
33 | const char EXP_CHARS[] = "eE";
|
---|
34 | const char FLT_CHARS[] = "dD";
|
---|
35 |
|
---|
36 | #define STATE_CONDITIONAL_BRANCH (1)
|
---|
37 | #define STATE_PC_RELATIVE (2)
|
---|
38 | #define STATE_INDEXED_OFFSET (3)
|
---|
39 | #define STATE_INDEXED_PCREL (4)
|
---|
40 | #define STATE_XBCC_BRANCH (5)
|
---|
41 | #define STATE_CONDITIONAL_BRANCH_6812 (6)
|
---|
42 |
|
---|
43 | #define STATE_BYTE (0)
|
---|
44 | #define STATE_BITS5 (0)
|
---|
45 | #define STATE_WORD (1)
|
---|
46 | #define STATE_BITS9 (1)
|
---|
47 | #define STATE_LONG (2)
|
---|
48 | #define STATE_BITS16 (2)
|
---|
49 | #define STATE_UNDF (3) /* Symbol undefined in pass1 */
|
---|
50 |
|
---|
51 | /* This macro has no side-effects. */
|
---|
52 | #define ENCODE_RELAX(what,length) (((what) << 2) + (length))
|
---|
53 | #define RELAX_STATE(s) ((s) >> 2)
|
---|
54 | #define RELAX_LENGTH(s) ((s) & 3)
|
---|
55 |
|
---|
56 | #define IS_OPCODE(C1,C2) (((C1) & 0x0FF) == ((C2) & 0x0FF))
|
---|
57 |
|
---|
58 | /* This table describes how you change sizes for the various types of variable
|
---|
59 | size expressions. This version only supports two kinds. */
|
---|
60 |
|
---|
61 | /* The fields are:
|
---|
62 | How far Forward this mode will reach.
|
---|
63 | How far Backward this mode will reach.
|
---|
64 | How many bytes this mode will add to the size of the frag.
|
---|
65 | Which mode to go to if the offset won't fit in this one. */
|
---|
66 |
|
---|
67 | relax_typeS md_relax_table[] = {
|
---|
68 | {1, 1, 0, 0}, /* First entries aren't used. */
|
---|
69 | {1, 1, 0, 0}, /* For no good reason except. */
|
---|
70 | {1, 1, 0, 0}, /* that the VAX doesn't either. */
|
---|
71 | {1, 1, 0, 0},
|
---|
72 |
|
---|
73 | /* Relax for bcc <L>.
|
---|
74 | These insns are translated into b!cc +3 jmp L. */
|
---|
75 | {(127), (-128), 0, ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_WORD)},
|
---|
76 | {0, 0, 3, 0},
|
---|
77 | {1, 1, 0, 0},
|
---|
78 | {1, 1, 0, 0},
|
---|
79 |
|
---|
80 | /* Relax for bsr <L> and bra <L>.
|
---|
81 | These insns are translated into jsr and jmp. */
|
---|
82 | {(127), (-128), 0, ENCODE_RELAX (STATE_PC_RELATIVE, STATE_WORD)},
|
---|
83 | {0, 0, 1, 0},
|
---|
84 | {1, 1, 0, 0},
|
---|
85 | {1, 1, 0, 0},
|
---|
86 |
|
---|
87 | /* Relax for indexed offset: 5-bits, 9-bits, 16-bits. */
|
---|
88 | {(15), (-16), 0, ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS9)},
|
---|
89 | {(255), (-256), 1, ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS16)},
|
---|
90 | {0, 0, 2, 0},
|
---|
91 | {1, 1, 0, 0},
|
---|
92 |
|
---|
93 | /* Relax for PC relative offset: 5-bits, 9-bits, 16-bits.
|
---|
94 | For the 9-bit case, there will be a -1 correction to take into
|
---|
95 | account the new byte that's why the range is -255..256. */
|
---|
96 | {(15), (-16), 0, ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS9)},
|
---|
97 | {(256), (-255), 1, ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS16)},
|
---|
98 | {0, 0, 2, 0},
|
---|
99 | {1, 1, 0, 0},
|
---|
100 |
|
---|
101 | /* Relax for dbeq/ibeq/tbeq r,<L>:
|
---|
102 | These insns are translated into db!cc +3 jmp L. */
|
---|
103 | {(255), (-256), 0, ENCODE_RELAX (STATE_XBCC_BRANCH, STATE_WORD)},
|
---|
104 | {0, 0, 3, 0},
|
---|
105 | {1, 1, 0, 0},
|
---|
106 | {1, 1, 0, 0},
|
---|
107 |
|
---|
108 | /* Relax for bcc <L> on 68HC12.
|
---|
109 | These insns are translated into lbcc <L>. */
|
---|
110 | {(127), (-128), 0, ENCODE_RELAX (STATE_CONDITIONAL_BRANCH_6812, STATE_WORD)},
|
---|
111 | {0, 0, 2, 0},
|
---|
112 | {1, 1, 0, 0},
|
---|
113 | {1, 1, 0, 0},
|
---|
114 |
|
---|
115 | };
|
---|
116 |
|
---|
117 | /* 68HC11 and 68HC12 registers. They are numbered according to the 68HC12. */
|
---|
118 | typedef enum register_id {
|
---|
119 | REG_NONE = -1,
|
---|
120 | REG_A = 0,
|
---|
121 | REG_B = 1,
|
---|
122 | REG_CCR = 2,
|
---|
123 | REG_D = 4,
|
---|
124 | REG_X = 5,
|
---|
125 | REG_Y = 6,
|
---|
126 | REG_SP = 7,
|
---|
127 | REG_PC = 8
|
---|
128 | } register_id;
|
---|
129 |
|
---|
130 | typedef struct operand {
|
---|
131 | expressionS exp;
|
---|
132 | register_id reg1;
|
---|
133 | register_id reg2;
|
---|
134 | int mode;
|
---|
135 | } operand;
|
---|
136 |
|
---|
137 | struct m68hc11_opcode_def {
|
---|
138 | long format;
|
---|
139 | int min_operands;
|
---|
140 | int max_operands;
|
---|
141 | int nb_modes;
|
---|
142 | int used;
|
---|
143 | struct m68hc11_opcode *opcode;
|
---|
144 | };
|
---|
145 |
|
---|
146 | static struct m68hc11_opcode_def *m68hc11_opcode_defs = 0;
|
---|
147 | static int m68hc11_nb_opcode_defs = 0;
|
---|
148 |
|
---|
149 | typedef struct alias {
|
---|
150 | const char *name;
|
---|
151 | const char *alias;
|
---|
152 | } alias;
|
---|
153 |
|
---|
154 | static alias alias_opcodes[] = {
|
---|
155 | {"cpd", "cmpd"},
|
---|
156 | {"cpx", "cmpx"},
|
---|
157 | {"cpy", "cmpy"},
|
---|
158 | {0, 0}
|
---|
159 | };
|
---|
160 |
|
---|
161 | /* Local functions. */
|
---|
162 | static register_id reg_name_search PARAMS ((char *));
|
---|
163 | static register_id register_name PARAMS ((void));
|
---|
164 | static int cmp_opcode PARAMS ((struct m68hc11_opcode *,
|
---|
165 | struct m68hc11_opcode *));
|
---|
166 | static char *print_opcode_format PARAMS ((struct m68hc11_opcode *, int));
|
---|
167 | static char *skip_whites PARAMS ((char *));
|
---|
168 | static int check_range PARAMS ((long, int));
|
---|
169 | static void print_opcode_list PARAMS ((void));
|
---|
170 | static void get_default_target PARAMS ((void));
|
---|
171 | static void print_insn_format PARAMS ((char *));
|
---|
172 | static int get_operand PARAMS ((operand *, int, long));
|
---|
173 | static void fixup8 PARAMS ((expressionS *, int, int));
|
---|
174 | static void fixup16 PARAMS ((expressionS *, int, int));
|
---|
175 | static void fixup24 PARAMS ((expressionS *, int, int));
|
---|
176 | static unsigned char convert_branch PARAMS ((unsigned char));
|
---|
177 | static char *m68hc11_new_insn PARAMS ((int));
|
---|
178 | static void build_dbranch_insn PARAMS ((struct m68hc11_opcode *,
|
---|
179 | operand *, int, int));
|
---|
180 | static int build_indexed_byte PARAMS ((operand *, int, int));
|
---|
181 | static int build_reg_mode PARAMS ((operand *, int));
|
---|
182 |
|
---|
183 | static struct m68hc11_opcode *find
|
---|
184 | PARAMS ((struct m68hc11_opcode_def *, operand *, int));
|
---|
185 | static struct m68hc11_opcode *find_opcode
|
---|
186 | PARAMS ((struct m68hc11_opcode_def *, operand *, int *));
|
---|
187 | static void build_jump_insn
|
---|
188 | PARAMS ((struct m68hc11_opcode *, operand *, int, int));
|
---|
189 | static void build_insn
|
---|
190 | PARAMS ((struct m68hc11_opcode *, operand *, int));
|
---|
191 | static int relaxable_symbol PARAMS ((symbolS *));
|
---|
192 |
|
---|
193 | /* Pseudo op to indicate a relax group. */
|
---|
194 | static void s_m68hc11_relax PARAMS((int));
|
---|
195 |
|
---|
196 | /* Pseudo op to control the ELF flags. */
|
---|
197 | static void s_m68hc11_mode PARAMS ((int));
|
---|
198 |
|
---|
199 | /* Mark the symbols with STO_M68HC12_FAR to indicate the functions
|
---|
200 | are using 'rtc' for returning. It is necessary to use 'call'
|
---|
201 | to invoke them. This is also used by the debugger to correctly
|
---|
202 | find the stack frame. */
|
---|
203 | static void s_m68hc11_mark_symbol PARAMS ((int));
|
---|
204 |
|
---|
205 | /* Controls whether relative branches can be turned into long branches.
|
---|
206 | When the relative offset is too large, the insn are changed:
|
---|
207 | bra -> jmp
|
---|
208 | bsr -> jsr
|
---|
209 | bcc -> b!cc +3
|
---|
210 | jmp L
|
---|
211 | dbcc -> db!cc +3
|
---|
212 | jmp L
|
---|
213 |
|
---|
214 | Setting the flag forbidds this. */
|
---|
215 | static short flag_fixed_branchs = 0;
|
---|
216 |
|
---|
217 | /* Force to use long jumps (absolute) instead of relative branches. */
|
---|
218 | static short flag_force_long_jumps = 0;
|
---|
219 |
|
---|
220 | /* Change the direct addressing mode into an absolute addressing mode
|
---|
221 | when the insn does not support direct addressing.
|
---|
222 | For example, "clr *ZD0" is normally not possible and is changed
|
---|
223 | into "clr ZDO". */
|
---|
224 | static short flag_strict_direct_addressing = 1;
|
---|
225 |
|
---|
226 | /* When an opcode has invalid operand, print out the syntax of the opcode
|
---|
227 | to stderr. */
|
---|
228 | static short flag_print_insn_syntax = 0;
|
---|
229 |
|
---|
230 | /* Dumps the list of instructions with syntax and then exit:
|
---|
231 | 1 -> Only dumps the list (sorted by name)
|
---|
232 | 2 -> Generate an example (or test) that can be compiled. */
|
---|
233 | static short flag_print_opcodes = 0;
|
---|
234 |
|
---|
235 | /* Opcode hash table. */
|
---|
236 | static struct hash_control *m68hc11_hash;
|
---|
237 |
|
---|
238 | /* Current cpu (either cpu6811 or cpu6812). This is determined automagically
|
---|
239 | by 'get_default_target' by looking at default BFD vector. This is overriden
|
---|
240 | with the -m<cpu> option. */
|
---|
241 | static int current_architecture = 0;
|
---|
242 |
|
---|
243 | /* Default cpu determined by 'get_default_target'. */
|
---|
244 | static const char *default_cpu;
|
---|
245 |
|
---|
246 | /* Number of opcodes in the sorted table (filtered by current cpu). */
|
---|
247 | static int num_opcodes;
|
---|
248 |
|
---|
249 | /* The opcodes sorted by name and filtered by current cpu. */
|
---|
250 | static struct m68hc11_opcode *m68hc11_sorted_opcodes;
|
---|
251 |
|
---|
252 | /* ELF flags to set in the output file header. */
|
---|
253 | static int elf_flags = E_M68HC11_F64;
|
---|
254 |
|
---|
255 | /* These are the machine dependent pseudo-ops. These are included so
|
---|
256 | the assembler can work on the output from the SUN C compiler, which
|
---|
257 | generates these. */
|
---|
258 |
|
---|
259 | /* This table describes all the machine specific pseudo-ops the assembler
|
---|
260 | has to support. The fields are:
|
---|
261 | pseudo-op name without dot
|
---|
262 | function to call to execute this pseudo-op
|
---|
263 | Integer arg to pass to the function. */
|
---|
264 | const pseudo_typeS md_pseudo_table[] = {
|
---|
265 | /* The following pseudo-ops are supported for MRI compatibility. */
|
---|
266 | {"fcb", cons, 1},
|
---|
267 | {"fdb", cons, 2},
|
---|
268 | {"fcc", stringer, 1},
|
---|
269 | {"rmb", s_space, 0},
|
---|
270 |
|
---|
271 | /* Dwarf2 support for Gcc. */
|
---|
272 | {"file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0},
|
---|
273 | {"loc", dwarf2_directive_loc, 0},
|
---|
274 |
|
---|
275 | /* Motorola ALIS. */
|
---|
276 | {"xrefb", s_ignore, 0}, /* Same as xref */
|
---|
277 |
|
---|
278 | /* Gcc driven relaxation. */
|
---|
279 | {"relax", s_m68hc11_relax, 0},
|
---|
280 |
|
---|
281 | /* .mode instruction (ala SH). */
|
---|
282 | {"mode", s_m68hc11_mode, 0},
|
---|
283 |
|
---|
284 | /* .far instruction. */
|
---|
285 | {"far", s_m68hc11_mark_symbol, STO_M68HC12_FAR},
|
---|
286 |
|
---|
287 | /* .interrupt instruction. */
|
---|
288 | {"interrupt", s_m68hc11_mark_symbol, STO_M68HC12_INTERRUPT},
|
---|
289 |
|
---|
290 | {0, 0, 0}
|
---|
291 | };
|
---|
292 | |
---|
293 |
|
---|
294 | /* Options and initialization. */
|
---|
295 |
|
---|
296 | const char *md_shortopts = "Sm:";
|
---|
297 |
|
---|
298 | struct option md_longopts[] = {
|
---|
299 | #define OPTION_FORCE_LONG_BRANCH (OPTION_MD_BASE)
|
---|
300 | {"force-long-branchs", no_argument, NULL, OPTION_FORCE_LONG_BRANCH},
|
---|
301 |
|
---|
302 | #define OPTION_SHORT_BRANCHS (OPTION_MD_BASE + 1)
|
---|
303 | {"short-branchs", no_argument, NULL, OPTION_SHORT_BRANCHS},
|
---|
304 |
|
---|
305 | #define OPTION_STRICT_DIRECT_MODE (OPTION_MD_BASE + 2)
|
---|
306 | {"strict-direct-mode", no_argument, NULL, OPTION_STRICT_DIRECT_MODE},
|
---|
307 |
|
---|
308 | #define OPTION_PRINT_INSN_SYNTAX (OPTION_MD_BASE + 3)
|
---|
309 | {"print-insn-syntax", no_argument, NULL, OPTION_PRINT_INSN_SYNTAX},
|
---|
310 |
|
---|
311 | #define OPTION_PRINT_OPCODES (OPTION_MD_BASE + 4)
|
---|
312 | {"print-opcodes", no_argument, NULL, OPTION_PRINT_OPCODES},
|
---|
313 |
|
---|
314 | #define OPTION_GENERATE_EXAMPLE (OPTION_MD_BASE + 5)
|
---|
315 | {"generate-example", no_argument, NULL, OPTION_GENERATE_EXAMPLE},
|
---|
316 |
|
---|
317 | #define OPTION_MSHORT (OPTION_MD_BASE + 6)
|
---|
318 | {"mshort", no_argument, NULL, OPTION_MSHORT},
|
---|
319 |
|
---|
320 | #define OPTION_MLONG (OPTION_MD_BASE + 7)
|
---|
321 | {"mlong", no_argument, NULL, OPTION_MLONG},
|
---|
322 |
|
---|
323 | #define OPTION_MSHORT_DOUBLE (OPTION_MD_BASE + 8)
|
---|
324 | {"mshort-double", no_argument, NULL, OPTION_MSHORT_DOUBLE},
|
---|
325 |
|
---|
326 | #define OPTION_MLONG_DOUBLE (OPTION_MD_BASE + 9)
|
---|
327 | {"mlong-double", no_argument, NULL, OPTION_MLONG_DOUBLE},
|
---|
328 |
|
---|
329 | {NULL, no_argument, NULL, 0}
|
---|
330 | };
|
---|
331 | size_t md_longopts_size = sizeof (md_longopts);
|
---|
332 |
|
---|
333 | /* Get the target cpu for the assembler. This is based on the configure
|
---|
334 | options and on the -m68hc11/-m68hc12 option. If no option is specified,
|
---|
335 | we must get the default. */
|
---|
336 | const char *
|
---|
337 | m68hc11_arch_format ()
|
---|
338 | {
|
---|
339 | get_default_target ();
|
---|
340 | if (current_architecture & cpu6811)
|
---|
341 | return "elf32-m68hc11";
|
---|
342 | else
|
---|
343 | return "elf32-m68hc12";
|
---|
344 | }
|
---|
345 |
|
---|
346 | enum bfd_architecture
|
---|
347 | m68hc11_arch ()
|
---|
348 | {
|
---|
349 | get_default_target ();
|
---|
350 | if (current_architecture & cpu6811)
|
---|
351 | return bfd_arch_m68hc11;
|
---|
352 | else
|
---|
353 | return bfd_arch_m68hc12;
|
---|
354 | }
|
---|
355 |
|
---|
356 | int
|
---|
357 | m68hc11_mach ()
|
---|
358 | {
|
---|
359 | return 0;
|
---|
360 | }
|
---|
361 |
|
---|
362 | /* Listing header selected according to cpu. */
|
---|
363 | const char *
|
---|
364 | m68hc11_listing_header ()
|
---|
365 | {
|
---|
366 | if (current_architecture & cpu6811)
|
---|
367 | return "M68HC11 GAS ";
|
---|
368 | else
|
---|
369 | return "M68HC12 GAS ";
|
---|
370 | }
|
---|
371 |
|
---|
372 | void
|
---|
373 | md_show_usage (stream)
|
---|
374 | FILE *stream;
|
---|
375 | {
|
---|
376 | get_default_target ();
|
---|
377 | fprintf (stream, _("\
|
---|
378 | Motorola 68HC11/68HC12/68HCS12 options:\n\
|
---|
379 | -m68hc11 | -m68hc12 |\n\
|
---|
380 | -m68hcs12 specify the processor [default %s]\n\
|
---|
381 | -mshort use 16-bit int ABI (default)\n\
|
---|
382 | -mlong use 32-bit int ABI\n\
|
---|
383 | -mshort-double use 32-bit double ABI\n\
|
---|
384 | -mlong-double use 64-bit double ABI (default)\n\
|
---|
385 | --force-long-branchs always turn relative branchs into absolute ones\n\
|
---|
386 | -S,--short-branchs do not turn relative branchs into absolute ones\n\
|
---|
387 | when the offset is out of range\n\
|
---|
388 | --strict-direct-mode do not turn the direct mode into extended mode\n\
|
---|
389 | when the instruction does not support direct mode\n\
|
---|
390 | --print-insn-syntax print the syntax of instruction in case of error\n\
|
---|
391 | --print-opcodes print the list of instructions with syntax\n\
|
---|
392 | --generate-example generate an example of each instruction\n\
|
---|
393 | (used for testing)\n"), default_cpu);
|
---|
394 |
|
---|
395 | }
|
---|
396 |
|
---|
397 | /* Try to identify the default target based on the BFD library. */
|
---|
398 | static void
|
---|
399 | get_default_target ()
|
---|
400 | {
|
---|
401 | const bfd_target *target;
|
---|
402 | bfd abfd;
|
---|
403 |
|
---|
404 | if (current_architecture != 0)
|
---|
405 | return;
|
---|
406 |
|
---|
407 | default_cpu = "unknown";
|
---|
408 | target = bfd_find_target (0, &abfd);
|
---|
409 | if (target && target->name)
|
---|
410 | {
|
---|
411 | if (strcmp (target->name, "elf32-m68hc12") == 0)
|
---|
412 | {
|
---|
413 | current_architecture = cpu6812;
|
---|
414 | default_cpu = "m68hc12";
|
---|
415 | }
|
---|
416 | else if (strcmp (target->name, "elf32-m68hc11") == 0)
|
---|
417 | {
|
---|
418 | current_architecture = cpu6811;
|
---|
419 | default_cpu = "m68hc11";
|
---|
420 | }
|
---|
421 | else
|
---|
422 | {
|
---|
423 | as_bad (_("Default target `%s' is not supported."), target->name);
|
---|
424 | }
|
---|
425 | }
|
---|
426 | }
|
---|
427 |
|
---|
428 | void
|
---|
429 | m68hc11_print_statistics (file)
|
---|
430 | FILE *file;
|
---|
431 | {
|
---|
432 | int i;
|
---|
433 | struct m68hc11_opcode_def *opc;
|
---|
434 |
|
---|
435 | hash_print_statistics (file, "opcode table", m68hc11_hash);
|
---|
436 |
|
---|
437 | opc = m68hc11_opcode_defs;
|
---|
438 | if (opc == 0 || m68hc11_nb_opcode_defs == 0)
|
---|
439 | return;
|
---|
440 |
|
---|
441 | /* Dump the opcode statistics table. */
|
---|
442 | fprintf (file, _("Name # Modes Min ops Max ops Modes mask # Used\n"));
|
---|
443 | for (i = 0; i < m68hc11_nb_opcode_defs; i++, opc++)
|
---|
444 | {
|
---|
445 | fprintf (file, "%-7.7s %5d %7d %7d 0x%08lx %7d\n",
|
---|
446 | opc->opcode->name,
|
---|
447 | opc->nb_modes,
|
---|
448 | opc->min_operands, opc->max_operands, opc->format, opc->used);
|
---|
449 | }
|
---|
450 | }
|
---|
451 |
|
---|
452 | int
|
---|
453 | md_parse_option (c, arg)
|
---|
454 | int c;
|
---|
455 | char *arg;
|
---|
456 | {
|
---|
457 | get_default_target ();
|
---|
458 | switch (c)
|
---|
459 | {
|
---|
460 | /* -S means keep external to 2 bit offset rather than 16 bit one. */
|
---|
461 | case OPTION_SHORT_BRANCHS:
|
---|
462 | case 'S':
|
---|
463 | flag_fixed_branchs = 1;
|
---|
464 | break;
|
---|
465 |
|
---|
466 | case OPTION_FORCE_LONG_BRANCH:
|
---|
467 | flag_force_long_jumps = 1;
|
---|
468 | break;
|
---|
469 |
|
---|
470 | case OPTION_PRINT_INSN_SYNTAX:
|
---|
471 | flag_print_insn_syntax = 1;
|
---|
472 | break;
|
---|
473 |
|
---|
474 | case OPTION_PRINT_OPCODES:
|
---|
475 | flag_print_opcodes = 1;
|
---|
476 | break;
|
---|
477 |
|
---|
478 | case OPTION_STRICT_DIRECT_MODE:
|
---|
479 | flag_strict_direct_addressing = 0;
|
---|
480 | break;
|
---|
481 |
|
---|
482 | case OPTION_GENERATE_EXAMPLE:
|
---|
483 | flag_print_opcodes = 2;
|
---|
484 | break;
|
---|
485 |
|
---|
486 | case OPTION_MSHORT:
|
---|
487 | elf_flags &= ~E_M68HC11_I32;
|
---|
488 | break;
|
---|
489 |
|
---|
490 | case OPTION_MLONG:
|
---|
491 | elf_flags |= E_M68HC11_I32;
|
---|
492 | break;
|
---|
493 |
|
---|
494 | case OPTION_MSHORT_DOUBLE:
|
---|
495 | elf_flags &= ~E_M68HC11_F64;
|
---|
496 | break;
|
---|
497 |
|
---|
498 | case OPTION_MLONG_DOUBLE:
|
---|
499 | elf_flags |= E_M68HC11_F64;
|
---|
500 | break;
|
---|
501 |
|
---|
502 | case 'm':
|
---|
503 | if (strcasecmp (arg, "68hc11") == 0)
|
---|
504 | current_architecture = cpu6811;
|
---|
505 | else if (strcasecmp (arg, "68hc12") == 0)
|
---|
506 | current_architecture = cpu6812;
|
---|
507 | else if (strcasecmp (arg, "68hcs12") == 0)
|
---|
508 | current_architecture = cpu6812 | cpu6812s;
|
---|
509 | else
|
---|
510 | as_bad (_("Option `%s' is not recognized."), arg);
|
---|
511 | break;
|
---|
512 |
|
---|
513 | default:
|
---|
514 | return 0;
|
---|
515 | }
|
---|
516 |
|
---|
517 | return 1;
|
---|
518 | }
|
---|
519 | |
---|
520 |
|
---|
521 | symbolS *
|
---|
522 | md_undefined_symbol (name)
|
---|
523 | char *name ATTRIBUTE_UNUSED;
|
---|
524 | {
|
---|
525 | return 0;
|
---|
526 | }
|
---|
527 |
|
---|
528 | /* Equal to MAX_PRECISION in atof-ieee.c. */
|
---|
529 | #define MAX_LITTLENUMS 6
|
---|
530 |
|
---|
531 | /* Turn a string in input_line_pointer into a floating point constant
|
---|
532 | of type TYPE, and store the appropriate bytes in *LITP. The number
|
---|
533 | of LITTLENUMS emitted is stored in *SIZEP. An error message is
|
---|
534 | returned, or NULL on OK. */
|
---|
535 | char *
|
---|
536 | md_atof (type, litP, sizeP)
|
---|
537 | char type;
|
---|
538 | char *litP;
|
---|
539 | int *sizeP;
|
---|
540 | {
|
---|
541 | int prec;
|
---|
542 | LITTLENUM_TYPE words[MAX_LITTLENUMS];
|
---|
543 | LITTLENUM_TYPE *wordP;
|
---|
544 | char *t;
|
---|
545 |
|
---|
546 | switch (type)
|
---|
547 | {
|
---|
548 | case 'f':
|
---|
549 | case 'F':
|
---|
550 | case 's':
|
---|
551 | case 'S':
|
---|
552 | prec = 2;
|
---|
553 | break;
|
---|
554 |
|
---|
555 | case 'd':
|
---|
556 | case 'D':
|
---|
557 | case 'r':
|
---|
558 | case 'R':
|
---|
559 | prec = 4;
|
---|
560 | break;
|
---|
561 |
|
---|
562 | case 'x':
|
---|
563 | case 'X':
|
---|
564 | prec = 6;
|
---|
565 | break;
|
---|
566 |
|
---|
567 | case 'p':
|
---|
568 | case 'P':
|
---|
569 | prec = 6;
|
---|
570 | break;
|
---|
571 |
|
---|
572 | default:
|
---|
573 | *sizeP = 0;
|
---|
574 | return _("Bad call to MD_ATOF()");
|
---|
575 | }
|
---|
576 | t = atof_ieee (input_line_pointer, type, words);
|
---|
577 | if (t)
|
---|
578 | input_line_pointer = t;
|
---|
579 |
|
---|
580 | *sizeP = prec * sizeof (LITTLENUM_TYPE);
|
---|
581 | for (wordP = words; prec--;)
|
---|
582 | {
|
---|
583 | md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
|
---|
584 | litP += sizeof (LITTLENUM_TYPE);
|
---|
585 | }
|
---|
586 | return 0;
|
---|
587 | }
|
---|
588 |
|
---|
589 | valueT
|
---|
590 | md_section_align (seg, addr)
|
---|
591 | asection *seg;
|
---|
592 | valueT addr;
|
---|
593 | {
|
---|
594 | int align = bfd_get_section_alignment (stdoutput, seg);
|
---|
595 | return ((addr + (1 << align) - 1) & (-1 << align));
|
---|
596 | }
|
---|
597 |
|
---|
598 | static int
|
---|
599 | cmp_opcode (op1, op2)
|
---|
600 | struct m68hc11_opcode *op1;
|
---|
601 | struct m68hc11_opcode *op2;
|
---|
602 | {
|
---|
603 | return strcmp (op1->name, op2->name);
|
---|
604 | }
|
---|
605 |
|
---|
606 | #define IS_CALL_SYMBOL(MODE) \
|
---|
607 | (((MODE) & (M6812_OP_PAGE|M6811_OP_IND16)) \
|
---|
608 | == ((M6812_OP_PAGE|M6811_OP_IND16)))
|
---|
609 |
|
---|
610 | /* Initialize the assembler. Create the opcode hash table
|
---|
611 | (sorted on the names) with the M6811 opcode table
|
---|
612 | (from opcode library). */
|
---|
613 | void
|
---|
614 | md_begin ()
|
---|
615 | {
|
---|
616 | char *prev_name = "";
|
---|
617 | struct m68hc11_opcode *opcodes;
|
---|
618 | struct m68hc11_opcode_def *opc = 0;
|
---|
619 | int i, j;
|
---|
620 |
|
---|
621 | get_default_target ();
|
---|
622 |
|
---|
623 | m68hc11_hash = hash_new ();
|
---|
624 |
|
---|
625 | /* Get a writable copy of the opcode table and sort it on the names. */
|
---|
626 | opcodes = (struct m68hc11_opcode *) xmalloc (m68hc11_num_opcodes *
|
---|
627 | sizeof (struct
|
---|
628 | m68hc11_opcode));
|
---|
629 | m68hc11_sorted_opcodes = opcodes;
|
---|
630 | num_opcodes = 0;
|
---|
631 | for (i = 0; i < m68hc11_num_opcodes; i++)
|
---|
632 | {
|
---|
633 | if (m68hc11_opcodes[i].arch & current_architecture)
|
---|
634 | {
|
---|
635 | opcodes[num_opcodes] = m68hc11_opcodes[i];
|
---|
636 | if (opcodes[num_opcodes].name[0] == 'b'
|
---|
637 | && opcodes[num_opcodes].format & M6811_OP_JUMP_REL
|
---|
638 | && !(opcodes[num_opcodes].format & M6811_OP_BITMASK))
|
---|
639 | {
|
---|
640 | num_opcodes++;
|
---|
641 | opcodes[num_opcodes] = m68hc11_opcodes[i];
|
---|
642 | }
|
---|
643 | num_opcodes++;
|
---|
644 | for (j = 0; alias_opcodes[j].name != 0; j++)
|
---|
645 | if (strcmp (m68hc11_opcodes[i].name, alias_opcodes[j].name) == 0)
|
---|
646 | {
|
---|
647 | opcodes[num_opcodes] = m68hc11_opcodes[i];
|
---|
648 | opcodes[num_opcodes].name = alias_opcodes[j].alias;
|
---|
649 | num_opcodes++;
|
---|
650 | break;
|
---|
651 | }
|
---|
652 | }
|
---|
653 | }
|
---|
654 | qsort (opcodes, num_opcodes, sizeof (struct m68hc11_opcode),
|
---|
655 | (int (*) PARAMS ((const PTR, const PTR))) cmp_opcode);
|
---|
656 |
|
---|
657 | opc = (struct m68hc11_opcode_def *)
|
---|
658 | xmalloc (num_opcodes * sizeof (struct m68hc11_opcode_def));
|
---|
659 | m68hc11_opcode_defs = opc--;
|
---|
660 |
|
---|
661 | /* Insert unique names into hash table. The M6811 instruction set
|
---|
662 | has several identical opcode names that have different opcodes based
|
---|
663 | on the operands. This hash table then provides a quick index to
|
---|
664 | the first opcode with a particular name in the opcode table. */
|
---|
665 | for (i = 0; i < num_opcodes; i++, opcodes++)
|
---|
666 | {
|
---|
667 | int expect;
|
---|
668 |
|
---|
669 | if (strcmp (prev_name, opcodes->name))
|
---|
670 | {
|
---|
671 | prev_name = (char *) opcodes->name;
|
---|
672 |
|
---|
673 | opc++;
|
---|
674 | opc->format = 0;
|
---|
675 | opc->min_operands = 100;
|
---|
676 | opc->max_operands = 0;
|
---|
677 | opc->nb_modes = 0;
|
---|
678 | opc->opcode = opcodes;
|
---|
679 | opc->used = 0;
|
---|
680 | hash_insert (m68hc11_hash, opcodes->name, (char *) opc);
|
---|
681 | }
|
---|
682 | opc->nb_modes++;
|
---|
683 | opc->format |= opcodes->format;
|
---|
684 |
|
---|
685 | /* See how many operands this opcode needs. */
|
---|
686 | expect = 0;
|
---|
687 | if (opcodes->format & M6811_OP_MASK)
|
---|
688 | expect++;
|
---|
689 | if (opcodes->format & M6811_OP_BITMASK)
|
---|
690 | expect++;
|
---|
691 | if (opcodes->format & (M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16))
|
---|
692 | expect++;
|
---|
693 | if (opcodes->format & (M6812_OP_IND16_P2 | M6812_OP_IDX_P2))
|
---|
694 | expect++;
|
---|
695 | /* Special case for call instruction. */
|
---|
696 | if ((opcodes->format & M6812_OP_PAGE)
|
---|
697 | && !(opcodes->format & M6811_OP_IND16))
|
---|
698 | expect++;
|
---|
699 |
|
---|
700 | if (expect < opc->min_operands)
|
---|
701 | opc->min_operands = expect;
|
---|
702 | if (IS_CALL_SYMBOL (opcodes->format))
|
---|
703 | expect++;
|
---|
704 | if (expect > opc->max_operands)
|
---|
705 | opc->max_operands = expect;
|
---|
706 | }
|
---|
707 | opc++;
|
---|
708 | m68hc11_nb_opcode_defs = opc - m68hc11_opcode_defs;
|
---|
709 |
|
---|
710 | if (flag_print_opcodes)
|
---|
711 | {
|
---|
712 | print_opcode_list ();
|
---|
713 | exit (EXIT_SUCCESS);
|
---|
714 | }
|
---|
715 | }
|
---|
716 |
|
---|
717 | void
|
---|
718 | m68hc11_init_after_args ()
|
---|
719 | {
|
---|
720 | }
|
---|
721 | |
---|
722 |
|
---|
723 | /* Builtin help. */
|
---|
724 |
|
---|
725 | /* Return a string that represents the operand format for the instruction.
|
---|
726 | When example is true, this generates an example of operand. This is used
|
---|
727 | to give an example and also to generate a test. */
|
---|
728 | static char *
|
---|
729 | print_opcode_format (opcode, example)
|
---|
730 | struct m68hc11_opcode *opcode;
|
---|
731 | int example;
|
---|
732 | {
|
---|
733 | static char buf[128];
|
---|
734 | int format = opcode->format;
|
---|
735 | char *p;
|
---|
736 |
|
---|
737 | p = buf;
|
---|
738 | buf[0] = 0;
|
---|
739 | if (format & M6811_OP_IMM8)
|
---|
740 | {
|
---|
741 | if (example)
|
---|
742 | sprintf (p, "#%d", rand () & 0x0FF);
|
---|
743 | else
|
---|
744 | strcpy (p, _("#<imm8>"));
|
---|
745 | p = &p[strlen (p)];
|
---|
746 | }
|
---|
747 |
|
---|
748 | if (format & M6811_OP_IMM16)
|
---|
749 | {
|
---|
750 | if (example)
|
---|
751 | sprintf (p, "#%d", rand () & 0x0FFFF);
|
---|
752 | else
|
---|
753 | strcpy (p, _("#<imm16>"));
|
---|
754 | p = &p[strlen (p)];
|
---|
755 | }
|
---|
756 |
|
---|
757 | if (format & M6811_OP_IX)
|
---|
758 | {
|
---|
759 | if (example)
|
---|
760 | sprintf (p, "%d,X", rand () & 0x0FF);
|
---|
761 | else
|
---|
762 | strcpy (p, _("<imm8>,X"));
|
---|
763 | p = &p[strlen (p)];
|
---|
764 | }
|
---|
765 |
|
---|
766 | if (format & M6811_OP_IY)
|
---|
767 | {
|
---|
768 | if (example)
|
---|
769 | sprintf (p, "%d,X", rand () & 0x0FF);
|
---|
770 | else
|
---|
771 | strcpy (p, _("<imm8>,X"));
|
---|
772 | p = &p[strlen (p)];
|
---|
773 | }
|
---|
774 |
|
---|
775 | if (format & M6812_OP_IDX)
|
---|
776 | {
|
---|
777 | if (example)
|
---|
778 | sprintf (p, "%d,X", rand () & 0x0FF);
|
---|
779 | else
|
---|
780 | strcpy (p, "n,r");
|
---|
781 | p = &p[strlen (p)];
|
---|
782 | }
|
---|
783 |
|
---|
784 | if (format & M6812_OP_PAGE)
|
---|
785 | {
|
---|
786 | if (example)
|
---|
787 | sprintf (p, ", %d", rand () & 0x0FF);
|
---|
788 | else
|
---|
789 | strcpy (p, ", <page>");
|
---|
790 | p = &p[strlen (p)];
|
---|
791 | }
|
---|
792 |
|
---|
793 | if (format & M6811_OP_DIRECT)
|
---|
794 | {
|
---|
795 | if (example)
|
---|
796 | sprintf (p, "*Z%d", rand () & 0x0FF);
|
---|
797 | else
|
---|
798 | strcpy (p, _("*<abs8>"));
|
---|
799 | p = &p[strlen (p)];
|
---|
800 | }
|
---|
801 |
|
---|
802 | if (format & M6811_OP_BITMASK)
|
---|
803 | {
|
---|
804 | if (buf[0])
|
---|
805 | *p++ = ' ';
|
---|
806 |
|
---|
807 | if (example)
|
---|
808 | sprintf (p, "#$%02x", rand () & 0x0FF);
|
---|
809 | else
|
---|
810 | strcpy (p, _("#<mask>"));
|
---|
811 |
|
---|
812 | p = &p[strlen (p)];
|
---|
813 | if (format & M6811_OP_JUMP_REL)
|
---|
814 | *p++ = ' ';
|
---|
815 | }
|
---|
816 |
|
---|
817 | if (format & M6811_OP_IND16)
|
---|
818 | {
|
---|
819 | if (example)
|
---|
820 | sprintf (p, _("symbol%d"), rand () & 0x0FF);
|
---|
821 | else
|
---|
822 | strcpy (p, _("<abs>"));
|
---|
823 |
|
---|
824 | p = &p[strlen (p)];
|
---|
825 | }
|
---|
826 |
|
---|
827 | if (format & (M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16))
|
---|
828 | {
|
---|
829 | if (example)
|
---|
830 | {
|
---|
831 | if (format & M6811_OP_BITMASK)
|
---|
832 | {
|
---|
833 | sprintf (p, ".+%d", rand () & 0x7F);
|
---|
834 | }
|
---|
835 | else
|
---|
836 | {
|
---|
837 | sprintf (p, "L%d", rand () & 0x0FF);
|
---|
838 | }
|
---|
839 | }
|
---|
840 | else
|
---|
841 | strcpy (p, _("<label>"));
|
---|
842 | }
|
---|
843 |
|
---|
844 | return buf;
|
---|
845 | }
|
---|
846 |
|
---|
847 | /* Prints the list of instructions with the possible operands. */
|
---|
848 | static void
|
---|
849 | print_opcode_list ()
|
---|
850 | {
|
---|
851 | int i;
|
---|
852 | char *prev_name = "";
|
---|
853 | struct m68hc11_opcode *opcodes;
|
---|
854 | int example = flag_print_opcodes == 2;
|
---|
855 |
|
---|
856 | if (example)
|
---|
857 | printf (_("# Example of `%s' instructions\n\t.sect .text\n_start:\n"),
|
---|
858 | default_cpu);
|
---|
859 |
|
---|
860 | opcodes = m68hc11_sorted_opcodes;
|
---|
861 |
|
---|
862 | /* Walk the list sorted on names (by md_begin). We only report
|
---|
863 | one instruction per line, and we collect the different operand
|
---|
864 | formats. */
|
---|
865 | for (i = 0; i < num_opcodes; i++, opcodes++)
|
---|
866 | {
|
---|
867 | char *fmt = print_opcode_format (opcodes, example);
|
---|
868 |
|
---|
869 | if (example)
|
---|
870 | {
|
---|
871 | printf ("L%d:\t", i);
|
---|
872 | printf ("%s %s\n", opcodes->name, fmt);
|
---|
873 | }
|
---|
874 | else
|
---|
875 | {
|
---|
876 | if (strcmp (prev_name, opcodes->name))
|
---|
877 | {
|
---|
878 | if (i > 0)
|
---|
879 | printf ("\n");
|
---|
880 |
|
---|
881 | printf ("%-5.5s ", opcodes->name);
|
---|
882 | prev_name = (char *) opcodes->name;
|
---|
883 | }
|
---|
884 | if (fmt[0])
|
---|
885 | printf (" [%s]", fmt);
|
---|
886 | }
|
---|
887 | }
|
---|
888 | printf ("\n");
|
---|
889 | }
|
---|
890 |
|
---|
891 | /* Print the instruction format. This operation is called when some
|
---|
892 | instruction is not correct. Instruction format is printed as an
|
---|
893 | error message. */
|
---|
894 | static void
|
---|
895 | print_insn_format (name)
|
---|
896 | char *name;
|
---|
897 | {
|
---|
898 | struct m68hc11_opcode_def *opc;
|
---|
899 | struct m68hc11_opcode *opcode;
|
---|
900 | char buf[128];
|
---|
901 |
|
---|
902 | opc = (struct m68hc11_opcode_def *) hash_find (m68hc11_hash, name);
|
---|
903 | if (opc == NULL)
|
---|
904 | {
|
---|
905 | as_bad (_("Instruction `%s' is not recognized."), name);
|
---|
906 | return;
|
---|
907 | }
|
---|
908 | opcode = opc->opcode;
|
---|
909 |
|
---|
910 | as_bad (_("Instruction formats for `%s':"), name);
|
---|
911 | do
|
---|
912 | {
|
---|
913 | char *fmt;
|
---|
914 |
|
---|
915 | fmt = print_opcode_format (opcode, 0);
|
---|
916 | sprintf (buf, "\t%-5.5s %s", opcode->name, fmt);
|
---|
917 |
|
---|
918 | as_bad ("%s", buf);
|
---|
919 | opcode++;
|
---|
920 | }
|
---|
921 | while (strcmp (opcode->name, name) == 0);
|
---|
922 | }
|
---|
923 | |
---|
924 |
|
---|
925 | /* Analysis of 68HC11 and 68HC12 operands. */
|
---|
926 |
|
---|
927 | /* reg_name_search() finds the register number given its name.
|
---|
928 | Returns the register number or REG_NONE on failure. */
|
---|
929 | static register_id
|
---|
930 | reg_name_search (name)
|
---|
931 | char *name;
|
---|
932 | {
|
---|
933 | if (strcasecmp (name, "x") == 0 || strcasecmp (name, "ix") == 0)
|
---|
934 | return REG_X;
|
---|
935 | if (strcasecmp (name, "y") == 0 || strcasecmp (name, "iy") == 0)
|
---|
936 | return REG_Y;
|
---|
937 | if (strcasecmp (name, "a") == 0)
|
---|
938 | return REG_A;
|
---|
939 | if (strcasecmp (name, "b") == 0)
|
---|
940 | return REG_B;
|
---|
941 | if (strcasecmp (name, "d") == 0)
|
---|
942 | return REG_D;
|
---|
943 | if (strcasecmp (name, "sp") == 0)
|
---|
944 | return REG_SP;
|
---|
945 | if (strcasecmp (name, "pc") == 0)
|
---|
946 | return REG_PC;
|
---|
947 | if (strcasecmp (name, "ccr") == 0)
|
---|
948 | return REG_CCR;
|
---|
949 |
|
---|
950 | return REG_NONE;
|
---|
951 | }
|
---|
952 |
|
---|
953 | static char *
|
---|
954 | skip_whites (p)
|
---|
955 | char *p;
|
---|
956 | {
|
---|
957 | while (*p == ' ' || *p == '\t')
|
---|
958 | p++;
|
---|
959 |
|
---|
960 | return p;
|
---|
961 | }
|
---|
962 |
|
---|
963 | /* Check the string at input_line_pointer
|
---|
964 | to see if it is a valid register name. */
|
---|
965 | static register_id
|
---|
966 | register_name ()
|
---|
967 | {
|
---|
968 | register_id reg_number;
|
---|
969 | char c, *p = input_line_pointer;
|
---|
970 |
|
---|
971 | if (!is_name_beginner (*p++))
|
---|
972 | return REG_NONE;
|
---|
973 |
|
---|
974 | while (is_part_of_name (*p++))
|
---|
975 | continue;
|
---|
976 |
|
---|
977 | c = *--p;
|
---|
978 | if (c)
|
---|
979 | *p++ = 0;
|
---|
980 |
|
---|
981 | /* Look to see if it's in the register table. */
|
---|
982 | reg_number = reg_name_search (input_line_pointer);
|
---|
983 | if (reg_number != REG_NONE)
|
---|
984 | {
|
---|
985 | if (c)
|
---|
986 | *--p = c;
|
---|
987 |
|
---|
988 | input_line_pointer = p;
|
---|
989 | return reg_number;
|
---|
990 | }
|
---|
991 | if (c)
|
---|
992 | *--p = c;
|
---|
993 |
|
---|
994 | return reg_number;
|
---|
995 | }
|
---|
996 | #define M6811_OP_CALL_ADDR 0x00800000
|
---|
997 | #define M6811_OP_PAGE_ADDR 0x04000000
|
---|
998 |
|
---|
999 | /* Parse a string of operands and return an array of expressions.
|
---|
1000 |
|
---|
1001 | Operand mode[0] mode[1] exp[0] exp[1]
|
---|
1002 | #n M6811_OP_IMM16 - O_*
|
---|
1003 | *<exp> M6811_OP_DIRECT - O_*
|
---|
1004 | .{+-}<exp> M6811_OP_JUMP_REL - O_*
|
---|
1005 | <exp> M6811_OP_IND16 - O_*
|
---|
1006 | ,r N,r M6812_OP_IDX M6812_OP_REG O_constant O_register
|
---|
1007 | n,-r M6812_PRE_DEC M6812_OP_REG O_constant O_register
|
---|
1008 | n,+r M6812_PRE_INC " "
|
---|
1009 | n,r- M6812_POST_DEC " "
|
---|
1010 | n,r+ M6812_POST_INC " "
|
---|
1011 | A,r B,r D,r M6811_OP_REG M6812_OP_REG O_register O_register
|
---|
1012 | [D,r] M6811_OP_D_IDX M6812_OP_REG O_register O_register
|
---|
1013 | [n,r] M6811_OP_D_IDX_2 M6812_OP_REG O_constant O_register */
|
---|
1014 | static int
|
---|
1015 | get_operand (oper, which, opmode)
|
---|
1016 | operand *oper;
|
---|
1017 | int which;
|
---|
1018 | long opmode;
|
---|
1019 | {
|
---|
1020 | char *p = input_line_pointer;
|
---|
1021 | int mode;
|
---|
1022 | register_id reg;
|
---|
1023 |
|
---|
1024 | oper->exp.X_op = O_absent;
|
---|
1025 | oper->reg1 = REG_NONE;
|
---|
1026 | oper->reg2 = REG_NONE;
|
---|
1027 | mode = M6811_OP_NONE;
|
---|
1028 |
|
---|
1029 | p = skip_whites (p);
|
---|
1030 |
|
---|
1031 | if (*p == 0 || *p == '\n' || *p == '\r')
|
---|
1032 | {
|
---|
1033 | input_line_pointer = p;
|
---|
1034 | return 0;
|
---|
1035 | }
|
---|
1036 |
|
---|
1037 | if (*p == '*' && (opmode & (M6811_OP_DIRECT | M6811_OP_IND16)))
|
---|
1038 | {
|
---|
1039 | mode = M6811_OP_DIRECT;
|
---|
1040 | p++;
|
---|
1041 | }
|
---|
1042 | else if (*p == '#')
|
---|
1043 | {
|
---|
1044 | if (!(opmode & (M6811_OP_IMM8 | M6811_OP_IMM16 | M6811_OP_BITMASK)))
|
---|
1045 | {
|
---|
1046 | as_bad (_("Immediate operand is not allowed for operand %d."),
|
---|
1047 | which);
|
---|
1048 | return -1;
|
---|
1049 | }
|
---|
1050 |
|
---|
1051 | mode = M6811_OP_IMM16;
|
---|
1052 | p++;
|
---|
1053 | if (strncmp (p, "%hi", 3) == 0)
|
---|
1054 | {
|
---|
1055 | p += 3;
|
---|
1056 | mode |= M6811_OP_HIGH_ADDR;
|
---|
1057 | }
|
---|
1058 | else if (strncmp (p, "%lo", 3) == 0)
|
---|
1059 | {
|
---|
1060 | p += 3;
|
---|
1061 | mode |= M6811_OP_LOW_ADDR;
|
---|
1062 | }
|
---|
1063 | /* %page modifier is used to obtain only the page number
|
---|
1064 | of the address of a function. */
|
---|
1065 | else if (strncmp (p, "%page", 5) == 0)
|
---|
1066 | {
|
---|
1067 | p += 5;
|
---|
1068 | mode |= M6811_OP_PAGE_ADDR;
|
---|
1069 | }
|
---|
1070 |
|
---|
1071 | /* %addr modifier is used to obtain the physical address part
|
---|
1072 | of the function (16-bit). For 68HC12 the function will be
|
---|
1073 | mapped in the 16K window at 0x8000 and the value will be
|
---|
1074 | within that window (although the function address may not fit
|
---|
1075 | in 16-bit). See bfd/elf32-m68hc12.c for the translation. */
|
---|
1076 | else if (strncmp (p, "%addr", 5) == 0)
|
---|
1077 | {
|
---|
1078 | p += 5;
|
---|
1079 | mode |= M6811_OP_CALL_ADDR;
|
---|
1080 | }
|
---|
1081 | }
|
---|
1082 | else if (*p == '.' && (p[1] == '+' || p[1] == '-'))
|
---|
1083 | {
|
---|
1084 | p++;
|
---|
1085 | mode = M6811_OP_JUMP_REL;
|
---|
1086 | }
|
---|
1087 | else if (*p == '[')
|
---|
1088 | {
|
---|
1089 | if (current_architecture & cpu6811)
|
---|
1090 | as_bad (_("Indirect indexed addressing is not valid for 68HC11."));
|
---|
1091 |
|
---|
1092 | p++;
|
---|
1093 | mode = M6812_OP_D_IDX;
|
---|
1094 | p = skip_whites (p);
|
---|
1095 | }
|
---|
1096 | else if (*p == ',') /* Special handling of ,x and ,y. */
|
---|
1097 | {
|
---|
1098 | p++;
|
---|
1099 | input_line_pointer = p;
|
---|
1100 |
|
---|
1101 | reg = register_name ();
|
---|
1102 | if (reg != REG_NONE)
|
---|
1103 | {
|
---|
1104 | oper->reg1 = reg;
|
---|
1105 | oper->exp.X_op = O_constant;
|
---|
1106 | oper->exp.X_add_number = 0;
|
---|
1107 | oper->mode = M6812_OP_IDX;
|
---|
1108 | return 1;
|
---|
1109 | }
|
---|
1110 | as_bad (_("Spurious `,' or bad indirect register addressing mode."));
|
---|
1111 | return -1;
|
---|
1112 | }
|
---|
1113 | /* Handle 68HC12 page specification in 'call foo,%page(bar)'. */
|
---|
1114 | else if ((opmode & M6812_OP_PAGE) && strncmp (p, "%page", 5) == 0)
|
---|
1115 | {
|
---|
1116 | p += 5;
|
---|
1117 | mode = M6811_OP_PAGE_ADDR | M6812_OP_PAGE | M6811_OP_IND16;
|
---|
1118 | }
|
---|
1119 | input_line_pointer = p;
|
---|
1120 |
|
---|
1121 | if (mode == M6811_OP_NONE || mode == M6812_OP_D_IDX)
|
---|
1122 | reg = register_name ();
|
---|
1123 | else
|
---|
1124 | reg = REG_NONE;
|
---|
1125 |
|
---|
1126 | if (reg != REG_NONE)
|
---|
1127 | {
|
---|
1128 | p = skip_whites (input_line_pointer);
|
---|
1129 | if (*p == ']' && mode == M6812_OP_D_IDX)
|
---|
1130 | {
|
---|
1131 | as_bad
|
---|
1132 | (_("Missing second register or offset for indexed-indirect mode."));
|
---|
1133 | return -1;
|
---|
1134 | }
|
---|
1135 |
|
---|
1136 | oper->reg1 = reg;
|
---|
1137 | oper->mode = mode | M6812_OP_REG;
|
---|
1138 | if (*p != ',')
|
---|
1139 | {
|
---|
1140 | if (mode == M6812_OP_D_IDX)
|
---|
1141 | {
|
---|
1142 | as_bad (_("Missing second register for indexed-indirect mode."));
|
---|
1143 | return -1;
|
---|
1144 | }
|
---|
1145 | return 1;
|
---|
1146 | }
|
---|
1147 |
|
---|
1148 | p++;
|
---|
1149 | input_line_pointer = p;
|
---|
1150 | reg = register_name ();
|
---|
1151 | if (reg != REG_NONE)
|
---|
1152 | {
|
---|
1153 | p = skip_whites (input_line_pointer);
|
---|
1154 | if (mode == M6812_OP_D_IDX)
|
---|
1155 | {
|
---|
1156 | if (*p != ']')
|
---|
1157 | {
|
---|
1158 | as_bad (_("Missing `]' to close indexed-indirect mode."));
|
---|
1159 | return -1;
|
---|
1160 | }
|
---|
1161 | p++;
|
---|
1162 | oper->mode = M6812_OP_D_IDX;
|
---|
1163 | }
|
---|
1164 | input_line_pointer = p;
|
---|
1165 |
|
---|
1166 | oper->reg2 = reg;
|
---|
1167 | return 1;
|
---|
1168 | }
|
---|
1169 | return 1;
|
---|
1170 | }
|
---|
1171 |
|
---|
1172 | /* In MRI mode, isolate the operand because we can't distinguish
|
---|
1173 | operands from comments. */
|
---|
1174 | if (flag_mri)
|
---|
1175 | {
|
---|
1176 | char c = 0;
|
---|
1177 |
|
---|
1178 | p = skip_whites (p);
|
---|
1179 | while (*p && *p != ' ' && *p != '\t')
|
---|
1180 | p++;
|
---|
1181 |
|
---|
1182 | if (*p)
|
---|
1183 | {
|
---|
1184 | c = *p;
|
---|
1185 | *p = 0;
|
---|
1186 | }
|
---|
1187 |
|
---|
1188 | /* Parse as an expression. */
|
---|
1189 | expression (&oper->exp);
|
---|
1190 |
|
---|
1191 | if (c)
|
---|
1192 | {
|
---|
1193 | *p = c;
|
---|
1194 | }
|
---|
1195 | }
|
---|
1196 | else
|
---|
1197 | {
|
---|
1198 | expression (&oper->exp);
|
---|
1199 | }
|
---|
1200 |
|
---|
1201 | if (oper->exp.X_op == O_illegal)
|
---|
1202 | {
|
---|
1203 | as_bad (_("Illegal operand."));
|
---|
1204 | return -1;
|
---|
1205 | }
|
---|
1206 | else if (oper->exp.X_op == O_absent)
|
---|
1207 | {
|
---|
1208 | as_bad (_("Missing operand."));
|
---|
1209 | return -1;
|
---|
1210 | }
|
---|
1211 |
|
---|
1212 | p = input_line_pointer;
|
---|
1213 |
|
---|
1214 | if (mode == M6811_OP_NONE || mode == M6811_OP_DIRECT
|
---|
1215 | || mode == M6812_OP_D_IDX)
|
---|
1216 | {
|
---|
1217 | p = skip_whites (input_line_pointer);
|
---|
1218 |
|
---|
1219 | if (*p == ',')
|
---|
1220 | {
|
---|
1221 | int possible_mode = M6811_OP_NONE;
|
---|
1222 | char *old_input_line;
|
---|
1223 |
|
---|
1224 | old_input_line = p;
|
---|
1225 | p++;
|
---|
1226 |
|
---|
1227 | /* 68HC12 pre increment or decrement. */
|
---|
1228 | if (mode == M6811_OP_NONE)
|
---|
1229 | {
|
---|
1230 | if (*p == '-')
|
---|
1231 | {
|
---|
1232 | possible_mode = M6812_PRE_DEC;
|
---|
1233 | p++;
|
---|
1234 | }
|
---|
1235 | else if (*p == '+')
|
---|
1236 | {
|
---|
1237 | possible_mode = M6812_PRE_INC;
|
---|
1238 | p++;
|
---|
1239 | }
|
---|
1240 | p = skip_whites (p);
|
---|
1241 | }
|
---|
1242 | input_line_pointer = p;
|
---|
1243 | reg = register_name ();
|
---|
1244 |
|
---|
1245 | /* Backtrack if we have a valid constant expression and
|
---|
1246 | it does not correspond to the offset of the 68HC12 indexed
|
---|
1247 | addressing mode (as in N,x). */
|
---|
1248 | if (reg == REG_NONE && mode == M6811_OP_NONE
|
---|
1249 | && possible_mode != M6811_OP_NONE)
|
---|
1250 | {
|
---|
1251 | oper->mode = M6811_OP_IND16 | M6811_OP_JUMP_REL;
|
---|
1252 | input_line_pointer = skip_whites (old_input_line);
|
---|
1253 | return 1;
|
---|
1254 | }
|
---|
1255 |
|
---|
1256 | if (possible_mode != M6811_OP_NONE)
|
---|
1257 | mode = possible_mode;
|
---|
1258 |
|
---|
1259 | if ((current_architecture & cpu6811)
|
---|
1260 | && possible_mode != M6811_OP_NONE)
|
---|
1261 | as_bad (_("Pre-increment mode is not valid for 68HC11"));
|
---|
1262 | /* Backtrack. */
|
---|
1263 | if (which == 0 && opmode & M6812_OP_IDX_P2
|
---|
1264 | && reg != REG_X && reg != REG_Y
|
---|
1265 | && reg != REG_PC && reg != REG_SP)
|
---|
1266 | {
|
---|
1267 | reg = REG_NONE;
|
---|
1268 | input_line_pointer = p;
|
---|
1269 | }
|
---|
1270 |
|
---|
1271 | if (reg == REG_NONE && mode != M6811_OP_DIRECT
|
---|
1272 | && !(mode == M6811_OP_NONE && opmode & M6811_OP_IND16))
|
---|
1273 | {
|
---|
1274 | as_bad (_("Wrong register in register indirect mode."));
|
---|
1275 | return -1;
|
---|
1276 | }
|
---|
1277 | if (mode == M6812_OP_D_IDX)
|
---|
1278 | {
|
---|
1279 | p = skip_whites (input_line_pointer);
|
---|
1280 | if (*p++ != ']')
|
---|
1281 | {
|
---|
1282 | as_bad (_("Missing `]' to close register indirect operand."));
|
---|
1283 | return -1;
|
---|
1284 | }
|
---|
1285 | input_line_pointer = p;
|
---|
1286 | oper->reg1 = reg;
|
---|
1287 | oper->mode = M6812_OP_D_IDX_2;
|
---|
1288 | return 1;
|
---|
1289 | }
|
---|
1290 | if (reg != REG_NONE)
|
---|
1291 | {
|
---|
1292 | oper->reg1 = reg;
|
---|
1293 | if (mode == M6811_OP_NONE)
|
---|
1294 | {
|
---|
1295 | p = input_line_pointer;
|
---|
1296 | if (*p == '-')
|
---|
1297 | {
|
---|
1298 | mode = M6812_POST_DEC;
|
---|
1299 | p++;
|
---|
1300 | if (current_architecture & cpu6811)
|
---|
1301 | as_bad
|
---|
1302 | (_("Post-decrement mode is not valid for 68HC11."));
|
---|
1303 | }
|
---|
1304 | else if (*p == '+')
|
---|
1305 | {
|
---|
1306 | mode = M6812_POST_INC;
|
---|
1307 | p++;
|
---|
1308 | if (current_architecture & cpu6811)
|
---|
1309 | as_bad
|
---|
1310 | (_("Post-increment mode is not valid for 68HC11."));
|
---|
1311 | }
|
---|
1312 | else
|
---|
1313 | mode = M6812_OP_IDX;
|
---|
1314 |
|
---|
1315 | input_line_pointer = p;
|
---|
1316 | }
|
---|
1317 | else
|
---|
1318 | mode |= M6812_OP_IDX;
|
---|
1319 |
|
---|
1320 | oper->mode = mode;
|
---|
1321 | return 1;
|
---|
1322 | }
|
---|
1323 | input_line_pointer = old_input_line;
|
---|
1324 | }
|
---|
1325 |
|
---|
1326 | if (mode == M6812_OP_D_IDX_2)
|
---|
1327 | {
|
---|
1328 | as_bad (_("Invalid indexed indirect mode."));
|
---|
1329 | return -1;
|
---|
1330 | }
|
---|
1331 | }
|
---|
1332 |
|
---|
1333 | /* If the mode is not known until now, this is either a label
|
---|
1334 | or an indirect address. */
|
---|
1335 | if (mode == M6811_OP_NONE)
|
---|
1336 | mode = M6811_OP_IND16 | M6811_OP_JUMP_REL;
|
---|
1337 |
|
---|
1338 | p = input_line_pointer;
|
---|
1339 | while (*p == ' ' || *p == '\t')
|
---|
1340 | p++;
|
---|
1341 | input_line_pointer = p;
|
---|
1342 | oper->mode = mode;
|
---|
1343 |
|
---|
1344 | return 1;
|
---|
1345 | }
|
---|
1346 |
|
---|
1347 | #define M6812_AUTO_INC_DEC (M6812_PRE_INC | M6812_PRE_DEC \
|
---|
1348 | | M6812_POST_INC | M6812_POST_DEC)
|
---|
1349 |
|
---|
1350 | /* Checks that the number 'num' fits for a given mode. */
|
---|
1351 | static int
|
---|
1352 | check_range (num, mode)
|
---|
1353 | long num;
|
---|
1354 | int mode;
|
---|
1355 | {
|
---|
1356 | /* Auto increment and decrement are ok for [-8..8] without 0. */
|
---|
1357 | if (mode & M6812_AUTO_INC_DEC)
|
---|
1358 | return (num != 0 && num <= 8 && num >= -8);
|
---|
1359 |
|
---|
1360 | /* The 68HC12 supports 5, 9 and 16-bit offsets. */
|
---|
1361 | if (mode & (M6812_INDEXED_IND | M6812_INDEXED | M6812_OP_IDX))
|
---|
1362 | mode = M6811_OP_IND16;
|
---|
1363 |
|
---|
1364 | if (mode & M6812_OP_JUMP_REL16)
|
---|
1365 | mode = M6811_OP_IND16;
|
---|
1366 |
|
---|
1367 | mode &= ~M6811_OP_BRANCH;
|
---|
1368 | switch (mode)
|
---|
1369 | {
|
---|
1370 | case M6811_OP_IX:
|
---|
1371 | case M6811_OP_IY:
|
---|
1372 | case M6811_OP_DIRECT:
|
---|
1373 | return (num >= 0 && num <= 255) ? 1 : 0;
|
---|
1374 |
|
---|
1375 | case M6811_OP_BITMASK:
|
---|
1376 | case M6811_OP_IMM8:
|
---|
1377 | case M6812_OP_PAGE:
|
---|
1378 | return (((num & 0xFFFFFF00) == 0) || ((num & 0xFFFFFF00) == 0xFFFFFF00))
|
---|
1379 | ? 1 : 0;
|
---|
1380 |
|
---|
1381 | case M6811_OP_JUMP_REL:
|
---|
1382 | return (num >= -128 && num <= 127) ? 1 : 0;
|
---|
1383 |
|
---|
1384 | case M6811_OP_IND16:
|
---|
1385 | case M6811_OP_IND16 | M6812_OP_PAGE:
|
---|
1386 | case M6811_OP_IMM16:
|
---|
1387 | return (((num & 0xFFFF0000) == 0) || ((num & 0xFFFF0000) == 0xFFFF0000))
|
---|
1388 | ? 1 : 0;
|
---|
1389 |
|
---|
1390 | case M6812_OP_IBCC_MARKER:
|
---|
1391 | case M6812_OP_TBCC_MARKER:
|
---|
1392 | case M6812_OP_DBCC_MARKER:
|
---|
1393 | return (num >= -256 && num <= 255) ? 1 : 0;
|
---|
1394 |
|
---|
1395 | case M6812_OP_TRAP_ID:
|
---|
1396 | return ((num >= 0x30 && num <= 0x39)
|
---|
1397 | || (num >= 0x40 && num <= 0x0ff)) ? 1 : 0;
|
---|
1398 |
|
---|
1399 | default:
|
---|
1400 | return 0;
|
---|
1401 | }
|
---|
1402 | }
|
---|
1403 | |
---|
1404 |
|
---|
1405 | /* Gas fixup generation. */
|
---|
1406 |
|
---|
1407 | /* Put a 1 byte expression described by 'oper'. If this expression contains
|
---|
1408 | unresolved symbols, generate an 8-bit fixup. */
|
---|
1409 | static void
|
---|
1410 | fixup8 (oper, mode, opmode)
|
---|
1411 | expressionS *oper;
|
---|
1412 | int mode;
|
---|
1413 | int opmode;
|
---|
1414 | {
|
---|
1415 | char *f;
|
---|
1416 |
|
---|
1417 | f = frag_more (1);
|
---|
1418 |
|
---|
1419 | if (oper->X_op == O_constant)
|
---|
1420 | {
|
---|
1421 | if (mode & M6812_OP_TRAP_ID
|
---|
1422 | && !check_range (oper->X_add_number, M6812_OP_TRAP_ID))
|
---|
1423 | {
|
---|
1424 | static char trap_id_warn_once = 0;
|
---|
1425 |
|
---|
1426 | as_bad (_("Trap id `%ld' is out of range."), oper->X_add_number);
|
---|
1427 | if (trap_id_warn_once == 0)
|
---|
1428 | {
|
---|
1429 | trap_id_warn_once = 1;
|
---|
1430 | as_bad (_("Trap id must be within [0x30..0x39] or [0x40..0xff]."));
|
---|
1431 | }
|
---|
1432 | }
|
---|
1433 |
|
---|
1434 | if (!(mode & M6812_OP_TRAP_ID)
|
---|
1435 | && !check_range (oper->X_add_number, mode))
|
---|
1436 | {
|
---|
1437 | as_bad (_("Operand out of 8-bit range: `%ld'."), oper->X_add_number);
|
---|
1438 | }
|
---|
1439 | number_to_chars_bigendian (f, oper->X_add_number & 0x0FF, 1);
|
---|
1440 | }
|
---|
1441 | else if (oper->X_op != O_register)
|
---|
1442 | {
|
---|
1443 | if (mode & M6812_OP_TRAP_ID)
|
---|
1444 | as_bad (_("The trap id must be a constant."));
|
---|
1445 |
|
---|
1446 | if (mode == M6811_OP_JUMP_REL)
|
---|
1447 | {
|
---|
1448 | fixS *fixp;
|
---|
1449 |
|
---|
1450 | fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 1,
|
---|
1451 | oper, TRUE, BFD_RELOC_8_PCREL);
|
---|
1452 | fixp->fx_pcrel_adjust = 1;
|
---|
1453 | }
|
---|
1454 | else
|
---|
1455 | {
|
---|
1456 | fixS *fixp;
|
---|
1457 | int reloc;
|
---|
1458 |
|
---|
1459 | /* Now create an 8-bit fixup. If there was some %hi, %lo
|
---|
1460 | or %page modifier, generate the reloc accordingly. */
|
---|
1461 | if (opmode & M6811_OP_HIGH_ADDR)
|
---|
1462 | reloc = BFD_RELOC_M68HC11_HI8;
|
---|
1463 | else if (opmode & M6811_OP_LOW_ADDR)
|
---|
1464 | reloc = BFD_RELOC_M68HC11_LO8;
|
---|
1465 | else if (opmode & M6811_OP_PAGE_ADDR)
|
---|
1466 | reloc = BFD_RELOC_M68HC11_PAGE;
|
---|
1467 | else
|
---|
1468 | reloc = BFD_RELOC_8;
|
---|
1469 |
|
---|
1470 | fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 1,
|
---|
1471 | oper, FALSE, reloc);
|
---|
1472 | if (reloc != BFD_RELOC_8)
|
---|
1473 | fixp->fx_no_overflow = 1;
|
---|
1474 | }
|
---|
1475 | number_to_chars_bigendian (f, 0, 1);
|
---|
1476 | }
|
---|
1477 | else
|
---|
1478 | {
|
---|
1479 | as_fatal (_("Operand `%x' not recognized in fixup8."), oper->X_op);
|
---|
1480 | }
|
---|
1481 | }
|
---|
1482 |
|
---|
1483 | /* Put a 2 byte expression described by 'oper'. If this expression contains
|
---|
1484 | unresolved symbols, generate a 16-bit fixup. */
|
---|
1485 | static void
|
---|
1486 | fixup16 (oper, mode, opmode)
|
---|
1487 | expressionS *oper;
|
---|
1488 | int mode;
|
---|
1489 | int opmode ATTRIBUTE_UNUSED;
|
---|
1490 | {
|
---|
1491 | char *f;
|
---|
1492 |
|
---|
1493 | f = frag_more (2);
|
---|
1494 |
|
---|
1495 | if (oper->X_op == O_constant)
|
---|
1496 | {
|
---|
1497 | if (!check_range (oper->X_add_number, mode))
|
---|
1498 | {
|
---|
1499 | as_bad (_("Operand out of 16-bit range: `%ld'."),
|
---|
1500 | oper->X_add_number);
|
---|
1501 | }
|
---|
1502 | number_to_chars_bigendian (f, oper->X_add_number & 0x0FFFF, 2);
|
---|
1503 | }
|
---|
1504 | else if (oper->X_op != O_register)
|
---|
1505 | {
|
---|
1506 | fixS *fixp;
|
---|
1507 | int reloc;
|
---|
1508 |
|
---|
1509 | if ((opmode & M6811_OP_CALL_ADDR) && (mode & M6811_OP_IMM16))
|
---|
1510 | reloc = BFD_RELOC_M68HC11_LO16;
|
---|
1511 | else if (mode & M6812_OP_JUMP_REL16)
|
---|
1512 | reloc = BFD_RELOC_16_PCREL;
|
---|
1513 | else if (mode & M6812_OP_PAGE)
|
---|
1514 | reloc = BFD_RELOC_M68HC11_LO16;
|
---|
1515 | else
|
---|
1516 | reloc = BFD_RELOC_16;
|
---|
1517 |
|
---|
1518 | /* Now create a 16-bit fixup. */
|
---|
1519 | fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 2,
|
---|
1520 | oper,
|
---|
1521 | reloc == BFD_RELOC_16_PCREL,
|
---|
1522 | reloc);
|
---|
1523 | number_to_chars_bigendian (f, 0, 2);
|
---|
1524 | if (reloc == BFD_RELOC_16_PCREL)
|
---|
1525 | fixp->fx_pcrel_adjust = 2;
|
---|
1526 | if (reloc == BFD_RELOC_M68HC11_LO16)
|
---|
1527 | fixp->fx_no_overflow = 1;
|
---|
1528 | }
|
---|
1529 | else
|
---|
1530 | {
|
---|
1531 | as_fatal (_("Operand `%x' not recognized in fixup16."), oper->X_op);
|
---|
1532 | }
|
---|
1533 | }
|
---|
1534 |
|
---|
1535 | /* Put a 3 byte expression described by 'oper'. If this expression contains
|
---|
1536 | unresolved symbols, generate a 24-bit fixup. */
|
---|
1537 | static void
|
---|
1538 | fixup24 (oper, mode, opmode)
|
---|
1539 | expressionS *oper;
|
---|
1540 | int mode;
|
---|
1541 | int opmode ATTRIBUTE_UNUSED;
|
---|
1542 | {
|
---|
1543 | char *f;
|
---|
1544 |
|
---|
1545 | f = frag_more (3);
|
---|
1546 |
|
---|
1547 | if (oper->X_op == O_constant)
|
---|
1548 | {
|
---|
1549 | if (!check_range (oper->X_add_number, mode))
|
---|
1550 | {
|
---|
1551 | as_bad (_("Operand out of 16-bit range: `%ld'."),
|
---|
1552 | oper->X_add_number);
|
---|
1553 | }
|
---|
1554 | number_to_chars_bigendian (f, oper->X_add_number & 0x0FFFFFF, 3);
|
---|
1555 | }
|
---|
1556 | else if (oper->X_op != O_register)
|
---|
1557 | {
|
---|
1558 | fixS *fixp;
|
---|
1559 |
|
---|
1560 | /* Now create a 24-bit fixup. */
|
---|
1561 | fixp = fix_new_exp (frag_now, f - frag_now->fr_literal, 2,
|
---|
1562 | oper, FALSE, BFD_RELOC_M68HC11_24);
|
---|
1563 | number_to_chars_bigendian (f, 0, 3);
|
---|
1564 | }
|
---|
1565 | else
|
---|
1566 | {
|
---|
1567 | as_fatal (_("Operand `%x' not recognized in fixup16."), oper->X_op);
|
---|
1568 | }
|
---|
1569 | }
|
---|
1570 | |
---|
1571 |
|
---|
1572 | /* 68HC11 and 68HC12 code generation. */
|
---|
1573 |
|
---|
1574 | /* Translate the short branch/bsr instruction into a long branch. */
|
---|
1575 | static unsigned char
|
---|
1576 | convert_branch (code)
|
---|
1577 | unsigned char code;
|
---|
1578 | {
|
---|
1579 | if (IS_OPCODE (code, M6812_BSR))
|
---|
1580 | return M6812_JSR;
|
---|
1581 | else if (IS_OPCODE (code, M6811_BSR))
|
---|
1582 | return M6811_JSR;
|
---|
1583 | else if (IS_OPCODE (code, M6811_BRA))
|
---|
1584 | return (current_architecture & cpu6812) ? M6812_JMP : M6811_JMP;
|
---|
1585 | else
|
---|
1586 | as_fatal (_("Unexpected branch conversion with `%x'"), code);
|
---|
1587 |
|
---|
1588 | /* Keep gcc happy. */
|
---|
1589 | return M6811_JSR;
|
---|
1590 | }
|
---|
1591 |
|
---|
1592 | /* Start a new insn that contains at least 'size' bytes. Record the
|
---|
1593 | line information of that insn in the dwarf2 debug sections. */
|
---|
1594 | static char *
|
---|
1595 | m68hc11_new_insn (size)
|
---|
1596 | int size;
|
---|
1597 | {
|
---|
1598 | char *f;
|
---|
1599 |
|
---|
1600 | f = frag_more (size);
|
---|
1601 |
|
---|
1602 | dwarf2_emit_insn (size);
|
---|
1603 |
|
---|
1604 | return f;
|
---|
1605 | }
|
---|
1606 |
|
---|
1607 | /* Builds a jump instruction (bra, bcc, bsr). */
|
---|
1608 | static void
|
---|
1609 | build_jump_insn (opcode, operands, nb_operands, jmp_mode)
|
---|
1610 | struct m68hc11_opcode *opcode;
|
---|
1611 | operand operands[];
|
---|
1612 | int nb_operands;
|
---|
1613 | int jmp_mode;
|
---|
1614 | {
|
---|
1615 | unsigned char code;
|
---|
1616 | char *f;
|
---|
1617 | unsigned long n;
|
---|
1618 | fragS *frag;
|
---|
1619 | int where;
|
---|
1620 |
|
---|
1621 | /* The relative branch convertion is not supported for
|
---|
1622 | brclr and brset. */
|
---|
1623 | assert ((opcode->format & M6811_OP_BITMASK) == 0);
|
---|
1624 | assert (nb_operands == 1);
|
---|
1625 | assert (operands[0].reg1 == REG_NONE && operands[0].reg2 == REG_NONE);
|
---|
1626 |
|
---|
1627 | code = opcode->opcode;
|
---|
1628 |
|
---|
1629 | n = operands[0].exp.X_add_number;
|
---|
1630 |
|
---|
1631 | /* Turn into a long branch:
|
---|
1632 | - when force long branch option (and not for jbcc pseudos),
|
---|
1633 | - when jbcc and the constant is out of -128..127 range,
|
---|
1634 | - when branch optimization is allowed and branch out of range. */
|
---|
1635 | if ((jmp_mode == 0 && flag_force_long_jumps)
|
---|
1636 | || (operands[0].exp.X_op == O_constant
|
---|
1637 | && (!check_range (n, opcode->format) &&
|
---|
1638 | (jmp_mode == 1 || flag_fixed_branchs == 0))))
|
---|
1639 | {
|
---|
1640 | frag = frag_now;
|
---|
1641 | where = frag_now_fix ();
|
---|
1642 |
|
---|
1643 | fix_new (frag_now, frag_now_fix (), 1,
|
---|
1644 | &abs_symbol, 0, 1, BFD_RELOC_M68HC11_RL_JUMP);
|
---|
1645 |
|
---|
1646 | if (code == M6811_BSR || code == M6811_BRA || code == M6812_BSR)
|
---|
1647 | {
|
---|
1648 | code = convert_branch (code);
|
---|
1649 |
|
---|
1650 | f = m68hc11_new_insn (1);
|
---|
1651 | number_to_chars_bigendian (f, code, 1);
|
---|
1652 | }
|
---|
1653 | else if (current_architecture & cpu6812)
|
---|
1654 | {
|
---|
1655 | /* 68HC12: translate the bcc into a lbcc. */
|
---|
1656 | f = m68hc11_new_insn (2);
|
---|
1657 | number_to_chars_bigendian (f, M6811_OPCODE_PAGE2, 1);
|
---|
1658 | number_to_chars_bigendian (f + 1, code, 1);
|
---|
1659 | fixup16 (&operands[0].exp, M6812_OP_JUMP_REL16,
|
---|
1660 | M6812_OP_JUMP_REL16);
|
---|
1661 | return;
|
---|
1662 | }
|
---|
1663 | else
|
---|
1664 | {
|
---|
1665 | /* 68HC11: translate the bcc into b!cc +3; jmp <L>. */
|
---|
1666 | f = m68hc11_new_insn (3);
|
---|
1667 | code ^= 1;
|
---|
1668 | number_to_chars_bigendian (f, code, 1);
|
---|
1669 | number_to_chars_bigendian (f + 1, 3, 1);
|
---|
1670 | number_to_chars_bigendian (f + 2, M6811_JMP, 1);
|
---|
1671 | }
|
---|
1672 | fixup16 (&operands[0].exp, M6811_OP_IND16, M6811_OP_IND16);
|
---|
1673 | return;
|
---|
1674 | }
|
---|
1675 |
|
---|
1676 | /* Branch with a constant that must fit in 8-bits. */
|
---|
1677 | if (operands[0].exp.X_op == O_constant)
|
---|
1678 | {
|
---|
1679 | if (!check_range (n, opcode->format))
|
---|
1680 | {
|
---|
1681 | as_bad (_("Operand out of range for a relative branch: `%ld'"),
|
---|
1682 | n);
|
---|
1683 | }
|
---|
1684 | else if (opcode->format & M6812_OP_JUMP_REL16)
|
---|
1685 | {
|
---|
1686 | f = m68hc11_new_insn (4);
|
---|
1687 | number_to_chars_bigendian (f, M6811_OPCODE_PAGE2, 1);
|
---|
1688 | number_to_chars_bigendian (f + 1, code, 1);
|
---|
1689 | number_to_chars_bigendian (f + 2, n & 0x0ffff, 2);
|
---|
1690 | }
|
---|
1691 | else
|
---|
1692 | {
|
---|
1693 | f = m68hc11_new_insn (2);
|
---|
1694 | number_to_chars_bigendian (f, code, 1);
|
---|
1695 | number_to_chars_bigendian (f + 1, n & 0x0FF, 1);
|
---|
1696 | }
|
---|
1697 | }
|
---|
1698 | else if (opcode->format & M6812_OP_JUMP_REL16)
|
---|
1699 | {
|
---|
1700 | frag = frag_now;
|
---|
1701 | where = frag_now_fix ();
|
---|
1702 |
|
---|
1703 | fix_new (frag_now, frag_now_fix (), 1,
|
---|
1704 | &abs_symbol, 0, 1, BFD_RELOC_M68HC11_RL_JUMP);
|
---|
1705 |
|
---|
1706 | f = m68hc11_new_insn (2);
|
---|
1707 | number_to_chars_bigendian (f, M6811_OPCODE_PAGE2, 1);
|
---|
1708 | number_to_chars_bigendian (f + 1, code, 1);
|
---|
1709 | fixup16 (&operands[0].exp, M6812_OP_JUMP_REL16, M6812_OP_JUMP_REL16);
|
---|
1710 | }
|
---|
1711 | else
|
---|
1712 | {
|
---|
1713 | char *opcode;
|
---|
1714 |
|
---|
1715 | frag = frag_now;
|
---|
1716 | where = frag_now_fix ();
|
---|
1717 |
|
---|
1718 | fix_new (frag_now, frag_now_fix (), 1,
|
---|
1719 | &abs_symbol, 0, 1, BFD_RELOC_M68HC11_RL_JUMP);
|
---|
1720 |
|
---|
1721 | /* Branch offset must fit in 8-bits, don't do some relax. */
|
---|
1722 | if (jmp_mode == 0 && flag_fixed_branchs)
|
---|
1723 | {
|
---|
1724 | opcode = m68hc11_new_insn (1);
|
---|
1725 | number_to_chars_bigendian (opcode, code, 1);
|
---|
1726 | fixup8 (&operands[0].exp, M6811_OP_JUMP_REL, M6811_OP_JUMP_REL);
|
---|
1727 | }
|
---|
1728 |
|
---|
1729 | /* bra/bsr made be changed into jmp/jsr. */
|
---|
1730 | else if (code == M6811_BSR || code == M6811_BRA || code == M6812_BSR)
|
---|
1731 | {
|
---|
1732 | /* Allocate worst case storage. */
|
---|
1733 | opcode = m68hc11_new_insn (3);
|
---|
1734 | number_to_chars_bigendian (opcode, code, 1);
|
---|
1735 | number_to_chars_bigendian (opcode + 1, 0, 1);
|
---|
1736 | frag_variant (rs_machine_dependent, 1, 1,
|
---|
1737 | ENCODE_RELAX (STATE_PC_RELATIVE, STATE_UNDF),
|
---|
1738 | operands[0].exp.X_add_symbol, (offsetT) n,
|
---|
1739 | opcode);
|
---|
1740 | }
|
---|
1741 | else if (current_architecture & cpu6812)
|
---|
1742 | {
|
---|
1743 | opcode = m68hc11_new_insn (2);
|
---|
1744 | number_to_chars_bigendian (opcode, code, 1);
|
---|
1745 | number_to_chars_bigendian (opcode + 1, 0, 1);
|
---|
1746 | frag_var (rs_machine_dependent, 2, 2,
|
---|
1747 | ENCODE_RELAX (STATE_CONDITIONAL_BRANCH_6812, STATE_UNDF),
|
---|
1748 | operands[0].exp.X_add_symbol, (offsetT) n, opcode);
|
---|
1749 | }
|
---|
1750 | else
|
---|
1751 | {
|
---|
1752 | opcode = m68hc11_new_insn (2);
|
---|
1753 | number_to_chars_bigendian (opcode, code, 1);
|
---|
1754 | number_to_chars_bigendian (opcode + 1, 0, 1);
|
---|
1755 | frag_var (rs_machine_dependent, 3, 3,
|
---|
1756 | ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_UNDF),
|
---|
1757 | operands[0].exp.X_add_symbol, (offsetT) n, opcode);
|
---|
1758 | }
|
---|
1759 | }
|
---|
1760 | }
|
---|
1761 |
|
---|
1762 | /* Builds a dbne/dbeq/tbne/tbeq instruction. */
|
---|
1763 | static void
|
---|
1764 | build_dbranch_insn (opcode, operands, nb_operands, jmp_mode)
|
---|
1765 | struct m68hc11_opcode *opcode;
|
---|
1766 | operand operands[];
|
---|
1767 | int nb_operands;
|
---|
1768 | int jmp_mode;
|
---|
1769 | {
|
---|
1770 | unsigned char code;
|
---|
1771 | char *f;
|
---|
1772 | unsigned long n;
|
---|
1773 |
|
---|
1774 | /* The relative branch convertion is not supported for
|
---|
1775 | brclr and brset. */
|
---|
1776 | assert ((opcode->format & M6811_OP_BITMASK) == 0);
|
---|
1777 | assert (nb_operands == 2);
|
---|
1778 | assert (operands[0].reg1 != REG_NONE);
|
---|
1779 |
|
---|
1780 | code = opcode->opcode & 0x0FF;
|
---|
1781 |
|
---|
1782 | f = m68hc11_new_insn (1);
|
---|
1783 | number_to_chars_bigendian (f, code, 1);
|
---|
1784 |
|
---|
1785 | n = operands[1].exp.X_add_number;
|
---|
1786 | code = operands[0].reg1;
|
---|
1787 |
|
---|
1788 | if (operands[0].reg1 == REG_NONE || operands[0].reg1 == REG_CCR
|
---|
1789 | || operands[0].reg1 == REG_PC)
|
---|
1790 | as_bad (_("Invalid register for dbcc/tbcc instruction."));
|
---|
1791 |
|
---|
1792 | if (opcode->format & M6812_OP_IBCC_MARKER)
|
---|
1793 | code |= 0x80;
|
---|
1794 | else if (opcode->format & M6812_OP_TBCC_MARKER)
|
---|
1795 | code |= 0x40;
|
---|
1796 |
|
---|
1797 | if (!(opcode->format & M6812_OP_EQ_MARKER))
|
---|
1798 | code |= 0x20;
|
---|
1799 |
|
---|
1800 | /* Turn into a long branch:
|
---|
1801 | - when force long branch option (and not for jbcc pseudos),
|
---|
1802 | - when jdbcc and the constant is out of -256..255 range,
|
---|
1803 | - when branch optimization is allowed and branch out of range. */
|
---|
1804 | if ((jmp_mode == 0 && flag_force_long_jumps)
|
---|
1805 | || (operands[1].exp.X_op == O_constant
|
---|
1806 | && (!check_range (n, M6812_OP_IBCC_MARKER) &&
|
---|
1807 | (jmp_mode == 1 || flag_fixed_branchs == 0))))
|
---|
1808 | {
|
---|
1809 | f = frag_more (2);
|
---|
1810 | code ^= 0x20;
|
---|
1811 | number_to_chars_bigendian (f, code, 1);
|
---|
1812 | number_to_chars_bigendian (f + 1, M6812_JMP, 1);
|
---|
1813 | fixup16 (&operands[0].exp, M6811_OP_IND16, M6811_OP_IND16);
|
---|
1814 | return;
|
---|
1815 | }
|
---|
1816 |
|
---|
1817 | /* Branch with a constant that must fit in 9-bits. */
|
---|
1818 | if (operands[1].exp.X_op == O_constant)
|
---|
1819 | {
|
---|
1820 | if (!check_range (n, M6812_OP_IBCC_MARKER))
|
---|
1821 | {
|
---|
1822 | as_bad (_("Operand out of range for a relative branch: `%ld'"),
|
---|
1823 | n);
|
---|
1824 | }
|
---|
1825 | else
|
---|
1826 | {
|
---|
1827 | if ((long) n < 0)
|
---|
1828 | code |= 0x10;
|
---|
1829 |
|
---|
1830 | f = frag_more (2);
|
---|
1831 | number_to_chars_bigendian (f, code, 1);
|
---|
1832 | number_to_chars_bigendian (f + 1, n & 0x0FF, 1);
|
---|
1833 | }
|
---|
1834 | }
|
---|
1835 | else
|
---|
1836 | {
|
---|
1837 | /* Branch offset must fit in 8-bits, don't do some relax. */
|
---|
1838 | if (jmp_mode == 0 && flag_fixed_branchs)
|
---|
1839 | {
|
---|
1840 | fixup8 (&operands[0].exp, M6811_OP_JUMP_REL, M6811_OP_JUMP_REL);
|
---|
1841 | }
|
---|
1842 |
|
---|
1843 | else
|
---|
1844 | {
|
---|
1845 | f = frag_more (2);
|
---|
1846 | number_to_chars_bigendian (f, code, 1);
|
---|
1847 | number_to_chars_bigendian (f + 1, 0, 1);
|
---|
1848 | frag_var (rs_machine_dependent, 3, 3,
|
---|
1849 | ENCODE_RELAX (STATE_XBCC_BRANCH, STATE_UNDF),
|
---|
1850 | operands[1].exp.X_add_symbol, (offsetT) n, f);
|
---|
1851 | }
|
---|
1852 | }
|
---|
1853 | }
|
---|
1854 |
|
---|
1855 | #define OP_EXTENDED (M6811_OP_PAGE2 | M6811_OP_PAGE3 | M6811_OP_PAGE4)
|
---|
1856 |
|
---|
1857 | /* Assemble the post index byte for 68HC12 extended addressing modes. */
|
---|
1858 | static int
|
---|
1859 | build_indexed_byte (op, format, move_insn)
|
---|
1860 | operand *op;
|
---|
1861 | int format ATTRIBUTE_UNUSED;
|
---|
1862 | int move_insn;
|
---|
1863 | {
|
---|
1864 | unsigned char byte = 0;
|
---|
1865 | char *f;
|
---|
1866 | int mode;
|
---|
1867 | long val;
|
---|
1868 |
|
---|
1869 | val = op->exp.X_add_number;
|
---|
1870 | mode = op->mode;
|
---|
1871 | if (mode & M6812_AUTO_INC_DEC)
|
---|
1872 | {
|
---|
1873 | byte = 0x20;
|
---|
1874 | if (mode & (M6812_POST_INC | M6812_POST_DEC))
|
---|
1875 | byte |= 0x10;
|
---|
1876 |
|
---|
1877 | if (op->exp.X_op == O_constant)
|
---|
1878 | {
|
---|
1879 | if (!check_range (val, mode))
|
---|
1880 | {
|
---|
1881 | as_bad (_("Increment/decrement value is out of range: `%ld'."),
|
---|
1882 | val);
|
---|
1883 | }
|
---|
1884 | if (mode & (M6812_POST_INC | M6812_PRE_INC))
|
---|
1885 | byte |= (val - 1) & 0x07;
|
---|
1886 | else
|
---|
1887 | byte |= (8 - ((val) & 7)) | 0x8;
|
---|
1888 | }
|
---|
1889 | switch (op->reg1)
|
---|
1890 | {
|
---|
1891 | case REG_NONE:
|
---|
1892 | as_fatal (_("Expecting a register."));
|
---|
1893 |
|
---|
1894 | case REG_X:
|
---|
1895 | byte |= 0;
|
---|
1896 | break;
|
---|
1897 |
|
---|
1898 | case REG_Y:
|
---|
1899 | byte |= 0x40;
|
---|
1900 | break;
|
---|
1901 |
|
---|
1902 | case REG_SP:
|
---|
1903 | byte |= 0x80;
|
---|
1904 | break;
|
---|
1905 |
|
---|
1906 | default:
|
---|
1907 | as_bad (_("Invalid register for post/pre increment."));
|
---|
1908 | break;
|
---|
1909 | }
|
---|
1910 |
|
---|
1911 | f = frag_more (1);
|
---|
1912 | number_to_chars_bigendian (f, byte, 1);
|
---|
1913 | return 1;
|
---|
1914 | }
|
---|
1915 |
|
---|
1916 | if (mode & (M6812_OP_IDX | M6812_OP_D_IDX_2))
|
---|
1917 | {
|
---|
1918 | switch (op->reg1)
|
---|
1919 | {
|
---|
1920 | case REG_X:
|
---|
1921 | byte = 0;
|
---|
1922 | break;
|
---|
1923 |
|
---|
1924 | case REG_Y:
|
---|
1925 | byte = 1;
|
---|
1926 | break;
|
---|
1927 |
|
---|
1928 | case REG_SP:
|
---|
1929 | byte = 2;
|
---|
1930 | break;
|
---|
1931 |
|
---|
1932 | case REG_PC:
|
---|
1933 | byte = 3;
|
---|
1934 | break;
|
---|
1935 |
|
---|
1936 | default:
|
---|
1937 | as_bad (_("Invalid register."));
|
---|
1938 | break;
|
---|
1939 | }
|
---|
1940 | if (op->exp.X_op == O_constant)
|
---|
1941 | {
|
---|
1942 | if (!check_range (val, M6812_OP_IDX))
|
---|
1943 | {
|
---|
1944 | as_bad (_("Offset out of 16-bit range: %ld."), val);
|
---|
1945 | }
|
---|
1946 |
|
---|
1947 | if (move_insn && !(val >= -16 && val <= 15))
|
---|
1948 | {
|
---|
1949 | as_bad (_("Offset out of 5-bit range for movw/movb insn: %ld."),
|
---|
1950 | val);
|
---|
1951 | return -1;
|
---|
1952 | }
|
---|
1953 |
|
---|
1954 | if (val >= -16 && val <= 15 && !(mode & M6812_OP_D_IDX_2))
|
---|
1955 | {
|
---|
1956 | byte = byte << 6;
|
---|
1957 | byte |= val & 0x1f;
|
---|
1958 | f = frag_more (1);
|
---|
1959 | number_to_chars_bigendian (f, byte, 1);
|
---|
1960 | return 1;
|
---|
1961 | }
|
---|
1962 | else if (val >= -256 && val <= 255 && !(mode & M6812_OP_D_IDX_2))
|
---|
1963 | {
|
---|
1964 | byte = byte << 3;
|
---|
1965 | byte |= 0xe0;
|
---|
1966 | if (val < 0)
|
---|
1967 | byte |= 0x1;
|
---|
1968 | f = frag_more (2);
|
---|
1969 | number_to_chars_bigendian (f, byte, 1);
|
---|
1970 | number_to_chars_bigendian (f + 1, val & 0x0FF, 1);
|
---|
1971 | return 2;
|
---|
1972 | }
|
---|
1973 | else
|
---|
1974 | {
|
---|
1975 | byte = byte << 3;
|
---|
1976 | if (mode & M6812_OP_D_IDX_2)
|
---|
1977 | byte |= 0xe3;
|
---|
1978 | else
|
---|
1979 | byte |= 0xe2;
|
---|
1980 |
|
---|
1981 | f = frag_more (3);
|
---|
1982 | number_to_chars_bigendian (f, byte, 1);
|
---|
1983 | number_to_chars_bigendian (f + 1, val & 0x0FFFF, 2);
|
---|
1984 | return 3;
|
---|
1985 | }
|
---|
1986 | }
|
---|
1987 | if (mode & M6812_OP_D_IDX_2)
|
---|
1988 | {
|
---|
1989 | byte = (byte << 3) | 0xe3;
|
---|
1990 | f = frag_more (1);
|
---|
1991 | number_to_chars_bigendian (f, byte, 1);
|
---|
1992 |
|
---|
1993 | fixup16 (&op->exp, 0, 0);
|
---|
1994 | }
|
---|
1995 | else if (op->reg1 != REG_PC)
|
---|
1996 | {
|
---|
1997 | symbolS *sym;
|
---|
1998 | offsetT off;
|
---|
1999 |
|
---|
2000 | f = frag_more (1);
|
---|
2001 | number_to_chars_bigendian (f, byte, 1);
|
---|
2002 | sym = op->exp.X_add_symbol;
|
---|
2003 | off = op->exp.X_add_number;
|
---|
2004 | if (op->exp.X_op != O_symbol)
|
---|
2005 | {
|
---|
2006 | sym = make_expr_symbol (&op->exp);
|
---|
2007 | off = 0;
|
---|
2008 | }
|
---|
2009 | frag_var (rs_machine_dependent, 2, 2,
|
---|
2010 | ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_UNDF),
|
---|
2011 | sym, off, f);
|
---|
2012 | }
|
---|
2013 | else
|
---|
2014 | {
|
---|
2015 | f = frag_more (1);
|
---|
2016 | number_to_chars_bigendian (f, byte, 1);
|
---|
2017 | frag_var (rs_machine_dependent, 2, 2,
|
---|
2018 | ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_UNDF),
|
---|
2019 | op->exp.X_add_symbol,
|
---|
2020 | op->exp.X_add_number, f);
|
---|
2021 | }
|
---|
2022 | return 3;
|
---|
2023 | }
|
---|
2024 |
|
---|
2025 | if (mode & (M6812_OP_REG | M6812_OP_D_IDX))
|
---|
2026 | {
|
---|
2027 | if (mode & M6812_OP_D_IDX)
|
---|
2028 | {
|
---|
2029 | if (op->reg1 != REG_D)
|
---|
2030 | as_bad (_("Expecting register D for indexed indirect mode."));
|
---|
2031 | if (move_insn)
|
---|
2032 | as_bad (_("Indexed indirect mode is not allowed for movb/movw."));
|
---|
2033 |
|
---|
2034 | byte = 0xE7;
|
---|
2035 | }
|
---|
2036 | else
|
---|
2037 | {
|
---|
2038 | switch (op->reg1)
|
---|
2039 | {
|
---|
2040 | case REG_A:
|
---|
2041 | byte = 0xE4;
|
---|
2042 | break;
|
---|
2043 |
|
---|
2044 | case REG_B:
|
---|
2045 | byte = 0xE5;
|
---|
2046 | break;
|
---|
2047 |
|
---|
2048 | default:
|
---|
2049 | as_bad (_("Invalid accumulator register."));
|
---|
2050 |
|
---|
2051 | case REG_D:
|
---|
2052 | byte = 0xE6;
|
---|
2053 | break;
|
---|
2054 | }
|
---|
2055 | }
|
---|
2056 | switch (op->reg2)
|
---|
2057 | {
|
---|
2058 | case REG_X:
|
---|
2059 | break;
|
---|
2060 |
|
---|
2061 | case REG_Y:
|
---|
2062 | byte |= (1 << 3);
|
---|
2063 | break;
|
---|
2064 |
|
---|
2065 | case REG_SP:
|
---|
2066 | byte |= (2 << 3);
|
---|
2067 | break;
|
---|
2068 |
|
---|
2069 | case REG_PC:
|
---|
2070 | byte |= (3 << 3);
|
---|
2071 | break;
|
---|
2072 |
|
---|
2073 | default:
|
---|
2074 | as_bad (_("Invalid indexed register."));
|
---|
2075 | break;
|
---|
2076 | }
|
---|
2077 | f = frag_more (1);
|
---|
2078 | number_to_chars_bigendian (f, byte, 1);
|
---|
2079 | return 1;
|
---|
2080 | }
|
---|
2081 |
|
---|
2082 | as_fatal (_("Addressing mode not implemented yet."));
|
---|
2083 | return 0;
|
---|
2084 | }
|
---|
2085 |
|
---|
2086 | /* Assemble the 68HC12 register mode byte. */
|
---|
2087 | static int
|
---|
2088 | build_reg_mode (op, format)
|
---|
2089 | operand *op;
|
---|
2090 | int format;
|
---|
2091 | {
|
---|
2092 | unsigned char byte;
|
---|
2093 | char *f;
|
---|
2094 |
|
---|
2095 | if (format & M6812_OP_SEX_MARKER
|
---|
2096 | && op->reg1 != REG_A && op->reg1 != REG_B && op->reg1 != REG_CCR)
|
---|
2097 | as_bad (_("Invalid source register for this instruction, use 'tfr'."));
|
---|
2098 | else if (op->reg1 == REG_NONE || op->reg1 == REG_PC)
|
---|
2099 | as_bad (_("Invalid source register."));
|
---|
2100 |
|
---|
2101 | if (format & M6812_OP_SEX_MARKER
|
---|
2102 | && op->reg2 != REG_D
|
---|
2103 | && op->reg2 != REG_X && op->reg2 != REG_Y && op->reg2 != REG_SP)
|
---|
2104 | as_bad (_("Invalid destination register for this instruction, use 'tfr'."));
|
---|
2105 | else if (op->reg2 == REG_NONE || op->reg2 == REG_PC)
|
---|
2106 | as_bad (_("Invalid destination register."));
|
---|
2107 |
|
---|
2108 | byte = (op->reg1 << 4) | (op->reg2);
|
---|
2109 | if (format & M6812_OP_EXG_MARKER)
|
---|
2110 | byte |= 0x80;
|
---|
2111 |
|
---|
2112 | f = frag_more (1);
|
---|
2113 | number_to_chars_bigendian (f, byte, 1);
|
---|
2114 | return 1;
|
---|
2115 | }
|
---|
2116 |
|
---|
2117 | /* build_insn takes a pointer to the opcode entry in the opcode table,
|
---|
2118 | the array of operand expressions and builds the correspding instruction.
|
---|
2119 | This operation only deals with non relative jumps insn (need special
|
---|
2120 | handling). */
|
---|
2121 | static void
|
---|
2122 | build_insn (opcode, operands, nb_operands)
|
---|
2123 | struct m68hc11_opcode *opcode;
|
---|
2124 | operand operands[];
|
---|
2125 | int nb_operands ATTRIBUTE_UNUSED;
|
---|
2126 | {
|
---|
2127 | int i;
|
---|
2128 | char *f;
|
---|
2129 | long format;
|
---|
2130 | int move_insn = 0;
|
---|
2131 |
|
---|
2132 | /* Put the page code instruction if there is one. */
|
---|
2133 | format = opcode->format;
|
---|
2134 |
|
---|
2135 | if (format & M6811_OP_BRANCH)
|
---|
2136 | fix_new (frag_now, frag_now_fix (), 1,
|
---|
2137 | &abs_symbol, 0, 1, BFD_RELOC_M68HC11_RL_JUMP);
|
---|
2138 |
|
---|
2139 | if (format & OP_EXTENDED)
|
---|
2140 | {
|
---|
2141 | int page_code;
|
---|
2142 |
|
---|
2143 | f = m68hc11_new_insn (2);
|
---|
2144 | if (format & M6811_OP_PAGE2)
|
---|
2145 | page_code = M6811_OPCODE_PAGE2;
|
---|
2146 | else if (format & M6811_OP_PAGE3)
|
---|
2147 | page_code = M6811_OPCODE_PAGE3;
|
---|
2148 | else
|
---|
2149 | page_code = M6811_OPCODE_PAGE4;
|
---|
2150 |
|
---|
2151 | number_to_chars_bigendian (f, page_code, 1);
|
---|
2152 | f++;
|
---|
2153 | }
|
---|
2154 | else
|
---|
2155 | f = m68hc11_new_insn (1);
|
---|
2156 |
|
---|
2157 | number_to_chars_bigendian (f, opcode->opcode, 1);
|
---|
2158 |
|
---|
2159 | i = 0;
|
---|
2160 |
|
---|
2161 | /* The 68HC12 movb and movw instructions are special. We have to handle
|
---|
2162 | them in a special way. */
|
---|
2163 | if (format & (M6812_OP_IND16_P2 | M6812_OP_IDX_P2))
|
---|
2164 | {
|
---|
2165 | move_insn = 1;
|
---|
2166 | if (format & M6812_OP_IDX)
|
---|
2167 | {
|
---|
2168 | build_indexed_byte (&operands[0], format, 1);
|
---|
2169 | i = 1;
|
---|
2170 | format &= ~M6812_OP_IDX;
|
---|
2171 | }
|
---|
2172 | if (format & M6812_OP_IDX_P2)
|
---|
2173 | {
|
---|
2174 | build_indexed_byte (&operands[1], format, 1);
|
---|
2175 | i = 0;
|
---|
2176 | format &= ~M6812_OP_IDX_P2;
|
---|
2177 | }
|
---|
2178 | }
|
---|
2179 |
|
---|
2180 | if (format & (M6811_OP_DIRECT | M6811_OP_IMM8))
|
---|
2181 | {
|
---|
2182 | fixup8 (&operands[i].exp,
|
---|
2183 | format & (M6811_OP_DIRECT | M6811_OP_IMM8 | M6812_OP_TRAP_ID),
|
---|
2184 | operands[i].mode);
|
---|
2185 | i++;
|
---|
2186 | }
|
---|
2187 | else if (IS_CALL_SYMBOL (format) && nb_operands == 1)
|
---|
2188 | {
|
---|
2189 | format &= ~M6812_OP_PAGE;
|
---|
2190 | fixup24 (&operands[i].exp, format & M6811_OP_IND16,
|
---|
2191 | operands[i].mode);
|
---|
2192 | i++;
|
---|
2193 | }
|
---|
2194 | else if (format & (M6811_OP_IMM16 | M6811_OP_IND16))
|
---|
2195 | {
|
---|
2196 | fixup16 (&operands[i].exp,
|
---|
2197 | format & (M6811_OP_IMM16 | M6811_OP_IND16 | M6812_OP_PAGE),
|
---|
2198 | operands[i].mode);
|
---|
2199 | i++;
|
---|
2200 | }
|
---|
2201 | else if (format & (M6811_OP_IX | M6811_OP_IY))
|
---|
2202 | {
|
---|
2203 | if ((format & M6811_OP_IX) && (operands[0].reg1 != REG_X))
|
---|
2204 | as_bad (_("Invalid indexed register, expecting register X."));
|
---|
2205 | if ((format & M6811_OP_IY) && (operands[0].reg1 != REG_Y))
|
---|
2206 | as_bad (_("Invalid indexed register, expecting register Y."));
|
---|
2207 |
|
---|
2208 | fixup8 (&operands[0].exp, M6811_OP_IX, operands[0].mode);
|
---|
2209 | i = 1;
|
---|
2210 | }
|
---|
2211 | else if (format &
|
---|
2212 | (M6812_OP_IDX | M6812_OP_IDX_2 | M6812_OP_IDX_1
|
---|
2213 | | M6812_OP_D_IDX | M6812_OP_D_IDX_2))
|
---|
2214 | {
|
---|
2215 | build_indexed_byte (&operands[i], format, move_insn);
|
---|
2216 | i++;
|
---|
2217 | }
|
---|
2218 | else if (format & M6812_OP_REG && current_architecture & cpu6812)
|
---|
2219 | {
|
---|
2220 | build_reg_mode (&operands[i], format);
|
---|
2221 | i++;
|
---|
2222 | }
|
---|
2223 | if (format & M6811_OP_BITMASK)
|
---|
2224 | {
|
---|
2225 | fixup8 (&operands[i].exp, M6811_OP_BITMASK, operands[i].mode);
|
---|
2226 | i++;
|
---|
2227 | }
|
---|
2228 | if (format & M6811_OP_JUMP_REL)
|
---|
2229 | {
|
---|
2230 | fixup8 (&operands[i].exp, M6811_OP_JUMP_REL, operands[i].mode);
|
---|
2231 | }
|
---|
2232 | else if (format & M6812_OP_IND16_P2)
|
---|
2233 | {
|
---|
2234 | fixup16 (&operands[1].exp, M6811_OP_IND16, operands[1].mode);
|
---|
2235 | }
|
---|
2236 | if (format & M6812_OP_PAGE)
|
---|
2237 | {
|
---|
2238 | fixup8 (&operands[i].exp, M6812_OP_PAGE, operands[i].mode);
|
---|
2239 | }
|
---|
2240 | }
|
---|
2241 | |
---|
2242 |
|
---|
2243 | /* Opcode identification and operand analysis. */
|
---|
2244 |
|
---|
2245 | /* find() gets a pointer to an entry in the opcode table. It must look at all
|
---|
2246 | opcodes with the same name and use the operands to choose the correct
|
---|
2247 | opcode. Returns the opcode pointer if there was a match and 0 if none. */
|
---|
2248 | static struct m68hc11_opcode *
|
---|
2249 | find (opc, operands, nb_operands)
|
---|
2250 | struct m68hc11_opcode_def *opc;
|
---|
2251 | operand operands[];
|
---|
2252 | int nb_operands;
|
---|
2253 | {
|
---|
2254 | int i, match, pos;
|
---|
2255 | struct m68hc11_opcode *opcode;
|
---|
2256 | struct m68hc11_opcode *op_indirect;
|
---|
2257 |
|
---|
2258 | op_indirect = 0;
|
---|
2259 | opcode = opc->opcode;
|
---|
2260 |
|
---|
2261 | /* Now search the opcode table table for one with operands
|
---|
2262 | that matches what we've got. We're only done if the operands matched so
|
---|
2263 | far AND there are no more to check. */
|
---|
2264 | for (pos = match = 0; match == 0 && pos < opc->nb_modes; pos++, opcode++)
|
---|
2265 | {
|
---|
2266 | int poss_indirect = 0;
|
---|
2267 | long format = opcode->format;
|
---|
2268 | int expect;
|
---|
2269 |
|
---|
2270 | expect = 0;
|
---|
2271 | if (opcode->format & M6811_OP_MASK)
|
---|
2272 | expect++;
|
---|
2273 | if (opcode->format & M6811_OP_BITMASK)
|
---|
2274 | expect++;
|
---|
2275 | if (opcode->format & (M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16))
|
---|
2276 | expect++;
|
---|
2277 | if (opcode->format & (M6812_OP_IND16_P2 | M6812_OP_IDX_P2))
|
---|
2278 | expect++;
|
---|
2279 | if ((opcode->format & M6812_OP_PAGE)
|
---|
2280 | && (!IS_CALL_SYMBOL (opcode->format) || nb_operands == 2))
|
---|
2281 | expect++;
|
---|
2282 |
|
---|
2283 | for (i = 0; expect == nb_operands && i < nb_operands; i++)
|
---|
2284 | {
|
---|
2285 | int mode = operands[i].mode;
|
---|
2286 |
|
---|
2287 | if (mode & M6811_OP_IMM16)
|
---|
2288 | {
|
---|
2289 | if (format &
|
---|
2290 | (M6811_OP_IMM8 | M6811_OP_IMM16 | M6811_OP_BITMASK))
|
---|
2291 | continue;
|
---|
2292 | break;
|
---|
2293 | }
|
---|
2294 | if (mode == M6811_OP_DIRECT)
|
---|
2295 | {
|
---|
2296 | if (format & M6811_OP_DIRECT)
|
---|
2297 | continue;
|
---|
2298 |
|
---|
2299 | /* If the operand is a page 0 operand, remember a
|
---|
2300 | possible <abs-16> addressing mode. We mark
|
---|
2301 | this and continue to check other operands. */
|
---|
2302 | if (format & M6811_OP_IND16
|
---|
2303 | && flag_strict_direct_addressing && op_indirect == 0)
|
---|
2304 | {
|
---|
2305 | poss_indirect = 1;
|
---|
2306 | continue;
|
---|
2307 | }
|
---|
2308 | break;
|
---|
2309 | }
|
---|
2310 | if (mode & M6811_OP_IND16)
|
---|
2311 | {
|
---|
2312 | if (i == 0 && (format & M6811_OP_IND16) != 0)
|
---|
2313 | continue;
|
---|
2314 | if (i != 0 && (format & M6812_OP_PAGE) != 0)
|
---|
2315 | continue;
|
---|
2316 | if (i != 0 && (format & M6812_OP_IND16_P2) != 0)
|
---|
2317 | continue;
|
---|
2318 | if (i == 0 && (format & M6811_OP_BITMASK))
|
---|
2319 | break;
|
---|
2320 | }
|
---|
2321 | if (mode & (M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16))
|
---|
2322 | {
|
---|
2323 | if (format & (M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16))
|
---|
2324 | continue;
|
---|
2325 | }
|
---|
2326 | if (mode & M6812_OP_REG)
|
---|
2327 | {
|
---|
2328 | if (i == 0
|
---|
2329 | && (format & M6812_OP_REG)
|
---|
2330 | && (operands[i].reg2 == REG_NONE))
|
---|
2331 | continue;
|
---|
2332 | if (i == 0
|
---|
2333 | && (format & M6812_OP_REG)
|
---|
2334 | && (format & M6812_OP_REG_2)
|
---|
2335 | && (operands[i].reg2 != REG_NONE))
|
---|
2336 | continue;
|
---|
2337 | if (i == 0
|
---|
2338 | && (format & M6812_OP_IDX)
|
---|
2339 | && (operands[i].reg2 != REG_NONE))
|
---|
2340 | continue;
|
---|
2341 | if (i == 0
|
---|
2342 | && (format & M6812_OP_IDX)
|
---|
2343 | && (format & (M6812_OP_IND16_P2 | M6812_OP_IDX_P2)))
|
---|
2344 | continue;
|
---|
2345 | if (i == 1
|
---|
2346 | && (format & M6812_OP_IDX_P2))
|
---|
2347 | continue;
|
---|
2348 | break;
|
---|
2349 | }
|
---|
2350 | if (mode & M6812_OP_IDX)
|
---|
2351 | {
|
---|
2352 | if (format & M6811_OP_IX && operands[i].reg1 == REG_X)
|
---|
2353 | continue;
|
---|
2354 | if (format & M6811_OP_IY && operands[i].reg1 == REG_Y)
|
---|
2355 | continue;
|
---|
2356 | if (i == 0
|
---|
2357 | && format & (M6812_OP_IDX | M6812_OP_IDX_1 | M6812_OP_IDX_2)
|
---|
2358 | && (operands[i].reg1 == REG_X
|
---|
2359 | || operands[i].reg1 == REG_Y
|
---|
2360 | || operands[i].reg1 == REG_SP
|
---|
2361 | || operands[i].reg1 == REG_PC))
|
---|
2362 | continue;
|
---|
2363 | if (i == 1 && format & M6812_OP_IDX_P2)
|
---|
2364 | continue;
|
---|
2365 | }
|
---|
2366 | if (mode & format & (M6812_OP_D_IDX | M6812_OP_D_IDX_2))
|
---|
2367 | {
|
---|
2368 | if (i == 0)
|
---|
2369 | continue;
|
---|
2370 | }
|
---|
2371 | if (mode & M6812_AUTO_INC_DEC)
|
---|
2372 | {
|
---|
2373 | if (i == 0
|
---|
2374 | && format & (M6812_OP_IDX | M6812_OP_IDX_1 |
|
---|
2375 | M6812_OP_IDX_2))
|
---|
2376 | continue;
|
---|
2377 | if (i == 1 && format & M6812_OP_IDX_P2)
|
---|
2378 | continue;
|
---|
2379 | }
|
---|
2380 | break;
|
---|
2381 | }
|
---|
2382 | match = i == nb_operands;
|
---|
2383 |
|
---|
2384 | /* Operands are ok but an operand uses page 0 addressing mode
|
---|
2385 | while the insn supports abs-16 mode. Keep a reference to this
|
---|
2386 | insns in case there is no insn supporting page 0 addressing. */
|
---|
2387 | if (match && poss_indirect)
|
---|
2388 | {
|
---|
2389 | op_indirect = opcode;
|
---|
2390 | match = 0;
|
---|
2391 | }
|
---|
2392 | if (match)
|
---|
2393 | break;
|
---|
2394 | }
|
---|
2395 |
|
---|
2396 | /* Page 0 addressing is used but not supported by any insn.
|
---|
2397 | If absolute addresses are supported, we use that insn. */
|
---|
2398 | if (match == 0 && op_indirect)
|
---|
2399 | {
|
---|
2400 | opcode = op_indirect;
|
---|
2401 | match = 1;
|
---|
2402 | }
|
---|
2403 |
|
---|
2404 | if (!match)
|
---|
2405 | {
|
---|
2406 | return (0);
|
---|
2407 | }
|
---|
2408 |
|
---|
2409 | return opcode;
|
---|
2410 | }
|
---|
2411 |
|
---|
2412 | /* Find the real opcode and its associated operands. We use a progressive
|
---|
2413 | approach here. On entry, 'opc' points to the first opcode in the
|
---|
2414 | table that matches the opcode name in the source line. We try to
|
---|
2415 | isolate an operand, find a possible match in the opcode table.
|
---|
2416 | We isolate another operand if no match were found. The table 'operands'
|
---|
2417 | is filled while operands are recognized.
|
---|
2418 |
|
---|
2419 | Returns the opcode pointer that matches the opcode name in the
|
---|
2420 | source line and the associated operands. */
|
---|
2421 | static struct m68hc11_opcode *
|
---|
2422 | find_opcode (opc, operands, nb_operands)
|
---|
2423 | struct m68hc11_opcode_def *opc;
|
---|
2424 | operand operands[];
|
---|
2425 | int *nb_operands;
|
---|
2426 | {
|
---|
2427 | struct m68hc11_opcode *opcode;
|
---|
2428 | int i;
|
---|
2429 |
|
---|
2430 | if (opc->max_operands == 0)
|
---|
2431 | {
|
---|
2432 | *nb_operands = 0;
|
---|
2433 | return opc->opcode;
|
---|
2434 | }
|
---|
2435 |
|
---|
2436 | for (i = 0; i < opc->max_operands;)
|
---|
2437 | {
|
---|
2438 | int result;
|
---|
2439 |
|
---|
2440 | result = get_operand (&operands[i], i, opc->format);
|
---|
2441 | if (result <= 0)
|
---|
2442 | return 0;
|
---|
2443 |
|
---|
2444 | /* Special case where the bitmask of the bclr/brclr
|
---|
2445 | instructions is not introduced by #.
|
---|
2446 | Example: bclr 3,x $80. */
|
---|
2447 | if (i == 1 && (opc->format & M6811_OP_BITMASK)
|
---|
2448 | && (operands[i].mode & M6811_OP_IND16))
|
---|
2449 | {
|
---|
2450 | operands[i].mode = M6811_OP_IMM16;
|
---|
2451 | }
|
---|
2452 |
|
---|
2453 | i += result;
|
---|
2454 | *nb_operands = i;
|
---|
2455 | if (i >= opc->min_operands)
|
---|
2456 | {
|
---|
2457 | opcode = find (opc, operands, i);
|
---|
2458 |
|
---|
2459 | /* Another special case for 'call foo,page' instructions.
|
---|
2460 | Since we support 'call foo' and 'call foo,page' we must look
|
---|
2461 | if the optional page specification is present otherwise we will
|
---|
2462 | assemble immediately and treat the page spec as garbage. */
|
---|
2463 | if (opcode && !(opcode->format & M6812_OP_PAGE))
|
---|
2464 | return opcode;
|
---|
2465 |
|
---|
2466 | if (opcode && *input_line_pointer != ',')
|
---|
2467 | return opcode;
|
---|
2468 | }
|
---|
2469 |
|
---|
2470 | if (*input_line_pointer == ',')
|
---|
2471 | input_line_pointer++;
|
---|
2472 | }
|
---|
2473 |
|
---|
2474 | return 0;
|
---|
2475 | }
|
---|
2476 |
|
---|
2477 | #define M6812_XBCC_MARKER (M6812_OP_TBCC_MARKER \
|
---|
2478 | | M6812_OP_DBCC_MARKER \
|
---|
2479 | | M6812_OP_IBCC_MARKER)
|
---|
2480 | |
---|
2481 |
|
---|
2482 | /* Gas line assembler entry point. */
|
---|
2483 |
|
---|
2484 | /* This is the main entry point for the machine-dependent assembler. str
|
---|
2485 | points to a machine-dependent instruction. This function is supposed to
|
---|
2486 | emit the frags/bytes it assembles to. */
|
---|
2487 | void
|
---|
2488 | md_assemble (str)
|
---|
2489 | char *str;
|
---|
2490 | {
|
---|
2491 | struct m68hc11_opcode_def *opc;
|
---|
2492 | struct m68hc11_opcode *opcode;
|
---|
2493 |
|
---|
2494 | unsigned char *op_start, *save;
|
---|
2495 | unsigned char *op_end;
|
---|
2496 | char name[20];
|
---|
2497 | int nlen = 0;
|
---|
2498 | operand operands[M6811_MAX_OPERANDS];
|
---|
2499 | int nb_operands;
|
---|
2500 | int branch_optimize = 0;
|
---|
2501 | int alias_id = -1;
|
---|
2502 |
|
---|
2503 | /* Drop leading whitespace. */
|
---|
2504 | while (*str == ' ')
|
---|
2505 | str++;
|
---|
2506 |
|
---|
2507 | /* Find the opcode end and get the opcode in 'name'. The opcode is forced
|
---|
2508 | lower case (the opcode table only has lower case op-codes). */
|
---|
2509 | for (op_start = op_end = (unsigned char *) (str);
|
---|
2510 | *op_end && nlen < 20 && !is_end_of_line[*op_end] && *op_end != ' ';
|
---|
2511 | op_end++)
|
---|
2512 | {
|
---|
2513 | name[nlen] = TOLOWER (op_start[nlen]);
|
---|
2514 | nlen++;
|
---|
2515 | }
|
---|
2516 | name[nlen] = 0;
|
---|
2517 |
|
---|
2518 | if (nlen == 0)
|
---|
2519 | {
|
---|
2520 | as_bad (_("No instruction or missing opcode."));
|
---|
2521 | return;
|
---|
2522 | }
|
---|
2523 |
|
---|
2524 | /* Find the opcode definition given its name. */
|
---|
2525 | opc = (struct m68hc11_opcode_def *) hash_find (m68hc11_hash, name);
|
---|
2526 |
|
---|
2527 | /* If it's not recognized, look for 'jbsr' and 'jbxx'. These are
|
---|
2528 | pseudo insns for relative branch. For these branchs, we always
|
---|
2529 | optimize them (turned into absolute branchs) even if --short-branchs
|
---|
2530 | is given. */
|
---|
2531 | if (opc == NULL && name[0] == 'j' && name[1] == 'b')
|
---|
2532 | {
|
---|
2533 | opc = (struct m68hc11_opcode_def *) hash_find (m68hc11_hash, &name[1]);
|
---|
2534 | if (opc
|
---|
2535 | && (!(opc->format & M6811_OP_JUMP_REL)
|
---|
2536 | || (opc->format & M6811_OP_BITMASK)))
|
---|
2537 | opc = 0;
|
---|
2538 | if (opc)
|
---|
2539 | branch_optimize = 1;
|
---|
2540 | }
|
---|
2541 |
|
---|
2542 | /* The following test should probably be removed. This is not conform
|
---|
2543 | to Motorola assembler specs. */
|
---|
2544 | if (opc == NULL && flag_mri)
|
---|
2545 | {
|
---|
2546 | if (*op_end == ' ' || *op_end == '\t')
|
---|
2547 | {
|
---|
2548 | while (*op_end == ' ' || *op_end == '\t')
|
---|
2549 | op_end++;
|
---|
2550 |
|
---|
2551 | if (nlen < 19
|
---|
2552 | && (*op_end &&
|
---|
2553 | (is_end_of_line[op_end[1]]
|
---|
2554 | || op_end[1] == ' ' || op_end[1] == '\t'
|
---|
2555 | || !ISALNUM (op_end[1])))
|
---|
2556 | && (*op_end == 'a' || *op_end == 'b'
|
---|
2557 | || *op_end == 'A' || *op_end == 'B'
|
---|
2558 | || *op_end == 'd' || *op_end == 'D'
|
---|
2559 | || *op_end == 'x' || *op_end == 'X'
|
---|
2560 | || *op_end == 'y' || *op_end == 'Y'))
|
---|
2561 | {
|
---|
2562 | name[nlen++] = TOLOWER (*op_end++);
|
---|
2563 | name[nlen] = 0;
|
---|
2564 | opc = (struct m68hc11_opcode_def *) hash_find (m68hc11_hash,
|
---|
2565 | name);
|
---|
2566 | }
|
---|
2567 | }
|
---|
2568 | }
|
---|
2569 |
|
---|
2570 | /* Identify a possible instruction alias. There are some on the
|
---|
2571 | 68HC12 to emulate a few 68HC11 instructions. */
|
---|
2572 | if (opc == NULL && (current_architecture & cpu6812))
|
---|
2573 | {
|
---|
2574 | int i;
|
---|
2575 |
|
---|
2576 | for (i = 0; i < m68hc12_num_alias; i++)
|
---|
2577 | if (strcmp (m68hc12_alias[i].name, name) == 0)
|
---|
2578 | {
|
---|
2579 | alias_id = i;
|
---|
2580 | break;
|
---|
2581 | }
|
---|
2582 | }
|
---|
2583 | if (opc == NULL && alias_id < 0)
|
---|
2584 | {
|
---|
2585 | as_bad (_("Opcode `%s' is not recognized."), name);
|
---|
2586 | return;
|
---|
2587 | }
|
---|
2588 | save = input_line_pointer;
|
---|
2589 | input_line_pointer = op_end;
|
---|
2590 |
|
---|
2591 | if (opc)
|
---|
2592 | {
|
---|
2593 | opc->used++;
|
---|
2594 | opcode = find_opcode (opc, operands, &nb_operands);
|
---|
2595 | }
|
---|
2596 | else
|
---|
2597 | opcode = 0;
|
---|
2598 |
|
---|
2599 | if ((opcode || alias_id >= 0) && !flag_mri)
|
---|
2600 | {
|
---|
2601 | char *p = input_line_pointer;
|
---|
2602 |
|
---|
2603 | while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r')
|
---|
2604 | p++;
|
---|
2605 |
|
---|
2606 | if (*p != '\n' && *p)
|
---|
2607 | as_bad (_("Garbage at end of instruction: `%s'."), p);
|
---|
2608 | }
|
---|
2609 |
|
---|
2610 | input_line_pointer = save;
|
---|
2611 |
|
---|
2612 | if (alias_id >= 0)
|
---|
2613 | {
|
---|
2614 | char *f = m68hc11_new_insn (m68hc12_alias[alias_id].size);
|
---|
2615 |
|
---|
2616 | number_to_chars_bigendian (f, m68hc12_alias[alias_id].code1, 1);
|
---|
2617 | if (m68hc12_alias[alias_id].size > 1)
|
---|
2618 | number_to_chars_bigendian (f + 1, m68hc12_alias[alias_id].code2, 1);
|
---|
2619 |
|
---|
2620 | return;
|
---|
2621 | }
|
---|
2622 |
|
---|
2623 | /* Opcode is known but does not have valid operands. Print out the
|
---|
2624 | syntax for this opcode. */
|
---|
2625 | if (opcode == 0)
|
---|
2626 | {
|
---|
2627 | if (flag_print_insn_syntax)
|
---|
2628 | print_insn_format (name);
|
---|
2629 |
|
---|
2630 | as_bad (_("Invalid operand for `%s'"), name);
|
---|
2631 | return;
|
---|
2632 | }
|
---|
2633 |
|
---|
2634 | /* Treat dbeq/ibeq/tbeq instructions in a special way. The branch is
|
---|
2635 | relative and must be in the range -256..255 (9-bits). */
|
---|
2636 | if ((opcode->format & M6812_XBCC_MARKER)
|
---|
2637 | && (opcode->format & M6811_OP_JUMP_REL))
|
---|
2638 | build_dbranch_insn (opcode, operands, nb_operands, branch_optimize);
|
---|
2639 |
|
---|
2640 | /* Relative jumps instructions are taken care of separately. We have to make
|
---|
2641 | sure that the relative branch is within the range -128..127. If it's out
|
---|
2642 | of range, the instructions are changed into absolute instructions.
|
---|
2643 | This is not supported for the brset and brclr instructions. */
|
---|
2644 | else if ((opcode->format & (M6811_OP_JUMP_REL | M6812_OP_JUMP_REL16))
|
---|
2645 | && !(opcode->format & M6811_OP_BITMASK))
|
---|
2646 | build_jump_insn (opcode, operands, nb_operands, branch_optimize);
|
---|
2647 | else
|
---|
2648 | build_insn (opcode, operands, nb_operands);
|
---|
2649 | }
|
---|
2650 |
|
---|
2651 | |
---|
2652 |
|
---|
2653 | /* Pseudo op to control the ELF flags. */
|
---|
2654 | static void
|
---|
2655 | s_m68hc11_mode (x)
|
---|
2656 | int x ATTRIBUTE_UNUSED;
|
---|
2657 | {
|
---|
2658 | char *name = input_line_pointer, ch;
|
---|
2659 |
|
---|
2660 | while (!is_end_of_line[(unsigned char) *input_line_pointer])
|
---|
2661 | input_line_pointer++;
|
---|
2662 | ch = *input_line_pointer;
|
---|
2663 | *input_line_pointer = '\0';
|
---|
2664 |
|
---|
2665 | if (strcmp (name, "mshort") == 0)
|
---|
2666 | {
|
---|
2667 | elf_flags &= ~E_M68HC11_I32;
|
---|
2668 | }
|
---|
2669 | else if (strcmp (name, "mlong") == 0)
|
---|
2670 | {
|
---|
2671 | elf_flags |= E_M68HC11_I32;
|
---|
2672 | }
|
---|
2673 | else if (strcmp (name, "mshort-double") == 0)
|
---|
2674 | {
|
---|
2675 | elf_flags &= ~E_M68HC11_F64;
|
---|
2676 | }
|
---|
2677 | else if (strcmp (name, "mlong-double") == 0)
|
---|
2678 | {
|
---|
2679 | elf_flags |= E_M68HC11_F64;
|
---|
2680 | }
|
---|
2681 | else
|
---|
2682 | {
|
---|
2683 | as_warn (_("Invalid mode: %s\n"), name);
|
---|
2684 | }
|
---|
2685 | *input_line_pointer = ch;
|
---|
2686 | demand_empty_rest_of_line ();
|
---|
2687 | }
|
---|
2688 |
|
---|
2689 | /* Mark the symbols with STO_M68HC12_FAR to indicate the functions
|
---|
2690 | are using 'rtc' for returning. It is necessary to use 'call'
|
---|
2691 | to invoke them. This is also used by the debugger to correctly
|
---|
2692 | find the stack frame. */
|
---|
2693 | static void
|
---|
2694 | s_m68hc11_mark_symbol (mark)
|
---|
2695 | int mark;
|
---|
2696 | {
|
---|
2697 | char *name;
|
---|
2698 | int c;
|
---|
2699 | symbolS *symbolP;
|
---|
2700 | asymbol *bfdsym;
|
---|
2701 | elf_symbol_type *elfsym;
|
---|
2702 |
|
---|
2703 | do
|
---|
2704 | {
|
---|
2705 | name = input_line_pointer;
|
---|
2706 | c = get_symbol_end ();
|
---|
2707 | symbolP = symbol_find_or_make (name);
|
---|
2708 | *input_line_pointer = c;
|
---|
2709 |
|
---|
2710 | SKIP_WHITESPACE ();
|
---|
2711 |
|
---|
2712 | bfdsym = symbol_get_bfdsym (symbolP);
|
---|
2713 | elfsym = elf_symbol_from (bfd_asymbol_bfd (bfdsym), bfdsym);
|
---|
2714 |
|
---|
2715 | assert (elfsym);
|
---|
2716 |
|
---|
2717 | /* Mark the symbol far (using rtc for function return). */
|
---|
2718 | elfsym->internal_elf_sym.st_other |= mark;
|
---|
2719 |
|
---|
2720 | if (c == ',')
|
---|
2721 | {
|
---|
2722 | input_line_pointer ++;
|
---|
2723 |
|
---|
2724 | SKIP_WHITESPACE ();
|
---|
2725 |
|
---|
2726 | if (*input_line_pointer == '\n')
|
---|
2727 | c = '\n';
|
---|
2728 | }
|
---|
2729 | }
|
---|
2730 | while (c == ',');
|
---|
2731 |
|
---|
2732 | demand_empty_rest_of_line ();
|
---|
2733 | }
|
---|
2734 |
|
---|
2735 | static void
|
---|
2736 | s_m68hc11_relax (ignore)
|
---|
2737 | int ignore ATTRIBUTE_UNUSED;
|
---|
2738 | {
|
---|
2739 | expressionS ex;
|
---|
2740 |
|
---|
2741 | expression (&ex);
|
---|
2742 |
|
---|
2743 | if (ex.X_op != O_symbol || ex.X_add_number != 0)
|
---|
2744 | {
|
---|
2745 | as_bad (_("bad .relax format"));
|
---|
2746 | ignore_rest_of_line ();
|
---|
2747 | return;
|
---|
2748 | }
|
---|
2749 |
|
---|
2750 | fix_new_exp (frag_now, frag_now_fix (), 1, &ex, 1,
|
---|
2751 | BFD_RELOC_M68HC11_RL_GROUP);
|
---|
2752 |
|
---|
2753 | demand_empty_rest_of_line ();
|
---|
2754 | }
|
---|
2755 |
|
---|
2756 | |
---|
2757 |
|
---|
2758 | /* Relocation, relaxation and frag conversions. */
|
---|
2759 |
|
---|
2760 | /* PC-relative offsets are relative to the start of the
|
---|
2761 | next instruction. That is, the address of the offset, plus its
|
---|
2762 | size, since the offset is always the last part of the insn. */
|
---|
2763 | long
|
---|
2764 | md_pcrel_from (fixP)
|
---|
2765 | fixS *fixP;
|
---|
2766 | {
|
---|
2767 | if (fixP->fx_r_type == BFD_RELOC_M68HC11_RL_JUMP)
|
---|
2768 | return 0;
|
---|
2769 |
|
---|
2770 | return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
|
---|
2771 | }
|
---|
2772 |
|
---|
2773 | /* If while processing a fixup, a reloc really needs to be created
|
---|
2774 | then it is done here. */
|
---|
2775 | arelent *
|
---|
2776 | tc_gen_reloc (section, fixp)
|
---|
2777 | asection *section ATTRIBUTE_UNUSED;
|
---|
2778 | fixS *fixp;
|
---|
2779 | {
|
---|
2780 | arelent *reloc;
|
---|
2781 |
|
---|
2782 | reloc = (arelent *) xmalloc (sizeof (arelent));
|
---|
2783 | reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
|
---|
2784 | *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
|
---|
2785 | reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
|
---|
2786 | if (fixp->fx_r_type == 0)
|
---|
2787 | reloc->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_16);
|
---|
2788 | else
|
---|
2789 | reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
|
---|
2790 | if (reloc->howto == (reloc_howto_type *) NULL)
|
---|
2791 | {
|
---|
2792 | as_bad_where (fixp->fx_file, fixp->fx_line,
|
---|
2793 | _("Relocation %d is not supported by object file format."),
|
---|
2794 | (int) fixp->fx_r_type);
|
---|
2795 | return NULL;
|
---|
2796 | }
|
---|
2797 |
|
---|
2798 | /* Since we use Rel instead of Rela, encode the vtable entry to be
|
---|
2799 | used in the relocation's section offset. */
|
---|
2800 | if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
|
---|
2801 | reloc->address = fixp->fx_offset;
|
---|
2802 |
|
---|
2803 | reloc->addend = 0;
|
---|
2804 | return reloc;
|
---|
2805 | }
|
---|
2806 |
|
---|
2807 | /* We need a port-specific relaxation function to cope with sym2 - sym1
|
---|
2808 | relative expressions with both symbols in the same segment (but not
|
---|
2809 | necessarily in the same frag as this insn), for example:
|
---|
2810 | ldab sym2-(sym1-2),pc
|
---|
2811 | sym1:
|
---|
2812 | The offset can be 5, 9 or 16 bits long. */
|
---|
2813 |
|
---|
2814 | long
|
---|
2815 | m68hc11_relax_frag (seg, fragP, stretch)
|
---|
2816 | segT seg ATTRIBUTE_UNUSED;
|
---|
2817 | fragS *fragP;
|
---|
2818 | long stretch ATTRIBUTE_UNUSED;
|
---|
2819 | {
|
---|
2820 | long growth;
|
---|
2821 | offsetT aim = 0;
|
---|
2822 | symbolS *symbolP;
|
---|
2823 | const relax_typeS *this_type;
|
---|
2824 | const relax_typeS *start_type;
|
---|
2825 | relax_substateT next_state;
|
---|
2826 | relax_substateT this_state;
|
---|
2827 | const relax_typeS *table = TC_GENERIC_RELAX_TABLE;
|
---|
2828 |
|
---|
2829 | /* We only have to cope with frags as prepared by
|
---|
2830 | md_estimate_size_before_relax. The STATE_BITS16 case may geet here
|
---|
2831 | because of the different reasons that it's not relaxable. */
|
---|
2832 | switch (fragP->fr_subtype)
|
---|
2833 | {
|
---|
2834 | case ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS16):
|
---|
2835 | case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS16):
|
---|
2836 | /* When we get to this state, the frag won't grow any more. */
|
---|
2837 | return 0;
|
---|
2838 |
|
---|
2839 | case ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS5):
|
---|
2840 | case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS5):
|
---|
2841 | case ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS9):
|
---|
2842 | case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS9):
|
---|
2843 | if (fragP->fr_symbol == NULL
|
---|
2844 | || S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)
|
---|
2845 | as_fatal (_("internal inconsistency problem in %s: fr_symbol %lx"),
|
---|
2846 | __FUNCTION__, (long) fragP->fr_symbol);
|
---|
2847 | symbolP = fragP->fr_symbol;
|
---|
2848 | if (symbol_resolved_p (symbolP))
|
---|
2849 | as_fatal (_("internal inconsistency problem in %s: resolved symbol"),
|
---|
2850 | __FUNCTION__);
|
---|
2851 | aim = S_GET_VALUE (symbolP);
|
---|
2852 | break;
|
---|
2853 |
|
---|
2854 | default:
|
---|
2855 | as_fatal (_("internal inconsistency problem in %s: fr_subtype %d"),
|
---|
2856 | __FUNCTION__, fragP->fr_subtype);
|
---|
2857 | }
|
---|
2858 |
|
---|
2859 | /* The rest is stolen from relax_frag. There's no obvious way to
|
---|
2860 | share the code, but fortunately no requirement to keep in sync as
|
---|
2861 | long as fragP->fr_symbol does not have its segment changed. */
|
---|
2862 |
|
---|
2863 | this_state = fragP->fr_subtype;
|
---|
2864 | start_type = this_type = table + this_state;
|
---|
2865 |
|
---|
2866 | if (aim < 0)
|
---|
2867 | {
|
---|
2868 | /* Look backwards. */
|
---|
2869 | for (next_state = this_type->rlx_more; next_state;)
|
---|
2870 | if (aim >= this_type->rlx_backward)
|
---|
2871 | next_state = 0;
|
---|
2872 | else
|
---|
2873 | {
|
---|
2874 | /* Grow to next state. */
|
---|
2875 | this_state = next_state;
|
---|
2876 | this_type = table + this_state;
|
---|
2877 | next_state = this_type->rlx_more;
|
---|
2878 | }
|
---|
2879 | }
|
---|
2880 | else
|
---|
2881 | {
|
---|
2882 | /* Look forwards. */
|
---|
2883 | for (next_state = this_type->rlx_more; next_state;)
|
---|
2884 | if (aim <= this_type->rlx_forward)
|
---|
2885 | next_state = 0;
|
---|
2886 | else
|
---|
2887 | {
|
---|
2888 | /* Grow to next state. */
|
---|
2889 | this_state = next_state;
|
---|
2890 | this_type = table + this_state;
|
---|
2891 | next_state = this_type->rlx_more;
|
---|
2892 | }
|
---|
2893 | }
|
---|
2894 |
|
---|
2895 | growth = this_type->rlx_length - start_type->rlx_length;
|
---|
2896 | if (growth != 0)
|
---|
2897 | fragP->fr_subtype = this_state;
|
---|
2898 | return growth;
|
---|
2899 | }
|
---|
2900 |
|
---|
2901 | void
|
---|
2902 | md_convert_frag (abfd, sec, fragP)
|
---|
2903 | bfd *abfd ATTRIBUTE_UNUSED;
|
---|
2904 | asection *sec ATTRIBUTE_UNUSED;
|
---|
2905 | fragS *fragP;
|
---|
2906 | {
|
---|
2907 | fixS *fixp;
|
---|
2908 | long value;
|
---|
2909 | long disp;
|
---|
2910 | char *buffer_address = fragP->fr_literal;
|
---|
2911 |
|
---|
2912 | /* Address in object code of the displacement. */
|
---|
2913 | register int object_address = fragP->fr_fix + fragP->fr_address;
|
---|
2914 |
|
---|
2915 | buffer_address += fragP->fr_fix;
|
---|
2916 |
|
---|
2917 | /* The displacement of the address, from current location. */
|
---|
2918 | value = S_GET_VALUE (fragP->fr_symbol);
|
---|
2919 | disp = (value + fragP->fr_offset) - object_address;
|
---|
2920 |
|
---|
2921 | switch (fragP->fr_subtype)
|
---|
2922 | {
|
---|
2923 | case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE):
|
---|
2924 | fragP->fr_opcode[1] = disp;
|
---|
2925 | break;
|
---|
2926 |
|
---|
2927 | case ENCODE_RELAX (STATE_PC_RELATIVE, STATE_WORD):
|
---|
2928 | /* This relax is only for bsr and bra. */
|
---|
2929 | assert (IS_OPCODE (fragP->fr_opcode[0], M6811_BSR)
|
---|
2930 | || IS_OPCODE (fragP->fr_opcode[0], M6811_BRA)
|
---|
2931 | || IS_OPCODE (fragP->fr_opcode[0], M6812_BSR));
|
---|
2932 |
|
---|
2933 | fragP->fr_opcode[0] = convert_branch (fragP->fr_opcode[0]);
|
---|
2934 |
|
---|
2935 | fix_new (fragP, fragP->fr_fix - 1, 2,
|
---|
2936 | fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_16);
|
---|
2937 | fragP->fr_fix += 1;
|
---|
2938 | break;
|
---|
2939 |
|
---|
2940 | case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_BYTE):
|
---|
2941 | case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH_6812, STATE_BYTE):
|
---|
2942 | fragP->fr_opcode[1] = disp;
|
---|
2943 | break;
|
---|
2944 |
|
---|
2945 | case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH, STATE_WORD):
|
---|
2946 | /* Invert branch. */
|
---|
2947 | fragP->fr_opcode[0] ^= 1;
|
---|
2948 | fragP->fr_opcode[1] = 3; /* Branch offset. */
|
---|
2949 | buffer_address[0] = M6811_JMP;
|
---|
2950 | fix_new (fragP, fragP->fr_fix + 1, 2,
|
---|
2951 | fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_16);
|
---|
2952 | fragP->fr_fix += 3;
|
---|
2953 | break;
|
---|
2954 |
|
---|
2955 | case ENCODE_RELAX (STATE_CONDITIONAL_BRANCH_6812, STATE_WORD):
|
---|
2956 | /* Translate branch into a long branch. */
|
---|
2957 | fragP->fr_opcode[1] = fragP->fr_opcode[0];
|
---|
2958 | fragP->fr_opcode[0] = M6811_OPCODE_PAGE2;
|
---|
2959 |
|
---|
2960 | fixp = fix_new (fragP, fragP->fr_fix, 2,
|
---|
2961 | fragP->fr_symbol, fragP->fr_offset, 1,
|
---|
2962 | BFD_RELOC_16_PCREL);
|
---|
2963 | fixp->fx_pcrel_adjust = 2;
|
---|
2964 | fragP->fr_fix += 2;
|
---|
2965 | break;
|
---|
2966 |
|
---|
2967 | case ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS5):
|
---|
2968 | if (fragP->fr_symbol != 0
|
---|
2969 | && S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)
|
---|
2970 | value = disp;
|
---|
2971 | /* fall through */
|
---|
2972 |
|
---|
2973 | case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS5):
|
---|
2974 | fragP->fr_opcode[0] = fragP->fr_opcode[0] << 6;
|
---|
2975 | fragP->fr_opcode[0] |= value & 0x1f;
|
---|
2976 | break;
|
---|
2977 |
|
---|
2978 | case ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS9):
|
---|
2979 | /* For a PC-relative offset, use the displacement with a -1 correction
|
---|
2980 | to take into account the additional byte of the insn. */
|
---|
2981 | if (fragP->fr_symbol != 0
|
---|
2982 | && S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)
|
---|
2983 | value = disp - 1;
|
---|
2984 | /* fall through */
|
---|
2985 |
|
---|
2986 | case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS9):
|
---|
2987 | fragP->fr_opcode[0] = (fragP->fr_opcode[0] << 3);
|
---|
2988 | fragP->fr_opcode[0] |= 0xE0;
|
---|
2989 | fragP->fr_opcode[0] |= (value >> 8) & 1;
|
---|
2990 | fragP->fr_opcode[1] = value;
|
---|
2991 | fragP->fr_fix += 1;
|
---|
2992 | break;
|
---|
2993 |
|
---|
2994 | case ENCODE_RELAX (STATE_INDEXED_PCREL, STATE_BITS16):
|
---|
2995 | case ENCODE_RELAX (STATE_INDEXED_OFFSET, STATE_BITS16):
|
---|
2996 | fragP->fr_opcode[0] = (fragP->fr_opcode[0] << 3);
|
---|
2997 | fragP->fr_opcode[0] |= 0xe2;
|
---|
2998 | if ((fragP->fr_opcode[0] & 0x0ff) == 0x0fa
|
---|
2999 | && fragP->fr_symbol != 0
|
---|
3000 | && S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)
|
---|
3001 | {
|
---|
3002 | fixp = fix_new (fragP, fragP->fr_fix, 2,
|
---|
3003 | fragP->fr_symbol, fragP->fr_offset,
|
---|
3004 | 1, BFD_RELOC_16_PCREL);
|
---|
3005 | }
|
---|
3006 | else
|
---|
3007 | {
|
---|
3008 | fix_new (fragP, fragP->fr_fix, 2,
|
---|
3009 | fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_16);
|
---|
3010 | }
|
---|
3011 | fragP->fr_fix += 2;
|
---|
3012 | break;
|
---|
3013 |
|
---|
3014 | case ENCODE_RELAX (STATE_XBCC_BRANCH, STATE_BYTE):
|
---|
3015 | if (disp < 0)
|
---|
3016 | fragP->fr_opcode[0] |= 0x10;
|
---|
3017 |
|
---|
3018 | fragP->fr_opcode[1] = disp & 0x0FF;
|
---|
3019 | break;
|
---|
3020 |
|
---|
3021 | case ENCODE_RELAX (STATE_XBCC_BRANCH, STATE_WORD):
|
---|
3022 | /* Invert branch. */
|
---|
3023 | fragP->fr_opcode[0] ^= 0x20;
|
---|
3024 | fragP->fr_opcode[1] = 3; /* Branch offset. */
|
---|
3025 | buffer_address[0] = M6812_JMP;
|
---|
3026 | fix_new (fragP, fragP->fr_fix + 1, 2,
|
---|
3027 | fragP->fr_symbol, fragP->fr_offset, 0, BFD_RELOC_16);
|
---|
3028 | fragP->fr_fix += 3;
|
---|
3029 | break;
|
---|
3030 |
|
---|
3031 | default:
|
---|
3032 | break;
|
---|
3033 | }
|
---|
3034 | }
|
---|
3035 |
|
---|
3036 | /* On an ELF system, we can't relax a weak symbol. The weak symbol
|
---|
3037 | can be overridden at final link time by a non weak symbol. We can
|
---|
3038 | relax externally visible symbol because there is no shared library
|
---|
3039 | and such symbol can't be overridden (unless they are weak). */
|
---|
3040 | static int
|
---|
3041 | relaxable_symbol (symbol)
|
---|
3042 | symbolS *symbol;
|
---|
3043 | {
|
---|
3044 | return ! S_IS_WEAK (symbol);
|
---|
3045 | }
|
---|
3046 |
|
---|
3047 | /* Force truly undefined symbols to their maximum size, and generally set up
|
---|
3048 | the frag list to be relaxed. */
|
---|
3049 | int
|
---|
3050 | md_estimate_size_before_relax (fragP, segment)
|
---|
3051 | fragS *fragP;
|
---|
3052 | asection *segment;
|
---|
3053 | {
|
---|
3054 | if (RELAX_LENGTH (fragP->fr_subtype) == STATE_UNDF)
|
---|
3055 | {
|
---|
3056 | if (S_GET_SEGMENT (fragP->fr_symbol) != segment
|
---|
3057 | || !relaxable_symbol (fragP->fr_symbol)
|
---|
3058 | || (segment != absolute_section
|
---|
3059 | && RELAX_STATE (fragP->fr_subtype) == STATE_INDEXED_OFFSET))
|
---|
3060 | {
|
---|
3061 | /* Non-relaxable cases. */
|
---|
3062 | int old_fr_fix;
|
---|
3063 | char *buffer_address;
|
---|
3064 |
|
---|
3065 | old_fr_fix = fragP->fr_fix;
|
---|
3066 | buffer_address = fragP->fr_fix + fragP->fr_literal;
|
---|
3067 |
|
---|
3068 | switch (RELAX_STATE (fragP->fr_subtype))
|
---|
3069 | {
|
---|
3070 | case STATE_PC_RELATIVE:
|
---|
3071 |
|
---|
3072 | /* This relax is only for bsr and bra. */
|
---|
3073 | assert (IS_OPCODE (fragP->fr_opcode[0], M6811_BSR)
|
---|
3074 | || IS_OPCODE (fragP->fr_opcode[0], M6811_BRA)
|
---|
3075 | || IS_OPCODE (fragP->fr_opcode[0], M6812_BSR));
|
---|
3076 |
|
---|
3077 | if (flag_fixed_branchs)
|
---|
3078 | as_bad_where (fragP->fr_file, fragP->fr_line,
|
---|
3079 | _("bra or bsr with undefined symbol."));
|
---|
3080 |
|
---|
3081 | /* The symbol is undefined or in a separate section.
|
---|
3082 | Turn bra into a jmp and bsr into a jsr. The insn
|
---|
3083 | becomes 3 bytes long (instead of 2). A fixup is
|
---|
3084 | necessary for the unresolved symbol address. */
|
---|
3085 | fragP->fr_opcode[0] = convert_branch (fragP->fr_opcode[0]);
|
---|
3086 |
|
---|
3087 | fix_new (fragP, fragP->fr_fix - 1, 2, fragP->fr_symbol,
|
---|
3088 | fragP->fr_offset, 0, BFD_RELOC_16);
|
---|
3089 | fragP->fr_fix++;
|
---|
3090 | break;
|
---|
3091 |
|
---|
3092 | case STATE_CONDITIONAL_BRANCH:
|
---|
3093 | assert (current_architecture & cpu6811);
|
---|
3094 |
|
---|
3095 | fragP->fr_opcode[0] ^= 1; /* Reverse sense of branch. */
|
---|
3096 | fragP->fr_opcode[1] = 3; /* Skip next jmp insn (3 bytes). */
|
---|
3097 |
|
---|
3098 | /* Don't use fr_opcode[2] because this may be
|
---|
3099 | in a different frag. */
|
---|
3100 | buffer_address[0] = M6811_JMP;
|
---|
3101 |
|
---|
3102 | fragP->fr_fix++;
|
---|
3103 | fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
|
---|
3104 | fragP->fr_offset, 0, BFD_RELOC_16);
|
---|
3105 | fragP->fr_fix += 2;
|
---|
3106 | break;
|
---|
3107 |
|
---|
3108 | case STATE_INDEXED_OFFSET:
|
---|
3109 | assert (current_architecture & cpu6812);
|
---|
3110 |
|
---|
3111 | if (fragP->fr_symbol
|
---|
3112 | && S_GET_SEGMENT (fragP->fr_symbol) == absolute_section)
|
---|
3113 | {
|
---|
3114 | fragP->fr_subtype = ENCODE_RELAX (STATE_INDEXED_OFFSET,
|
---|
3115 | STATE_BITS5);
|
---|
3116 | /* Return the size of the variable part of the frag. */
|
---|
3117 | return md_relax_table[fragP->fr_subtype].rlx_length;
|
---|
3118 | }
|
---|
3119 | else
|
---|
3120 | {
|
---|
3121 | /* Switch the indexed operation to 16-bit mode. */
|
---|
3122 | fragP->fr_opcode[0] = fragP->fr_opcode[0] << 3;
|
---|
3123 | fragP->fr_opcode[0] |= 0xe2;
|
---|
3124 | fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
|
---|
3125 | fragP->fr_offset, 0, BFD_RELOC_16);
|
---|
3126 | fragP->fr_fix += 2;
|
---|
3127 | }
|
---|
3128 | break;
|
---|
3129 |
|
---|
3130 | case STATE_INDEXED_PCREL:
|
---|
3131 | assert (current_architecture & cpu6812);
|
---|
3132 |
|
---|
3133 | if (fragP->fr_symbol
|
---|
3134 | && S_GET_SEGMENT (fragP->fr_symbol) == absolute_section)
|
---|
3135 | {
|
---|
3136 | fragP->fr_subtype = ENCODE_RELAX (STATE_INDEXED_PCREL,
|
---|
3137 | STATE_BITS5);
|
---|
3138 | /* Return the size of the variable part of the frag. */
|
---|
3139 | return md_relax_table[fragP->fr_subtype].rlx_length;
|
---|
3140 | }
|
---|
3141 | else
|
---|
3142 | {
|
---|
3143 | fixS* fixp;
|
---|
3144 |
|
---|
3145 | fragP->fr_opcode[0] = fragP->fr_opcode[0] << 3;
|
---|
3146 | fragP->fr_opcode[0] |= 0xe2;
|
---|
3147 | fixp = fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
|
---|
3148 | fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
|
---|
3149 | fragP->fr_fix += 2;
|
---|
3150 | }
|
---|
3151 | break;
|
---|
3152 |
|
---|
3153 | case STATE_XBCC_BRANCH:
|
---|
3154 | assert (current_architecture & cpu6812);
|
---|
3155 |
|
---|
3156 | fragP->fr_opcode[0] ^= 0x20; /* Reverse sense of branch. */
|
---|
3157 | fragP->fr_opcode[1] = 3; /* Skip next jmp insn (3 bytes). */
|
---|
3158 |
|
---|
3159 | /* Don't use fr_opcode[2] because this may be
|
---|
3160 | in a different frag. */
|
---|
3161 | buffer_address[0] = M6812_JMP;
|
---|
3162 |
|
---|
3163 | fragP->fr_fix++;
|
---|
3164 | fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
|
---|
3165 | fragP->fr_offset, 0, BFD_RELOC_16);
|
---|
3166 | fragP->fr_fix += 2;
|
---|
3167 | break;
|
---|
3168 |
|
---|
3169 | case STATE_CONDITIONAL_BRANCH_6812:
|
---|
3170 | assert (current_architecture & cpu6812);
|
---|
3171 |
|
---|
3172 | /* Translate into a lbcc branch. */
|
---|
3173 | fragP->fr_opcode[1] = fragP->fr_opcode[0];
|
---|
3174 | fragP->fr_opcode[0] = M6811_OPCODE_PAGE2;
|
---|
3175 |
|
---|
3176 | fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol,
|
---|
3177 | fragP->fr_offset, 1, BFD_RELOC_16_PCREL);
|
---|
3178 | fragP->fr_fix += 2;
|
---|
3179 | break;
|
---|
3180 |
|
---|
3181 | default:
|
---|
3182 | as_fatal (_("Subtype %d is not recognized."), fragP->fr_subtype);
|
---|
3183 | }
|
---|
3184 | frag_wane (fragP);
|
---|
3185 |
|
---|
3186 | /* Return the growth in the fixed part of the frag. */
|
---|
3187 | return fragP->fr_fix - old_fr_fix;
|
---|
3188 | }
|
---|
3189 |
|
---|
3190 | /* Relaxable cases. */
|
---|
3191 | switch (RELAX_STATE (fragP->fr_subtype))
|
---|
3192 | {
|
---|
3193 | case STATE_PC_RELATIVE:
|
---|
3194 | /* This relax is only for bsr and bra. */
|
---|
3195 | assert (IS_OPCODE (fragP->fr_opcode[0], M6811_BSR)
|
---|
3196 | || IS_OPCODE (fragP->fr_opcode[0], M6811_BRA)
|
---|
3197 | || IS_OPCODE (fragP->fr_opcode[0], M6812_BSR));
|
---|
3198 |
|
---|
3199 | fragP->fr_subtype = ENCODE_RELAX (STATE_PC_RELATIVE, STATE_BYTE);
|
---|
3200 | break;
|
---|
3201 |
|
---|
3202 | case STATE_CONDITIONAL_BRANCH:
|
---|
3203 | assert (current_architecture & cpu6811);
|
---|
3204 |
|
---|
3205 | fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH,
|
---|
3206 | STATE_BYTE);
|
---|
3207 | break;
|
---|
3208 |
|
---|
3209 | case STATE_INDEXED_OFFSET:
|
---|
3210 | assert (current_architecture & cpu6812);
|
---|
3211 |
|
---|
3212 | fragP->fr_subtype = ENCODE_RELAX (STATE_INDEXED_OFFSET,
|
---|
3213 | STATE_BITS5);
|
---|
3214 | break;
|
---|
3215 |
|
---|
3216 | case STATE_INDEXED_PCREL:
|
---|
3217 | assert (current_architecture & cpu6812);
|
---|
3218 |
|
---|
3219 | fragP->fr_subtype = ENCODE_RELAX (STATE_INDEXED_PCREL,
|
---|
3220 | STATE_BITS5);
|
---|
3221 | break;
|
---|
3222 |
|
---|
3223 | case STATE_XBCC_BRANCH:
|
---|
3224 | assert (current_architecture & cpu6812);
|
---|
3225 |
|
---|
3226 | fragP->fr_subtype = ENCODE_RELAX (STATE_XBCC_BRANCH, STATE_BYTE);
|
---|
3227 | break;
|
---|
3228 |
|
---|
3229 | case STATE_CONDITIONAL_BRANCH_6812:
|
---|
3230 | assert (current_architecture & cpu6812);
|
---|
3231 |
|
---|
3232 | fragP->fr_subtype = ENCODE_RELAX (STATE_CONDITIONAL_BRANCH_6812,
|
---|
3233 | STATE_BYTE);
|
---|
3234 | break;
|
---|
3235 | }
|
---|
3236 | }
|
---|
3237 |
|
---|
3238 | if (fragP->fr_subtype >= sizeof (md_relax_table) / sizeof (md_relax_table[0]))
|
---|
3239 | as_fatal (_("Subtype %d is not recognized."), fragP->fr_subtype);
|
---|
3240 |
|
---|
3241 | /* Return the size of the variable part of the frag. */
|
---|
3242 | return md_relax_table[fragP->fr_subtype].rlx_length;
|
---|
3243 | }
|
---|
3244 |
|
---|
3245 | /* See whether we need to force a relocation into the output file. */
|
---|
3246 | int
|
---|
3247 | tc_m68hc11_force_relocation (fixP)
|
---|
3248 | fixS * fixP;
|
---|
3249 | {
|
---|
3250 | if (fixP->fx_r_type == BFD_RELOC_M68HC11_RL_GROUP)
|
---|
3251 | return 1;
|
---|
3252 |
|
---|
3253 | return generic_force_reloc (fixP);
|
---|
3254 | }
|
---|
3255 |
|
---|
3256 | /* Here we decide which fixups can be adjusted to make them relative
|
---|
3257 | to the beginning of the section instead of the symbol. Basically
|
---|
3258 | we need to make sure that the linker relaxation is done
|
---|
3259 | correctly, so in some cases we force the original symbol to be
|
---|
3260 | used. */
|
---|
3261 | int
|
---|
3262 | tc_m68hc11_fix_adjustable (fixP)
|
---|
3263 | fixS *fixP;
|
---|
3264 | {
|
---|
3265 | switch (fixP->fx_r_type)
|
---|
3266 | {
|
---|
3267 | /* For the linker relaxation to work correctly, these relocs
|
---|
3268 | need to be on the symbol itself. */
|
---|
3269 | case BFD_RELOC_16:
|
---|
3270 | case BFD_RELOC_M68HC11_RL_JUMP:
|
---|
3271 | case BFD_RELOC_M68HC11_RL_GROUP:
|
---|
3272 | case BFD_RELOC_VTABLE_INHERIT:
|
---|
3273 | case BFD_RELOC_VTABLE_ENTRY:
|
---|
3274 | case BFD_RELOC_32:
|
---|
3275 |
|
---|
3276 | /* The memory bank addressing translation also needs the original
|
---|
3277 | symbol. */
|
---|
3278 | case BFD_RELOC_M68HC11_LO16:
|
---|
3279 | case BFD_RELOC_M68HC11_PAGE:
|
---|
3280 | case BFD_RELOC_M68HC11_24:
|
---|
3281 | return 0;
|
---|
3282 |
|
---|
3283 | default:
|
---|
3284 | return 1;
|
---|
3285 | }
|
---|
3286 | }
|
---|
3287 |
|
---|
3288 | void
|
---|
3289 | md_apply_fix3 (fixP, valP, seg)
|
---|
3290 | fixS *fixP;
|
---|
3291 | valueT *valP;
|
---|
3292 | segT seg ATTRIBUTE_UNUSED;
|
---|
3293 | {
|
---|
3294 | char *where;
|
---|
3295 | long value = * valP;
|
---|
3296 | int op_type;
|
---|
3297 |
|
---|
3298 | if (fixP->fx_addsy == (symbolS *) NULL)
|
---|
3299 | fixP->fx_done = 1;
|
---|
3300 |
|
---|
3301 | /* We don't actually support subtracting a symbol. */
|
---|
3302 | if (fixP->fx_subsy != (symbolS *) NULL)
|
---|
3303 | as_bad_where (fixP->fx_file, fixP->fx_line, _("Expression too complex."));
|
---|
3304 |
|
---|
3305 | op_type = fixP->fx_r_type;
|
---|
3306 |
|
---|
3307 | /* Patch the instruction with the resolved operand. Elf relocation
|
---|
3308 | info will also be generated to take care of linker/loader fixups.
|
---|
3309 | The 68HC11 addresses only 64Kb, we are only concerned by 8 and 16-bit
|
---|
3310 | relocs. BFD_RELOC_8 is basically used for .page0 access (the linker
|
---|
3311 | will warn for overflows). BFD_RELOC_8_PCREL should not be generated
|
---|
3312 | because it's either resolved or turned out into non-relative insns (see
|
---|
3313 | relax table, bcc, bra, bsr transformations)
|
---|
3314 |
|
---|
3315 | The BFD_RELOC_32 is necessary for the support of --gstabs. */
|
---|
3316 | where = fixP->fx_frag->fr_literal + fixP->fx_where;
|
---|
3317 |
|
---|
3318 | switch (fixP->fx_r_type)
|
---|
3319 | {
|
---|
3320 | case BFD_RELOC_32:
|
---|
3321 | bfd_putb32 ((bfd_vma) value, (unsigned char *) where);
|
---|
3322 | break;
|
---|
3323 |
|
---|
3324 | case BFD_RELOC_24:
|
---|
3325 | case BFD_RELOC_M68HC11_24:
|
---|
3326 | bfd_putb16 ((bfd_vma) (value & 0x0ffff), (unsigned char *) where);
|
---|
3327 | ((bfd_byte*) where)[2] = ((value >> 16) & 0x0ff);
|
---|
3328 | break;
|
---|
3329 |
|
---|
3330 | case BFD_RELOC_16:
|
---|
3331 | case BFD_RELOC_16_PCREL:
|
---|
3332 | case BFD_RELOC_M68HC11_LO16:
|
---|
3333 | bfd_putb16 ((bfd_vma) value, (unsigned char *) where);
|
---|
3334 | if (value < -65537 || value > 65535)
|
---|
3335 | as_bad_where (fixP->fx_file, fixP->fx_line,
|
---|
3336 | _("Value out of 16-bit range."));
|
---|
3337 | break;
|
---|
3338 |
|
---|
3339 | case BFD_RELOC_M68HC11_HI8:
|
---|
3340 | value = value >> 8;
|
---|
3341 | /* Fall through. */
|
---|
3342 |
|
---|
3343 | case BFD_RELOC_M68HC11_LO8:
|
---|
3344 | case BFD_RELOC_8:
|
---|
3345 | case BFD_RELOC_M68HC11_PAGE:
|
---|
3346 | #if 0
|
---|
3347 | bfd_putb8 ((bfd_vma) value, (unsigned char *) where);
|
---|
3348 | #endif
|
---|
3349 | ((bfd_byte *) where)[0] = (bfd_byte) value;
|
---|
3350 | break;
|
---|
3351 |
|
---|
3352 | case BFD_RELOC_8_PCREL:
|
---|
3353 | #if 0
|
---|
3354 | bfd_putb8 ((bfd_vma) value, (unsigned char *) where);
|
---|
3355 | #endif
|
---|
3356 | ((bfd_byte *) where)[0] = (bfd_byte) value;
|
---|
3357 |
|
---|
3358 | if (value < -128 || value > 127)
|
---|
3359 | as_bad_where (fixP->fx_file, fixP->fx_line,
|
---|
3360 | _("Value %ld too large for 8-bit PC-relative branch."),
|
---|
3361 | value);
|
---|
3362 | break;
|
---|
3363 |
|
---|
3364 | case BFD_RELOC_M68HC11_3B:
|
---|
3365 | if (value <= 0 || value > 8)
|
---|
3366 | as_bad_where (fixP->fx_file, fixP->fx_line,
|
---|
3367 | _("Auto increment/decrement offset '%ld' is out of range."),
|
---|
3368 | value);
|
---|
3369 | if (where[0] & 0x8)
|
---|
3370 | value = 8 - value;
|
---|
3371 | else
|
---|
3372 | value--;
|
---|
3373 |
|
---|
3374 | where[0] = where[0] | (value & 0x07);
|
---|
3375 | break;
|
---|
3376 |
|
---|
3377 | case BFD_RELOC_M68HC11_RL_JUMP:
|
---|
3378 | case BFD_RELOC_M68HC11_RL_GROUP:
|
---|
3379 | case BFD_RELOC_VTABLE_INHERIT:
|
---|
3380 | case BFD_RELOC_VTABLE_ENTRY:
|
---|
3381 | fixP->fx_done = 0;
|
---|
3382 | return;
|
---|
3383 |
|
---|
3384 | default:
|
---|
3385 | as_fatal (_("Line %d: unknown relocation type: 0x%x."),
|
---|
3386 | fixP->fx_line, fixP->fx_r_type);
|
---|
3387 | }
|
---|
3388 | }
|
---|
3389 |
|
---|
3390 | /* Set the ELF specific flags. */
|
---|
3391 | void
|
---|
3392 | m68hc11_elf_final_processing ()
|
---|
3393 | {
|
---|
3394 | if (current_architecture & cpu6812s)
|
---|
3395 | elf_flags |= EF_M68HCS12_MACH;
|
---|
3396 | elf_elfheader (stdoutput)->e_flags &= ~EF_M68HC11_ABI;
|
---|
3397 | elf_elfheader (stdoutput)->e_flags |= elf_flags;
|
---|
3398 | }
|
---|