1 /* m88k.c -- Assembler for the Motorola 88000
2 Contributed by Devon Bowen of Buffalo University
3 and Torbjorn Granlund of the Swedish Institute of Computer Science.
4 Copyright (C) 1989, 1990, 1991, 1993 Free Software Foundation, Inc.
6 This file is part of GAS, the GNU Assembler.
8 GAS is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 1, or (at your option)
13 GAS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GAS; see the file COPYING. If not, write to
20 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
24 #include "m88k-opcode.h"
37 struct field_val_assoc
43 struct field_val_assoc cr_regs
[] =
70 struct field_val_assoc fcr_regs
[] =
88 struct field_val_assoc cmpslot
[] =
90 /* Integer Floating point */
100 {"ls", 9}, {"ib", 9},
101 {"lo", 10}, {"in", 10},
102 {"hs", 11}, {"ob", 11},
103 {"be", 12}, {"ue", 12},
104 {"nb", 13}, {"lg", 13},
105 {"he", 14}, {"ug", 14},
106 {"nh", 15}, {"ule", 15},
113 struct field_val_assoc cndmsk
[] =
127 unsigned long opcode
;
129 enum reloc_type reloc
;
133 static struct hash_control
*op_hash
= NULL
;
135 /* These bits should be turned off in the first address of every segment */
136 int md_seg_align
= 7;
138 /* These chars start a comment anywhere in a source file (except inside
140 const char comment_chars
[] = ";";
142 /* These chars only start a comment at the beginning of a line. */
143 const char line_comment_chars
[] = "#";
145 const char line_separator_chars
[] = "";
147 /* Chars that can be used to separate mant from exp in floating point nums */
148 const char EXP_CHARS
[] = "eE";
150 /* Chars that mean this number is a floating point constant */
151 /* as in 0f123.456 */
152 /* or 0H1.234E-12 (see exp chars above) */
153 const char FLT_CHARS
[] = "dDfF";
155 extern void float_cons (), cons (), s_globl (), s_space (),
156 s_set (), s_lcomm ();
157 static void s_file ();
159 const pseudo_typeS md_pseudo_table
[] =
161 {"align", s_align_bytes
, 4},
163 {"dfloat", float_cons
, 'd'},
164 {"ffloat", float_cons
, 'f'},
165 {"global", s_globl
, 0},
168 {"string", stringer
, 0},
170 {"zero", s_space
, 0},
171 /* Force set to be treated as an instruction. */
182 /* initialize hash table */
184 op_hash
= hash_new ();
186 as_fatal ("Could not initialize hash table");
188 /* loop until you see the end of the list */
190 while (*m88k_opcodes
[i
].name
)
192 char *name
= m88k_opcodes
[i
].name
;
194 /* hash each mnemonic and record its position */
196 retval
= hash_insert (op_hash
, name
, &m88k_opcodes
[i
]);
198 if (retval
!= NULL
&& *retval
!= '\0')
199 as_fatal ("Can't hash instruction '%s':%s",
200 m88k_opcodes
[i
].name
, retval
);
202 /* skip to next unique mnemonic or end of list */
204 for (i
++; !strcmp (m88k_opcodes
[i
].name
, name
); i
++)
210 md_parse_option (argP
, cntP
, vecP
)
222 char *param
, *thisfrag
;
224 struct m88k_opcode
*format
;
225 struct m88k_insn insn
;
229 /* skip over instruction to find parameters */
231 for (param
= op
; *param
!= 0 && !isspace (*param
); param
++)
236 /* try to find the instruction in the hash table */
238 if ((format
= (struct m88k_opcode
*) hash_find (op_hash
, op
)) == NULL
)
240 as_bad ("Invalid mnemonic '%s'", op
);
244 /* try parsing this instruction into insn */
246 insn
.exp
.X_add_symbol
= 0;
247 insn
.exp
.X_op_symbol
= 0;
248 insn
.exp
.X_add_number
= 0;
249 insn
.exp
.X_op
= O_illegal
;
250 insn
.reloc
= NO_RELOC
;
252 while (!calcop (format
, param
, &insn
))
254 /* if it doesn't parse try the next instruction */
256 if (!strcmp (format
[0].name
, format
[1].name
))
260 as_fatal ("Parameter syntax error");
265 /* grow the current frag and plop in the opcode */
267 thisfrag
= frag_more (4);
268 md_number_to_chars (thisfrag
, insn
.opcode
, 4);
270 /* if this instruction requires labels mark it for later */
279 fix_new_exp (frag_now
,
280 thisfrag
- frag_now
->fr_literal
+ 2,
288 fix_new_exp (frag_now
,
289 thisfrag
- frag_now
->fr_literal
,
297 fix_new_exp (frag_now
,
298 thisfrag
- frag_now
->fr_literal
+ 2,
306 fix_new_exp (frag_now
,
307 thisfrag
- frag_now
->fr_literal
,
315 as_fatal ("Unknown relocation type");
321 calcop (format
, param
, insn
)
322 struct m88k_opcode
*format
;
324 struct m88k_insn
*insn
;
326 char *fmt
= format
->op_spec
;
330 int reg_prefix
= 'r';
332 insn
->opcode
= format
->opcode
;
343 insn
->opcode
|= opcode
;
352 param
= get_reg (param
, &val
, reg_prefix
);
362 param
= get_reg (param
, &val
, reg_prefix
);
368 param
= get_reg (param
, &val
, reg_prefix
);
374 param
= get_reg (param
, &val
, 'r');
375 opcode
|= (val
<< 16) | val
;
379 param
= get_imm16 (param
, insn
);
383 param
= get_bf (param
, &val
);
388 param
= get_pcr (param
, insn
, RELOC_PC16
);
392 param
= get_pcr (param
, insn
, RELOC_PC26
);
396 param
= get_cmp (param
, &val
);
401 param
= get_cnd (param
, &val
);
406 param
= get_cr (param
, &val
);
411 param
= get_fcr (param
, &val
);
416 param
= get_vec9 (param
, &val
);
421 /* Having this here repeats the warning somtimes.
422 But can't we stand that? */
423 as_warn ("Use of obsolete instruction");
430 match_name (param
, assoc_tab
, valp
)
432 struct field_val_assoc
*assoc_tab
;
441 name
= assoc_tab
[i
].name
;
444 name_len
= strlen (name
);
445 if (!strncmp (param
, name
, name_len
))
447 *valp
= assoc_tab
[i
].val
;
448 return param
+ name_len
;
454 get_reg (param
, regnop
, reg_prefix
)
465 regno
= *param
++ - '0';
476 regno
= regno
* 10 + c
;
491 else if (c
== 's' && param
[0] == 'p')
501 get_imm16 (param
, insn
)
503 struct m88k_insn
*insn
;
505 enum reloc_type reloc
= NO_RELOC
;
509 if (!strncmp (param
, "hi16", 4) && !isalnum (param
[4]))
514 else if (!strncmp (param
, "lo16", 4) && !isalnum (param
[4]))
519 else if (!strncmp (param
, "iw16", 4) && !isalnum (param
[4]))
525 save_ptr
= input_line_pointer
;
526 input_line_pointer
= param
;
527 expression (&insn
->exp
);
528 param
= input_line_pointer
;
529 input_line_pointer
= save_ptr
;
531 val
= insn
->exp
.X_add_number
;
533 if (insn
->exp
.X_op
== O_constant
)
535 /* Insert the value now, and reset reloc to NO_RELOC. */
536 if (reloc
== NO_RELOC
)
538 /* Warn about too big expressions if not surrounded by xx16. */
540 as_warn ("Expression truncated to 16 bits");
543 if (reloc
== RELOC_HI16
)
546 insn
->opcode
|= val
& 0xffff;
549 else if (reloc
== NO_RELOC
)
550 /* We accept a symbol even without lo16, hi16, etc, and assume
551 lo16 was intended. */
560 get_pcr (param
, insn
, reloc
)
562 struct m88k_insn
*insn
;
563 enum reloc_type reloc
;
565 char *saveptr
, *saveparam
;
567 saveptr
= input_line_pointer
;
568 input_line_pointer
= param
;
570 expression (&insn
->exp
);
572 saveparam
= input_line_pointer
;
573 input_line_pointer
= saveptr
;
575 /* Botch: We should relocate now if O_constant. */
582 get_cmp (param
, valp
)
591 param
= match_name (param
, cmpslot
, valp
);
598 save_ptr
= input_line_pointer
;
599 input_line_pointer
= param
;
600 val
= get_absolute_expression ();
601 param
= input_line_pointer
;
602 input_line_pointer
= save_ptr
;
606 as_warn ("Expression truncated to 5 bits");
616 get_cnd (param
, valp
)
622 if (isdigit (*param
))
624 param
= getval (param
, &val
);
628 as_warn ("Expression truncated to 5 bits");
634 if (isupper (*param
))
635 *param
= tolower (*param
);
637 if (isupper (param
[1]))
638 param
[1] = tolower (param
[1]);
640 param
= match_name (param
, cndmsk
, valp
);
669 else if (c
== bc
&& depth
<= 0)
676 get_bf_offset_expression (param
, offsetp
)
682 if (isalpha (param
[0]))
684 if (isupper (param
[0]))
685 param
[0] = tolower (param
[0]);
686 if (isupper (param
[1]))
687 param
[1] = tolower (param
[1]);
689 param
= match_name (param
, cmpslot
, offsetp
);
695 input_line_pointer
= param
;
696 offset
= get_absolute_expression ();
697 param
= input_line_pointer
;
714 xp
= get_bf2 (param
, '<');
716 save_ptr
= input_line_pointer
;
717 input_line_pointer
= param
;
720 /* We did not find '<'. We have an offset (width implicitly 32). */
721 param
= get_bf_offset_expression (param
, &offset
);
722 input_line_pointer
= save_ptr
;
728 *xp
++ = 0; /* Overwrite the '<' */
729 param
= get_bf2 (xp
, '>');
732 *param
++ = 0; /* Overwrite the '>' */
734 width
= get_absolute_expression ();
735 xp
= get_bf_offset_expression (xp
, &offset
);
736 input_line_pointer
= save_ptr
;
742 *valp
= ((width
% 32) << 5) | (offset
% 32);
748 get_cr (param
, regnop
)
757 if (!strncmp (param
, "cr", 2))
761 regno
= *param
++ - '0';
772 regno
= regno
* 10 + c
;
788 param
= match_name (param
, cr_regs
, regnop
);
794 get_fcr (param
, regnop
)
803 if (!strncmp (param
, "fcr", 3))
807 regno
= *param
++ - '0';
818 regno
= regno
* 10 + c
;
834 param
= match_name (param
, fcr_regs
, regnop
);
840 get_vec9 (param
, valp
)
847 save_ptr
= input_line_pointer
;
848 input_line_pointer
= param
;
849 val
= get_absolute_expression ();
850 param
= input_line_pointer
;
851 input_line_pointer
= save_ptr
;
854 as_warn ("Expression truncated to 9 bits");
856 *valp
= val
% (1 << 9);
862 (isdigit (z) ? (z) - '0' : \
863 islower (z) ? (z) - 'a' + 10 : \
864 isupper (z) ? (z) - 'A' + 10 : -1)
871 unsigned int val
= 0;
878 if (c
== 'x' || c
== 'X')
914 md_number_to_chars (buf
, val
, nbytes
)
937 /* This routine is never called. What is it for?
938 Ian Taylor, Cygnus Support 13 Jul 1993 */
941 md_number_to_imm (buf
, val
, nbytes
, fixP
, seg_type
)
948 if (seg_type
!= N_TEXT
|| fixP
->fx_r_type
== NO_RELOC
)
967 switch (fixP
->fx_r_type
)
992 buf
[0] |= (val
>> 26) & 0x03;
1006 as_fatal ("Bad relocation type");
1014 md_number_to_disp (buf
, val
, nbytes
)
1019 as_fatal ("md_number_to_disp not defined");
1020 md_number_to_chars (buf
, val
, nbytes
);
1024 md_number_to_field (buf
, val
, nbytes
)
1029 as_fatal ("md_number_to_field not defined");
1030 md_number_to_chars (buf
, val
, nbytes
);
1033 #define MAX_LITTLENUMS 6
1035 /* Turn a string in input_line_pointer into a floating point constant of type
1036 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1037 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
1040 md_atof (type
, litP
, sizeP
)
1046 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
1047 LITTLENUM_TYPE
*wordP
;
1079 return "Bad call to MD_ATOF()";
1081 t
= atof_ieee (input_line_pointer
, type
, words
);
1083 input_line_pointer
= t
;
1085 *sizeP
= prec
* sizeof (LITTLENUM_TYPE
);
1086 for (wordP
= words
; prec
--;)
1088 md_number_to_chars (litP
, (long) (*wordP
++), sizeof (LITTLENUM_TYPE
));
1089 litP
+= sizeof (LITTLENUM_TYPE
);
1091 return ""; /* Someone should teach Dean about null pointers */
1094 int md_short_jump_size
= 4;
1097 md_create_short_jump (ptr
, from_addr
, to_addr
, frag
, to_symbol
)
1099 addressT from_addr
, to_addr
;
1103 ptr
[0] = (char) 0xc0;
1108 ptr
- frag
->fr_literal
,
1113 RELOC_PC26
); /* Botch: Shouldn't this be RELOC_PC16? */
1116 int md_long_jump_size
= 4;
1119 md_create_long_jump (ptr
, from_addr
, to_addr
, frag
, to_symbol
)
1121 addressT from_addr
, to_addr
;
1125 ptr
[0] = (char) 0xc0;
1130 ptr
- frag
->fr_literal
,
1139 md_estimate_size_before_relax (fragP
, segment_type
)
1143 as_fatal ("Relaxation should never occur");
1146 const relax_typeS md_relax_table
[] =
1156 /* As far as I can tell, this routine is never called. What is it
1158 Ian Taylor, Cygnus Support 13 Jul 1993 */
1162 * Risc relocations are completely different, so it needs
1163 * this machine dependent routine to emit them.
1166 emit_relocations (fixP
, segment_address_in_file
)
1168 relax_addressT segment_address_in_file
;
1170 struct reloc_info_m88k ri
;
1172 extern char *next_object_file_charP
;
1174 bzero ((char *) &ri
, sizeof (ri
));
1175 for (; fixP
; fixP
= fixP
->fx_next
)
1177 if (fixP
->fx_r_type
>= NO_RELOC
)
1179 fprintf (stderr
, "fixP->fx_r_type = %d\n", fixP
->fx_r_type
);
1183 if ((symbolP
= fixP
->fx_addsy
) != NULL
)
1185 ri
.r_address
= fixP
->fx_frag
->fr_address
+
1186 fixP
->fx_where
- segment_address_in_file
;
1187 if ((symbolP
->sy_type
& N_TYPE
) == N_UNDF
)
1190 ri
.r_symbolnum
= symbolP
->sy_number
;
1195 ri
.r_symbolnum
= symbolP
->sy_type
& N_TYPE
;
1197 if (symbolP
&& symbolP
->sy_frag
)
1199 ri
.r_addend
= symbolP
->sy_frag
->fr_address
;
1201 ri
.r_type
= fixP
->fx_r_type
;
1204 ri
.r_addend
-= ri
.r_address
;
1208 ri
.r_addend
= fixP
->fx_addnumber
;
1211 append (&next_object_file_charP
, (char *) &ri
, sizeof (ri
));
1221 /* This routine can be subsumed by s_lcomm in read.c.
1222 Ian Taylor, Cygnus Support 13 Jul 1993 */
1231 int temp
, bss_align
;
1234 name
= input_line_pointer
;
1235 c
= get_symbol_end ();
1236 p
= input_line_pointer
;
1239 if (*input_line_pointer
!= ',')
1241 as_warn ("Expected comma after name");
1242 ignore_rest_of_line ();
1245 input_line_pointer
++;
1246 if ((temp
= get_absolute_expression ()) < 0)
1248 as_warn ("BSS length (%d.) <0! Ignored.", temp
);
1249 ignore_rest_of_line ();
1253 symbolP
= symbol_find_or_make (name
);
1255 if (*input_line_pointer
== ',')
1257 input_line_pointer
++;
1258 bss_align
= get_absolute_expression ();
1263 if (!S_IS_DEFINED(symbolP
)
1264 || S_GET_SEGMENT(symbolP
) == SEG_BSS
)
1269 segT current_seg
= now_seg
;
1270 subsegT current_subseg
= now_subseg
;
1272 subseg_set (SEG_BSS
, 1); /* switch to bss */
1275 frag_align (bss_align
, 0);
1277 /* detach from old frag */
1278 if (symbolP
->sy_type
== N_BSS
&& symbolP
->sy_frag
!= NULL
)
1279 symbolP
->sy_frag
->fr_symbol
= NULL
;
1281 symbolP
->sy_frag
= frag_now
;
1282 p
= frag_var (rs_org
, 1, 1, (relax_substateT
)0, symbolP
,
1285 S_SET_SEGMENT (symbolP
, SEG_BSS
);
1287 subseg_set (current_seg
, current_subseg
);
1292 as_warn ("Ignoring attempt to re-define symbol %s.", name
);
1295 while (!is_end_of_line
[*input_line_pointer
])
1297 input_line_pointer
++;
1307 /* These functions are needed if we are linking with obj-coffbfd.c.
1308 That file may be replaced by a more BFD oriented version at some
1309 point. If that happens, these functions should be rexamined.
1311 Ian Lance Taylor, Cygnus Support, 13 July 1993. */
1313 /* Given a fixS structure (created by a call to fix_new, above),
1314 return the BFD relocation type to use for it. */
1317 tc_coff_fix2rtype (fixp
)
1320 switch (fixp
->fx_r_type
)
1339 /* Apply a fixS to the object file. Since COFF does not use addends
1340 in relocs, the addend is actually stored directly in the object
1344 md_apply_fix (fixp
, val
)
1350 buf
= fixp
->fx_frag
->fr_literal
+ fixp
->fx_where
;
1351 fixp
->fx_offset
= 0;
1353 switch (fixp
->fx_r_type
)
1356 fixp
->fx_offset
= val
>> 16;
1362 fixp
->fx_offset
= val
>> 16;
1368 fixp
->fx_offset
= val
>> 16;
1379 buf
[0] |= (val
>> 26) & 0x03;
1397 /* Where a PC relative offset is calculated from. On the m88k they
1398 are calculated from just after the instruction. */
1401 md_pcrel_from (fixp
)
1404 switch (fixp
->fx_r_type
)
1407 return fixp
->fx_frag
->fr_address
+ fixp
->fx_where
- 2;
1409 return fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
1416 #endif /* M88KCOFF */