1 /* m88k.c -- Assemble for the 88100
2 Copyright (C) 1989 Free Software Foundation, Inc.
4 This file is not yet part of GAS, the GNU Assembler.
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 1, or (at your option)
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING. If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
23 #include <mach-o/m88k/reloc.h>
24 #include "m88k-opcode.h"
36 #include "input-scrub.h"
40 * These are the default cputype and cpusubtype for the m88k architecture.
42 const cpu_type_t md_cputype
= CPU_TYPE_MC88000
;
43 cpu_subtype_t md_cpusubtype
= CPU_SUBTYPE_MC88000_ALL
;
45 /* This is the byte sex for the m88k architecture */
46 const enum byte_sex md_target_byte_sex
= BIG_ENDIAN_BYTE_SEX
;
49 static int32_t in_delay_slot
= 0;
52 static char *cmpslot
[] = { "**", "**", "eq", "ne", "gt", "le", "lt", "ge",
53 "hi", "ls", "lo", "hs",
55 "be", "nb", "he", "nh",
79 enum reloc_type reloc
;
83 static struct hash_control
*op_hash
= NULL
;
85 /* These chars start a comment anywhere in a source file (except inside
87 const char md_comment_chars
[] = ";";
89 /* These chars only start a comment at the beginning of a line. */
90 const char md_line_comment_chars
[] = "#";
92 /* Chars that can be used to separate mant from exp in floating point nums */
93 const char md_EXP_CHARS
[] = "eE";
95 /* Chars that mean this number is a floating point constant */
97 /* or 0H1.234E-12 (see exp chars above) */
98 const char md_FLT_CHARS
[] = "dDfF";
101 struct m88k_opcode
*format
,
103 struct m88k_insn
*insn
);
104 static char * parse_reg(
106 struct m88k_insn
*insn
,
107 struct m88k_opcode
*format
,
110 static char *parse_ereg(
112 struct m88k_insn
*insn
,
113 struct m88k_opcode
*format
,
115 static char *parse_e4rot(
117 struct m88k_insn
*insn
,
118 struct m88k_opcode
*format
,
120 static char *parse_xreg(
122 struct m88k_insn
*insn
,
123 struct m88k_opcode
*format
,
126 static char *parse_pcr(
128 struct m88k_insn
*insn
,
129 struct m88k_opcode
*format
,
131 static char *parse_cmp(
133 struct m88k_insn
*insn
,
134 struct m88k_opcode
*format
,
136 static char *parse_cnd(
138 struct m88k_insn
*insn
,
139 struct m88k_opcode
*format
,
141 static char *parse_bf(
143 struct m88k_insn
*insn
,
144 struct m88k_opcode
*format
,
146 static char *parse_rot(
148 struct m88k_insn
*insn
,
149 struct m88k_opcode
*format
,
151 static char *parse_rsc(
153 struct m88k_insn
*insn
,
154 struct m88k_opcode
*format
,
156 static char *parse_cr(
158 struct m88k_insn
*insn
,
159 struct m88k_opcode
*format
,
161 static char *parse_fcr(
163 struct m88k_insn
*insn
,
164 struct m88k_opcode
*format
,
166 static char *parse_cst(
168 struct m88k_insn
*insn
,
169 struct m88k_opcode
*format
,
177 static void s_scaled(
179 static void s_m88k_abs(
181 static void s_no_delay(
185 #endif /* NeXT_MOD */
187 const pseudo_typeS md_pseudo_table
[] =
190 {"greg", s_reg
, 'r' },
191 {"xreg", s_reg
, 'x' },
192 {"scaled", s_scaled
, 0},
193 {"abs", s_m88k_abs
, 0},
194 {"no_delay", s_no_delay
, 0},
198 /* At NeXT we don't allow these */
199 {"dfloat", float_cons
, 'd'},
200 {"ffloat", float_cons
, 'f'},
201 {"global", s_globl
, 0},
204 {"zero", s_space
, 0},
216 char *name
, *end_name
, delim
;
219 if( * input_line_pointer
== '"')
220 name
= input_line_pointer
+ 1;
222 name
= input_line_pointer
;
223 delim
= get_symbol_end();
224 end_name
= input_line_pointer
;
227 symbolP
= symbol_find_or_make (name
);
228 symbolP
-> sy_type
= N_ABS
;
229 symbolP
-> sy_other
= 0; /* NO_SECT */
230 symbolP
-> sy_value
= obstack_next_free(&frags
) - frag_now
->fr_literal
;
231 symbolP
-> sy_frag
= &zero_address_frag
;
234 totally_ignore_line();
237 * s_reg() is used to implement ".greg symbol,exp" and ".xreg symbol,exp"
238 * which set symbol to 1 or 0 depending on if the expression is a general
239 * register or extended register respectfully. These are intended for use in
247 char *name
, *end_name
, delim
;
249 uint32_t n_value
, val
;
251 if( * input_line_pointer
== '"')
252 name
= input_line_pointer
+ 1;
254 name
= input_line_pointer
;
255 delim
= get_symbol_end();
256 end_name
= input_line_pointer
;
259 if ( * input_line_pointer
!= ',' ) {
261 as_warn("Expected comma after name \"%s\"", name
);
263 ignore_rest_of_line();
266 input_line_pointer
++;
271 if (*input_line_pointer
== reg
|| *input_line_pointer
== toupper(reg
)){
272 input_line_pointer
++;
273 if(isdigit(*input_line_pointer
)){
275 while (isdigit(*input_line_pointer
)){
276 if ((val
= val
* 10 + *input_line_pointer
++ - '0') > 31)
281 (*input_line_pointer
== '\n' || *input_line_pointer
== '@'))
286 symbolP
= symbol_find_or_make (name
);
287 symbolP
-> sy_type
= N_ABS
;
288 symbolP
-> sy_other
= 0; /* NO_SECT */
289 symbolP
-> sy_value
= n_value
;
290 symbolP
-> sy_frag
= &zero_address_frag
;
293 totally_ignore_line();
297 * s_scaled() is used to implement ".scaled symbol,exp" which sets symbol to 1
298 * or 0 depending on if the expression is a scaled general register expression
299 * "r1[r2]" or not respectfully. This is intended for use in macros.
306 char *name
, *end_name
, delim
;
308 uint32_t n_value
, val
;
310 if( * input_line_pointer
== '"')
311 name
= input_line_pointer
+ 1;
313 name
= input_line_pointer
;
314 delim
= get_symbol_end();
315 end_name
= input_line_pointer
;
318 if ( * input_line_pointer
!= ',' ) {
320 as_warn("Expected comma after name \"%s\"", name
);
322 ignore_rest_of_line();
325 input_line_pointer
++;
330 if (*input_line_pointer
== 'r' || *input_line_pointer
== 'R'){
331 input_line_pointer
++;
332 if(isdigit(*input_line_pointer
)){
334 while (isdigit(*input_line_pointer
)){
335 if ((val
= val
* 10 + *input_line_pointer
++ - '0') > 31)
339 if(val
<= 31 && *input_line_pointer
== '['){
340 input_line_pointer
++;
341 if (*input_line_pointer
== 'r' ||
342 *input_line_pointer
== 'R'){
343 input_line_pointer
++;
344 if(isdigit(*input_line_pointer
)){
346 while (isdigit(*input_line_pointer
)){
347 if ((val
= val
* 10 +
348 *input_line_pointer
++ - '0') > 31)
351 if(val
<= 31 && *input_line_pointer
== ']'){
352 input_line_pointer
++;
354 if(*input_line_pointer
== '\n' ||
355 *input_line_pointer
== '@')
364 symbolP
= symbol_find_or_make (name
);
365 symbolP
-> sy_type
= N_ABS
;
366 symbolP
-> sy_other
= 0; /* NO_SECT */
367 symbolP
-> sy_value
= n_value
;
368 symbolP
-> sy_frag
= & zero_address_frag
;
371 totally_ignore_line();
375 * s_m88k_abs() is used to implement ".abs symbol,exp" which sets symbol to 1
376 * or 0 depending on if the expression is an absolute expression or not
377 * respectfully. This is intended for use in macros.
384 char *name
, *end_name
, delim
, *start
;
386 uint32_t n_value
, val
, is_reg_exp
;
388 start
= input_line_pointer
;
389 if( * input_line_pointer
== '"')
390 name
= input_line_pointer
+ 1;
392 name
= input_line_pointer
;
393 delim
= get_symbol_end();
394 end_name
= input_line_pointer
;
397 if ( * input_line_pointer
!= ',' ) {
399 as_warn("Expected comma after name \"%s\"", name
);
401 ignore_rest_of_line();
404 input_line_pointer
++;
410 if(*input_line_pointer
== 'r' || *input_line_pointer
== 'R'){
411 input_line_pointer
++;
412 if(isdigit(*input_line_pointer
)){
414 while (isdigit(*input_line_pointer
)){
415 if ((val
= val
* 10 + *input_line_pointer
++ - '0') > 31)
425 input_line_pointer
= start
;
430 symbolP
= symbol_find_or_make (name
);
431 symbolP
-> sy_type
= N_ABS
;
432 symbolP
-> sy_other
= 0; /* NO_SECT */
433 symbolP
-> sy_value
= n_value
;
434 symbolP
-> sy_frag
= & zero_address_frag
;
437 totally_ignore_line();
441 * s_no_delay() is used to implement ".no_delay string" which will abort and
442 * print the string if the last instruction assembled has a delay slot.
443 * This is intended for use in macros that expand to more than one instruction
444 * that could be put in delay slots. This is not really correct in it's
445 * operation in that it is not per-section and does not take into account
446 * anything other than assembled instructions.
455 p
= input_line_pointer
;
456 while(*p
!= '\n' && *p
!= '@' && *p
!= '\0')
462 as_fatal("delay slot abort %s detected. Assembly stopping.",
464 input_line_pointer
= p
;
467 #endif /* NeXT_MOD */
473 const char *retval
= NULL
;
474 register unsigned int i
= 0;
476 /* initialize hash table */
478 op_hash
= hash_new();
480 as_fatal("Could not initialize hash table");
482 /* loop until you see the end of the list */
484 while (*m88k_opcodes
[i
].name
) {
485 char *name
= m88k_opcodes
[i
].name
;
487 /* hash each mnemonic and record its position */
489 retval
= hash_insert(op_hash
, name
, (char *)&m88k_opcodes
[i
]);
491 if (retval
!= NULL
&& *retval
!= '\0')
492 as_fatal("Can't hash instruction '%s':%s",
493 m88k_opcodes
[i
].name
, retval
);
495 /* skip to next unique mnemonic or end of list */
497 for (i
++; !strcmp(m88k_opcodes
[i
].name
, name
); i
++);
514 char *param
, *thisfrag
;
515 struct m88k_opcode
*format
;
516 struct m88k_insn insn
;
523 /* skip over instruction to find parameters */
525 /* *param != '\0' is need for instructions that have no parameters
527 for (param
= op
; !isspace(*param
) && *param
!= '\0' ; param
++);
530 /* try to find the instruction in the hash table */
532 if ((format
= (struct m88k_opcode
*) hash_find(op_hash
, op
)) == NULL
) {
533 as_warn("Invalid mnemonic '%s'", op
);
537 /* try parsing this instruction into insn */
539 while (!calcop(format
,param
,&insn
))
541 /* if it doesn't parse try the next instruction */
543 if (!strcmp(format
->name
, format
[1].name
))
546 as_warn("Parameter syntax error");
550 /* grow the current frag and plop in the opcode */
552 thisfrag
= frag_more(4);
553 md_number_to_chars(thisfrag
, insn
.opcode
, 4);
555 in_delay_slot
= format
->delay_slot
;
557 #ifdef NeXT_MOD /* generate stabs for debugging assembly code */
559 * If the -g flag is present generate a line number stab for the
562 * See the detailed comments about stabs in read_a_source_file() for a
563 * description of what is going on here.
565 if(flagseen
['g'] && frchain_now
->frch_nsect
== text_nsect
){
570 logical_input_line
/* n_desc, line number */,
571 obstack_next_free(&frags
) - frag_now
->fr_literal
,
574 #endif /* NeXT_MOD */
576 #ifdef NeXT_MOD /* mark sections containing instructions */
578 * We are putting a machine instruction in this section so mark it as
579 * containg some machine instructions.
581 frchain_now
->frch_section
.flags
|= S_ATTR_SOME_INSTRUCTIONS
;
582 #endif /* NeXT_MOD */
586 if (insn
.reloc
== M88K_RELOC_PC16
|| insn
.reloc
== M88K_RELOC_PC26
){
588 * The NeXT linker has the ability to scatter blocks of
589 * sections between labels. This requires that brances to
590 * labels that survive to the link phase must be able to
593 if(insn
.exp
.X_add_symbol
!= NULL
&&
594 (insn
.exp
.X_add_symbol
->sy_name
[0] != 'L' || flagseen
['L']))
599 #endif /* NeXT_MOD */
601 /* if this instruction requires labels mark it for later */
602 switch (insn
.reloc
) {
603 case M88K_RELOC_LO16
:
604 case M88K_RELOC_HI16
:
608 thisfrag
- frag_now
->fr_literal
,
611 thisfrag
- frag_now
->fr_literal
+ 2,
614 insn
.exp
.X_add_symbol
,
615 insn
.exp
.X_subtract_symbol
,
616 insn
.exp
.X_add_number
,
623 case M88K_RELOC_IW16
:
626 thisfrag
- frag_now
->fr_literal
,
628 insn
.exp
.X_add_symbol
,
629 insn
.exp
.X_subtract_symbol
,
630 insn
.exp
.X_add_number
,
635 #endif /* !defined(NeXT_MOD) */
637 case M88K_RELOC_PC16
:
641 thisfrag
- frag_now
->fr_literal
,
644 thisfrag
- frag_now
->fr_literal
+ 2,
647 insn
.exp
.X_add_symbol
,
648 insn
.exp
.X_subtract_symbol
,
649 insn
.exp
.X_add_number
,
655 case M88K_RELOC_PC26
:
658 thisfrag
- frag_now
->fr_literal
,
660 insn
.exp
.X_add_symbol
,
661 insn
.exp
.X_subtract_symbol
,
662 insn
.exp
.X_add_number
,
669 as_warn("Unknown relocation type");
677 struct m88k_opcode
*format
,
679 struct m88k_insn
*insn
)
683 /* initial the passed structure */
685 memset(insn
, '\0', sizeof(*insn
));
686 insn
->reloc
= NO_RELOC
;
687 insn
->opcode
= format
->opcode
;
689 /* parse all parameters */
691 for (parcnt
=0; parcnt
<3 && format
->op
[parcnt
].type
!= NIL
; parcnt
++) {
693 switch (format
->op
[parcnt
].type
) {
696 param
= parse_cst(param
, insn
, format
, parcnt
);
700 param
= parse_reg(param
, insn
, format
, parcnt
);
704 param
= parse_ereg(param
, insn
, format
, parcnt
);
708 param
= parse_e4rot(param
, insn
, format
,parcnt
);
712 param
= parse_xreg(param
, insn
, format
, parcnt
);
716 param
= parse_bf(param
, insn
, format
, parcnt
);
720 param
= parse_rot(param
, insn
, format
, parcnt
);
724 param
= parse_rsc(param
, insn
, format
, parcnt
);
728 param
= parse_cr(param
, insn
, format
, parcnt
);
732 param
= parse_fcr(param
, insn
, format
, parcnt
);
736 param
= parse_pcr(param
, insn
, format
, parcnt
);
740 param
= parse_cnd(param
, insn
, format
, parcnt
);
744 param
= parse_cmp(param
, insn
, format
, parcnt
);
748 as_fatal("Unknown parameter type");
751 /* see if parser failed or not */
764 struct m88k_insn
*insn
,
765 struct m88k_opcode
*format
,
768 char *saveptr
, *saveparam
;
771 saveptr
= input_line_pointer
;
772 input_line_pointer
= param
;
774 seg
= expression(&insn
->exp
);
776 saveparam
= input_line_pointer
;
777 input_line_pointer
= saveptr
;
779 switch (format
->op
[parcnt
].width
) {
781 case 16: insn
->reloc
= M88K_RELOC_PC16
;
784 case 26: insn
->reloc
= M88K_RELOC_PC26
;
787 default: as_warn("Strange PC relative width %d",
788 format
->op
[parcnt
].width
);
799 struct m88k_insn
*insn
,
800 struct m88k_opcode
*format
,
803 unsigned int val
= 0;
805 if (*param
!= 'r' && *param
!= 'R')
810 if (!isdigit(*param
))
813 while (isdigit(*param
))
814 if ((val
= val
* 10 + *param
++ - '0') > 31)
817 insn
->opcode
|= val
<< format
->op
[parcnt
].offset
;
822 if (parcnt
== 2 || format
->op
[parcnt
+1].type
== NIL
)
828 if (parcnt
!= 2 && format
->op
[parcnt
+1].type
== REGSC
)
834 if (parcnt
!= 2 && format
->op
[parcnt
+1].type
!= NIL
)
848 struct m88k_insn
*insn
,
849 struct m88k_opcode
*format
,
852 unsigned int val
= 0;
854 if (*param
!= 'r' && *param
!= 'R')
859 if (!isdigit(*param
))
862 while (isdigit(*param
))
863 if ((val
= val
* 10 + *param
++ - '0') > 31)
869 insn
->opcode
|= val
<< format
->op
[parcnt
].offset
;
874 if (parcnt
== 2 || format
->op
[parcnt
+1].type
== NIL
)
880 if (parcnt
!= 2 && format
->op
[parcnt
+1].type
== REGSC
)
886 if (parcnt
!= 2 && format
->op
[parcnt
+1].type
!= NIL
)
899 struct m88k_insn
*insn
,
900 struct m88k_opcode
*format
,
904 char *saveptr
, save_c
, *offset_ptr
;
908 /* Now step over the '<' and look for the offset expression before a
909 '>' and the end of line (which is a '\0' when we get here). We
910 know there is a '\0' where the end of line was because that is
911 what parse_a_buffer() in read.c does before calling md_assemble */
915 while(*param
!= '\0')
917 if(param
== offset_ptr
|| param
[-1] != '>')
922 saveptr
= input_line_pointer
;
923 input_line_pointer
= offset_ptr
;
924 seg
= expression(&exp
);
926 input_line_pointer
= saveptr
;
927 val
= exp
.X_add_number
;
928 if(seg
!= SEG_ABSOLUTE
|| val
> 60 || (val
& 0x3) != 0)
932 insn
->opcode
|= val
<< format
->op
[parcnt
].offset
;
941 struct m88k_insn
*insn
,
942 struct m88k_opcode
*format
,
945 unsigned int val
= 0;
947 if (*param
!= 'x' && *param
!= 'X')
952 if (!isdigit(*param
))
955 while (isdigit(*param
))
956 if ((val
= val
* 10 + *param
++ - '0') > 31)
959 insn
->opcode
|= val
<< format
->op
[parcnt
].offset
;
964 if (parcnt
== 2 || format
->op
[parcnt
+1].type
== NIL
)
970 if (parcnt
!= 2 && format
->op
[parcnt
+1].type
== REGSC
)
976 if (parcnt
!= 2 && format
->op
[parcnt
+1].type
!= NIL
)
990 struct m88k_insn
*insn
,
991 struct m88k_opcode
*format
,
995 char *saveptr
, save_c
, *offset_ptr
, c
;
999 /* look for the offset expression before a ',' */
1001 if (isdigit(c
) || c
== '(' || c
== '-' || c
== '+' || c
== '!' ||
1004 while(*param
!= ',')
1006 if(param
== offset_ptr
|| *param
!= ',')
1010 saveptr
= input_line_pointer
;
1011 input_line_pointer
= offset_ptr
;
1012 seg
= expression(&exp
);
1014 input_line_pointer
= saveptr
;
1015 val
= exp
.X_add_number
;
1016 if(seg
!= SEG_ABSOLUTE
||
1017 val
> (1 << format
->op
[parcnt
].width
) || val
< 0)
1020 if (isupper(*param
))
1021 *param
= tolower(*param
);
1023 if (isupper(*(param
+1)))
1024 *(param
+1) = tolower(*(param
+1));
1026 for (val
=0; cmpslot
[val
] != NULL
; val
++)
1027 if (!strncmp(param
,cmpslot
[val
],2))
1030 if (cmpslot
[val
] == NULL
)
1036 if (*param
++ != ',')
1039 insn
->opcode
|= val
<< format
->op
[parcnt
].offset
;
1048 struct m88k_insn
*insn
,
1049 struct m88k_opcode
*format
,
1053 char *saveptr
, save_c
, *offset_ptr
, c
;
1057 /* look for the offset expression before a ',' */
1059 if (isdigit(c
) || c
== '(' || c
== '-' || c
== '+' || c
== '!' ||
1062 while(*param
!= ',')
1064 if(param
== offset_ptr
|| *param
!= ',')
1068 saveptr
= input_line_pointer
;
1069 input_line_pointer
= offset_ptr
;
1070 seg
= expression(&exp
);
1072 input_line_pointer
= saveptr
;
1073 val
= exp
.X_add_number
;
1074 if(seg
!= SEG_ABSOLUTE
||
1075 val
> (1 << format
->op
[parcnt
].width
) || val
< 0)
1078 if (isupper(*param
))
1079 *param
= tolower(*param
);
1081 if (isupper(*(param
+1)))
1082 *(param
+1) = tolower(*(param
+1));
1084 for (val
=0; cndmsk
[val
].name
!= NULL
; val
++)
1085 if (!strncmp(param
,cndmsk
[val
].name
,3))
1088 if (cndmsk
[val
].name
== NULL
)
1091 val
= cndmsk
[val
].num
;
1096 if (*param
++ != ',')
1099 insn
->opcode
|= val
<< format
->op
[parcnt
].offset
;
1108 struct m88k_insn
*insn
,
1109 struct m88k_opcode
*format
,
1113 char *saveptr
, save_c
, *offset_ptr
, c
;
1117 /* We know there is a '\0' where the end of line was because that is
1118 what parse_a_buffer() in read.c does before calling md_assemble */
1120 /* First look for the width expression before a '<' */
1121 saveptr
= input_line_pointer
;
1122 input_line_pointer
= param
;
1123 while(*param
!= '<' && *param
!= '\0')
1126 input_line_pointer
= saveptr
;
1131 seg
= expression(&exp
);
1133 input_line_pointer
= saveptr
;
1134 width
= exp
.X_add_number
;
1135 if(seg
!= SEG_ABSOLUTE
|| width
> 32 || width
< 0)
1138 /* Now step over the '<' and look for the offset expression before a
1139 '>' and the end of line (which is a '\0' when we get here) */
1142 if (isdigit(c
) || c
== '(' || c
== '-' || c
== '+' || c
== '!' ||
1145 while(*param
!= '\0')
1147 if(param
!= offset_ptr
&& param
[-1] != '>')
1152 saveptr
= input_line_pointer
;
1153 input_line_pointer
= offset_ptr
;
1154 seg
= expression(&exp
);
1156 input_line_pointer
= saveptr
;
1157 val
= exp
.X_add_number
;
1158 if(seg
!= SEG_ABSOLUTE
|| val
> 32 || val
< 0)
1162 if (isupper(*param
))
1163 *param
= tolower(*param
);
1165 if (isupper(*(param
+1)))
1166 *(param
+1) = tolower(*(param
+1));
1168 for (val
=0; cmpslot
[val
] != NULL
; val
++)
1169 if (!strncmp(param
,cmpslot
[val
],2))
1172 if (cmpslot
[val
] == NULL
)
1179 insn
->opcode
|= width
<< 5;
1180 insn
->opcode
|= val
;
1189 struct m88k_insn
*insn
,
1190 struct m88k_opcode
*format
,
1194 char *saveptr
, save_c
, *offset_ptr
;
1198 /* Now step over the '<' and look for the offset expression before a
1199 '>' and the end of line (which is a '\0' when we get here). We
1200 know there is a '\0' where the end of line was because that is
1201 what parse_a_buffer() in read.c does before calling md_assemble */
1202 if (*param
++ != '<')
1205 while(*param
!= '\0')
1207 if(param
!= offset_ptr
&& param
[-1] != '>')
1212 saveptr
= input_line_pointer
;
1213 input_line_pointer
= offset_ptr
;
1214 seg
= expression(&exp
);
1216 input_line_pointer
= saveptr
;
1217 val
= exp
.X_add_number
;
1218 if(seg
!= SEG_ABSOLUTE
&& (val
> 32 || val
< 0))
1221 insn
->opcode
|= val
;
1230 struct m88k_insn
*insn
,
1231 struct m88k_opcode
*format
,
1234 unsigned int val
= 0;
1236 if (*param
!= 'r' && *param
!= 'R')
1241 if (!isdigit(*param
))
1244 while (isdigit(*param
))
1245 if ((val
= val
* 10 + *param
++ - '0') > 31)
1248 insn
->opcode
|= val
<< format
->op
[parcnt
].offset
;
1250 if (*param
!= ']' || *(param
+1) != '\0')
1260 struct m88k_insn
*insn
,
1261 struct m88k_opcode
*format
,
1264 unsigned int val
= 0;
1266 if (strncmp(param
, "cr", 2))
1271 if (!isdigit(*param
))
1274 while (isdigit(*param
))
1275 if ((val
= val
* 10 + *param
++ - '0') > 63)
1279 * the following fix is not as generic as I'd like, but the
1280 * hardware is real picky about this. - bowen@cs.buffalo.edu
1281 * This fix is to make sure the S1 and S2 fields are the same.
1283 insn
->opcode
|= (insn
->opcode
& 0x001f0000) >> 16;
1285 insn
->opcode
|= val
<< format
->op
[parcnt
].offset
;
1297 struct m88k_insn
*insn
,
1298 struct m88k_opcode
*format
,
1301 unsigned int val
= 0;
1303 if (strncmp(param
, "fcr", 3))
1308 if (!isdigit(*param
))
1311 while (isdigit(*param
))
1312 if ((val
= val
* 10 + *param
++ - '0') > 63)
1316 * This is to make sure the S1 and S2 fields are the same.
1318 insn
->opcode
|= (insn
->opcode
& 0x001f0000) >> 16;
1320 insn
->opcode
|= val
<< format
->op
[parcnt
].offset
;
1332 struct m88k_insn
*insn
,
1333 struct m88k_opcode
*format
,
1336 char c
, *saveptr
, *saveparam
;
1337 int val
, nohilo
= 0;
1342 if (isdigit(c
) || c
== '(' || c
== '-' || c
== '+' || c
== '!' ||
1344 saveptr
= input_line_pointer
;
1345 input_line_pointer
= param
;
1346 while(*param
!= '\0')
1348 seg
= expression(&exp
);
1349 input_line_pointer
= saveptr
;
1350 val
= exp
.X_add_number
;
1351 if(seg
!= SEG_ABSOLUTE
|| val
> (1 << format
->op
[parcnt
].width
))
1354 else if (!strncmp(param
,"hi16(",5))
1356 if (isdigit(*(param
+5))) {
1357 param
= getval(param
+5, (unsigned int *)&val
);
1358 val
= (val
& 0xffff0000) >> 16;
1359 if (*param
++ != ')')
1363 insn
->reloc
= M88K_RELOC_HI16
;
1364 else if (!strncmp(param
,"lo16(",5))
1366 if (isdigit(*(param
+5))) {
1367 param
= getval(param
+5, (unsigned int *)&val
);
1369 if (*param
++ != ')')
1373 insn
->reloc
= M88K_RELOC_LO16
;
1376 else if (!strncmp(param
,"iw16(",5))
1378 if (isdigit(*(param
+5))) {
1379 param
= getval(param
+5,&val
);
1381 if (*param
++ != ')')
1385 insn
->reloc
= M88K_RELOC_IW16
;
1386 #endif /* !defined(NeXT_MOD) */
1388 else if (*param
== 'r' && isdigit(*(param
+1)))
1393 insn
->reloc
= M88K_RELOC_LO16
;
1397 if (insn
->reloc
!= NO_RELOC
) {
1399 saveptr
= input_line_pointer
;
1400 input_line_pointer
= param
+ (nohilo
? 0 : 5);
1402 seg
= expression(&insn
->exp
);
1404 saveparam
= input_line_pointer
;
1405 input_line_pointer
= saveptr
;
1409 if (*saveparam
!= '\0')
1415 if (*saveparam
!= ')')
1421 if ((1 << format
->op
[parcnt
].width
) <= val
)
1424 insn
->opcode
|= val
<< format
->op
[parcnt
].offset
;
1432 #define isoct(z) (z >= '0' && z <= '7')
1433 #define ishex(z) ((z >= '0' && z <= '9') || (z >= 'a' && z <= 'f') || (z >= 'A' && z <= 'F'))
1435 (isdigit(z) ? (z) - '0' : \
1436 islower(z) ? (z) - 'a' + 10 : \
1447 if (*param
== '0' && (*(param
+1) == 'x' || *(param
+1) == 'X'))
1449 for (param
+= 2; ishex(*param
); param
++)
1451 if (*val
> 0x0fffffff)
1454 *val
= *val
* 16 + hexval(*param
);
1456 else if (*param
== '0')
1458 for (param
++; isoct(*param
); param
++)
1460 if (*val
> 0x1fffffff)
1463 *val
= *val
* 8 + *param
- '0';
1467 for (; isdigit(*param
); param
++)
1469 *val
= *val
* 10 + *param
- '0';
1504 if(fixP
->fx_r_type
== NO_RELOC
||
1505 fixP
->fx_r_type
== M88K_RELOC_VANILLA
) {
1522 switch (fixP
->fx_r_type
) {
1524 case M88K_RELOC_LO16
:
1528 case M88K_RELOC_HI16
:
1533 case M88K_RELOC_PC16
:
1539 case M88K_RELOC_PC26
:
1541 buf
[0] |= (val
>> 26) & 0x03;
1546 #else /* !defined NeXT_MOD */
1547 case M88K_RELOC_LO16
:
1552 case M88K_RELOC_IW16
:
1557 case M88K_RELOC_HI16
:
1562 case M88K_RELOC_PC16
:
1568 case M88K_RELOC_PC26
:
1570 buf
[0] |= (val
>> 26) & 0x03;
1582 #endif /* !defined(NeXT_MOD) */
1585 as_warn("Bad relocation type");
1590 #define MAX_LITTLENUMS 6
1592 /* Turn a string in input_line_pointer into a floating point constant of type
1593 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
1594 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
1603 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
1604 LITTLENUM_TYPE
*wordP
;
1635 return "Bad call to MD_ATOF()";
1637 t
=atof_ieee(input_line_pointer
,type
,words
);
1639 input_line_pointer
=t
;
1641 *sizeP
=prec
* sizeof(LITTLENUM_TYPE
);
1642 for(wordP
=words
;prec
--;) {
1643 md_number_to_chars(litP
,(int32_t)(*wordP
++),sizeof(LITTLENUM_TYPE
));
1644 litP
+=sizeof(LITTLENUM_TYPE
);
1646 return ""; /* Someone should teach Dean about null pointers */
1649 const relax_typeS md_relax_table
[] = { {0} };
1652 md_estimate_size_before_relax(
1656 as_fatal("internal error: Relaxation should never occur");
1664 as_fatal("internal error: Relaxation should never occur");