source: trunk/binutils/gas/config/tc-z8k.c@ 2562

Last change on this file since 2562 was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 33.0 KB
Line 
1/* tc-z8k.c -- Assemble code for the Zilog Z800n
2 Copyright 1992, 1993, 1994, 1995, 1996, 1998, 2000, 2001, 2002, 2003
3 Free Software Foundation, Inc.
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 the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA. */
21
22/* Written By Steve Chamberlain <sac@cygnus.com>. */
23
24#define DEFINE_TABLE
25#include <stdio.h>
26
27#include "as.h"
28#include "bfd.h"
29#include "safe-ctype.h"
30#include "opcodes/z8k-opc.h"
31
32const char comment_chars[] = "!";
33const char line_comment_chars[] = "#";
34const char line_separator_chars[] = ";";
35
36extern int machine;
37extern int coff_flags;
38int segmented_mode;
39const int md_reloc_size;
40
41/* This is non-zero if target was set from the command line. */
42static int z8k_target_from_cmdline;
43
44static void s_segm PARAMS ((int));
45static void even PARAMS ((int));
46static int tohex PARAMS ((int));
47static void sval PARAMS ((int));
48
49static void
50s_segm (segm)
51 int segm;
52{
53 if (segm)
54 {
55 segmented_mode = 1;
56 machine = bfd_mach_z8001;
57 coff_flags = F_Z8001;
58 }
59 else
60 {
61 segmented_mode = 0;
62 machine = bfd_mach_z8002;
63 coff_flags = F_Z8002;
64 }
65}
66
67static void
68even (ignore)
69 int ignore ATTRIBUTE_UNUSED;
70{
71 frag_align (1, 0, 0);
72 record_alignment (now_seg, 1);
73}
74
75static int
76tohex (c)
77 int c;
78{
79 if (ISDIGIT (c))
80 return c - '0';
81 if (ISLOWER (c))
82 return c - 'a' + 10;
83 return c - 'A' + 10;
84}
85
86static void
87sval (ignore)
88 int ignore ATTRIBUTE_UNUSED;
89{
90 SKIP_WHITESPACE ();
91 if (*input_line_pointer == '\'')
92 {
93 int c;
94 input_line_pointer++;
95 c = *input_line_pointer++;
96 while (c != '\'')
97 {
98 if (c == '%')
99 {
100 c = (tohex (input_line_pointer[0]) << 4)
101 | tohex (input_line_pointer[1]);
102 input_line_pointer += 2;
103 }
104 FRAG_APPEND_1_CHAR (c);
105 c = *input_line_pointer++;
106 }
107 demand_empty_rest_of_line ();
108 }
109}
110
111/* This table describes all the machine specific pseudo-ops the assembler
112 has to support. The fields are:
113 pseudo-op name without dot
114 function to call to execute this pseudo-op
115 Integer arg to pass to the function
116 */
117
118const pseudo_typeS md_pseudo_table[] = {
119 {"int" , cons , 2},
120 {"data.b" , cons , 1},
121 {"data.w" , cons , 2},
122 {"data.l" , cons , 4},
123 {"form" , listing_psize , 0},
124 {"heading", listing_title , 0},
125 {"import" , s_ignore , 0},
126 {"page" , listing_eject , 0},
127 {"program", s_ignore , 0},
128 {"z8001" , s_segm , 1},
129 {"z8002" , s_segm , 0},
130
131 {"segm" , s_segm , 1},
132 {"unsegm" , s_segm , 0},
133 {"unseg" , s_segm , 0},
134 {"name" , s_app_file , 0},
135 {"global" , s_globl , 0},
136 {"wval" , cons , 2},
137 {"lval" , cons , 4},
138 {"bval" , cons , 1},
139 {"sval" , sval , 0},
140 {"rsect" , obj_coff_section, 0},
141 {"sect" , obj_coff_section, 0},
142 {"block" , s_space , 0},
143 {"even" , even , 0},
144 {0 , 0 , 0}
145};
146
147const char EXP_CHARS[] = "eE";
148
149/* Chars that mean this number is a floating point constant.
150 As in 0f12.456
151 or 0d1.2345e12 */
152const char FLT_CHARS[] = "rRsSfFdDxXpP";
153
154/* Opcode mnemonics. */
155static struct hash_control *opcode_hash_control;
156
157void
158md_begin ()
159{
160 const opcode_entry_type *opcode;
161 int idx = -1;
162
163 opcode_hash_control = hash_new ();
164
165 for (opcode = z8k_table; opcode->name; opcode++)
166 {
167 /* Only enter unique codes into the table. */
168 if (idx != opcode->idx)
169 hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
170 idx = opcode->idx;
171 }
172
173 /* Default to z8002. */
174 if (! z8k_target_from_cmdline)
175 s_segm (0);
176
177 /* Insert the pseudo ops, too. */
178 for (idx = 0; md_pseudo_table[idx].poc_name; idx++)
179 {
180 opcode_entry_type *fake_opcode;
181 fake_opcode = (opcode_entry_type *) malloc (sizeof (opcode_entry_type));
182 fake_opcode->name = md_pseudo_table[idx].poc_name;
183 fake_opcode->func = (void *) (md_pseudo_table + idx);
184 fake_opcode->opcode = 250;
185 hash_insert (opcode_hash_control, fake_opcode->name, fake_opcode);
186 }
187}
188
189struct z8k_exp {
190 char *e_beg;
191 char *e_end;
192 expressionS e_exp;
193};
194
195typedef struct z8k_op {
196 /* 'b','w','r','q'. */
197 char regsize;
198
199 /* 0 .. 15. */
200 unsigned int reg;
201
202 int mode;
203
204 /* Any other register associated with the mode. */
205 unsigned int x_reg;
206
207 /* Any expression. */
208 expressionS exp;
209} op_type;
210
211static expressionS *da_operand;
212static expressionS *imm_operand;
213
214int reg[16];
215int the_cc;
216int the_ctrl;
217int the_flags;
218int the_interrupt;
219
220static char *whatreg PARAMS ((int *, char *));
221static char *parse_reg PARAMS ((char *, int *, unsigned int *));
222static char *parse_exp PARAMS ((char *, expressionS *));
223static char *checkfor PARAMS ((char *, char));
224static void regword PARAMS ((int, char *));
225static void regaddr PARAMS ((int, char *));
226static void get_ctrl_operand
227 PARAMS ((char **, struct z8k_op *, unsigned int));
228static void get_flags_operand
229 PARAMS ((char **, struct z8k_op *, unsigned int));
230static void get_interrupt_operand
231 PARAMS ((char **, struct z8k_op *, unsigned int));
232static void get_cc_operand
233 PARAMS ((char **, struct z8k_op *, unsigned int));
234static void get_operand
235 PARAMS ((char **, struct z8k_op *, unsigned int));
236static char *get_operands
237 PARAMS ((const opcode_entry_type *, char *, op_type *));
238static opcode_entry_type *get_specific
239 PARAMS ((opcode_entry_type *, op_type *));
240static void newfix
241 PARAMS ((int, int, int, expressionS *));
242static char *apply_fix
243 PARAMS ((char *, int, expressionS *, int));
244static void build_bytes
245 PARAMS ((opcode_entry_type *, struct z8k_op *));
246
247static char *
248whatreg (reg, src)
249 int *reg;
250 char *src;
251{
252 if (ISDIGIT (src[1]))
253 {
254 *reg = (src[0] - '0') * 10 + src[1] - '0';
255 return src + 2;
256 }
257 else
258 {
259 *reg = (src[0] - '0');
260 return src + 1;
261 }
262}
263
264/* Parse operands
265
266 rh0-rh7, rl0-rl7
267 r0-r15
268 rr0-rr14
269 rq0--rq12
270 WREG r0,r1,r2,r3,r4,r5,r6,r7,fp,sp
271 r0l,r0h,..r7l,r7h
272 @WREG
273 @WREG+
274 @-WREG
275 #const
276*/
277
278/* Try to parse a reg name. Return a pointer to the first character
279 in SRC after the reg name. */
280
281static char *
282parse_reg (src, mode, reg)
283 char *src;
284 int *mode;
285 unsigned int *reg;
286{
287 char *res = 0;
288 char regno;
289
290 if (src[0] == 's' && src[1] == 'p' && (src[2] == 0 || src[2] == ','))
291 {
292 if (segmented_mode)
293 {
294 *mode = CLASS_REG_LONG;
295 *reg = 14;
296 }
297 else
298 {
299 *mode = CLASS_REG_WORD;
300 *reg = 15;
301 }
302 return src + 2;
303 }
304 if (src[0] == 'r')
305 {
306 if (src[1] == 'r')
307 {
308 if (src[2] < '0' || src[2] > '9')
309 return res; /* Assume no register name but a label starting with 'rr'. */
310 *mode = CLASS_REG_LONG;
311 res = whatreg (reg, src + 2);
312 regno = *reg;
313 if (regno > 14)
314 as_warn (_("register rr%d, out of range."), regno);
315 }
316 else if (src[1] == 'h')
317 {
318 if (src[2] < '0' || src[2] > '9')
319 return res; /* Assume no register name but a label starting with 'rh'. */
320 *mode = CLASS_REG_BYTE;
321 res = whatreg (reg, src + 2);
322 regno = *reg;
323 if (regno > 7)
324 as_warn (_("register rh%d, out of range."), regno);
325 }
326 else if (src[1] == 'l')
327 {
328 if (src[2] < '0' || src[2] > '9')
329 return res; /* Assume no register name but a label starting with 'rl'. */
330 *mode = CLASS_REG_BYTE;
331 res = whatreg (reg, src + 2);
332 regno = *reg;
333 if (regno > 7)
334 as_warn (_("register rl%d, out of range."), regno);
335 *reg += 8;
336 }
337 else if (src[1] == 'q')
338 {
339 if (src[2] < '0' || src[2] > '9')
340 return res; /* Assume no register name but a label starting with 'rq'. */
341 *mode = CLASS_REG_QUAD;
342 res = whatreg (reg, src + 2);
343 regno = *reg;
344 if (regno > 12)
345 as_warn (_("register rq%d, out of range."), regno);
346 }
347 else
348 {
349 if (src[1] < '0' || src[1] > '9')
350 return res; /* Assume no register name but a label starting with 'r'. */
351 *mode = CLASS_REG_WORD;
352 res = whatreg (reg, src + 1);
353 regno = *reg;
354 if (regno > 15)
355 as_warn (_("register r%d, out of range."), regno);
356 }
357 }
358 return res;
359}
360
361static char *
362parse_exp (s, op)
363 char *s;
364 expressionS *op;
365{
366 char *save = input_line_pointer;
367 char *new;
368
369 input_line_pointer = s;
370 expression (op);
371 if (op->X_op == O_absent)
372 as_bad (_("missing operand"));
373 new = input_line_pointer;
374 input_line_pointer = save;
375 return new;
376}
377
378/* The many forms of operand:
379
380 <rb>
381 <r>
382 <rr>
383 <rq>
384 @r
385 #exp
386 exp
387 exp(r)
388 r(#exp)
389 r(r)
390 */
391
392static char *
393checkfor (ptr, what)
394 char *ptr;
395 char what;
396{
397 if (*ptr == what)
398 ptr++;
399 else
400 as_bad (_("expected %c"), what);
401
402 return ptr;
403}
404
405/* Make sure the mode supplied is the size of a word. */
406
407static void
408regword (mode, string)
409 int mode;
410 char *string;
411{
412 int ok;
413
414 ok = CLASS_REG_WORD;
415 if (ok != mode)
416 {
417 as_bad (_("register is wrong size for a word %s"), string);
418 }
419}
420
421/* Make sure the mode supplied is the size of an address. */
422
423static void
424regaddr (mode, string)
425 int mode;
426 char *string;
427{
428 int ok;
429
430 ok = segmented_mode ? CLASS_REG_LONG : CLASS_REG_WORD;
431 if (ok != mode)
432 {
433 as_bad (_("register is wrong size for address %s"), string);
434 }
435}
436
437struct ctrl_names {
438 int value;
439 char *name;
440};
441
442struct ctrl_names ctrl_table[] = {
443 { 0x2, "fcw" },
444 { 0x3, "refresh" },
445 { 0x4, "psapseg" },
446 { 0x5, "psapoff" },
447 { 0x5, "psap" },
448 { 0x6, "nspseg" },
449 { 0x7, "nspoff" },
450 { 0x7, "nsp" },
451 { 0 , 0 }
452};
453
454static void
455get_ctrl_operand (ptr, mode, dst)
456 char **ptr;
457 struct z8k_op *mode;
458 unsigned int dst ATTRIBUTE_UNUSED;
459{
460 char *src = *ptr;
461 int i;
462
463 while (*src == ' ')
464 src++;
465
466 mode->mode = CLASS_CTRL;
467 for (i = 0; ctrl_table[i].name; i++)
468 {
469 int j;
470
471 for (j = 0; ctrl_table[i].name[j]; j++)
472 {
473 if (ctrl_table[i].name[j] != src[j])
474 goto fail;
475 }
476 the_ctrl = ctrl_table[i].value;
477 *ptr = src + j;
478 return;
479 fail:
480 ;
481 }
482 the_ctrl = 0;
483 return;
484}
485
486struct flag_names {
487 int value;
488 char *name;
489
490};
491
492struct flag_names flag_table[] = {
493 { 0x1, "p" },
494 { 0x1, "v" },
495 { 0x2, "s" },
496 { 0x4, "z" },
497 { 0x8, "c" },
498 { 0x0, "+" },
499 { 0, 0 }
500};
501
502static void
503get_flags_operand (ptr, mode, dst)
504 char **ptr;
505 struct z8k_op *mode;
506 unsigned int dst ATTRIBUTE_UNUSED;
507{
508 char *src = *ptr;
509 int i;
510 int j;
511
512 while (*src == ' ')
513 src++;
514
515 mode->mode = CLASS_FLAGS;
516 the_flags = 0;
517 for (j = 0; j <= 9; j++)
518 {
519 if (!src[j])
520 goto done;
521 for (i = 0; flag_table[i].name; i++)
522 {
523 if (flag_table[i].name[0] == src[j])
524 {
525 the_flags = the_flags | flag_table[i].value;
526 goto match;
527 }
528 }
529 goto done;
530 match:
531 ;
532 }
533 done:
534 *ptr = src + j;
535 return;
536}
537
538struct interrupt_names {
539 int value;
540 char *name;
541
542};
543
544struct interrupt_names intr_table[] = {
545 { 0x1, "nvi" },
546 { 0x2, "vi" },
547 { 0x3, "both" },
548 { 0x3, "all" },
549 { 0, 0 }
550};
551
552static void
553get_interrupt_operand (ptr, mode, dst)
554 char **ptr;
555 struct z8k_op *mode;
556 unsigned int dst ATTRIBUTE_UNUSED;
557{
558 char *src = *ptr;
559 int i;
560
561 while (*src == ' ')
562 src++;
563
564 mode->mode = CLASS_IMM;
565 for (i = 0; intr_table[i].name; i++)
566 {
567 int j;
568
569 for (j = 0; intr_table[i].name[j]; j++)
570 {
571 if (intr_table[i].name[j] != src[j])
572 goto fail;
573 }
574 the_interrupt = intr_table[i].value;
575 *ptr = src + j;
576 return;
577 fail:
578 ;
579 }
580 /* No interrupt type specified, opcode won't do anything. */
581 as_warn (_("opcode has no effect."));
582 the_interrupt = 0x0;
583 return;
584}
585
586struct cc_names {
587 int value;
588 char *name;
589};
590
591struct cc_names table[] = {
592 { 0x0, "f" },
593 { 0x1, "lt" },
594 { 0x2, "le" },
595 { 0x3, "ule" },
596 { 0x4, "ov" },
597 { 0x4, "pe" },
598 { 0x5, "mi" },
599 { 0x6, "eq" },
600 { 0x6, "z" },
601 { 0x7, "c" },
602 { 0x7, "ult" },
603 { 0x8, "t" },
604 { 0x9, "ge" },
605 { 0xa, "gt" },
606 { 0xb, "ugt" },
607 { 0xc, "nov" },
608 { 0xc, "po" },
609 { 0xd, "pl" },
610 { 0xe, "ne" },
611 { 0xe, "nz" },
612 { 0xf, "nc" },
613 { 0xf, "uge" },
614 { 0 , 0 }
615};
616
617static void
618get_cc_operand (ptr, mode, dst)
619 char **ptr;
620 struct z8k_op *mode;
621 unsigned int dst ATTRIBUTE_UNUSED;
622{
623 char *src = *ptr;
624 int i;
625
626 while (*src == ' ')
627 src++;
628
629 mode->mode = CLASS_CC;
630 for (i = 0; table[i].name; i++)
631 {
632 int j;
633
634 for (j = 0; table[i].name[j]; j++)
635 {
636 if (table[i].name[j] != src[j])
637 goto fail;
638 }
639 the_cc = table[i].value;
640 *ptr = src + j;
641 return;
642 fail:
643 ;
644 }
645 the_cc = 0x8;
646}
647
648static void
649get_operand (ptr, mode, dst)
650 char **ptr;
651 struct z8k_op *mode;
652 unsigned int dst ATTRIBUTE_UNUSED;
653{
654 char *src = *ptr;
655 char *end;
656
657 mode->mode = 0;
658
659 while (*src == ' ')
660 src++;
661 if (*src == '#')
662 {
663 mode->mode = CLASS_IMM;
664 imm_operand = &(mode->exp);
665 src = parse_exp (src + 1, &(mode->exp));
666 }
667 else if (*src == '@')
668 {
669 int d;
670
671 mode->mode = CLASS_IR;
672 src = parse_reg (src + 1, &d, &mode->reg);
673 }
674 else
675 {
676 int regn;
677
678 end = parse_reg (src, &mode->mode, &regn);
679
680 if (end)
681 {
682 int nw, nr;
683
684 src = end;
685 if (*src == '(')
686 {
687 src++;
688 end = parse_reg (src, &nw, &nr);
689 if (end)
690 {
691 /* Got Ra(Rb). */
692 src = end;
693
694 if (*src != ')')
695 as_bad (_("Missing ) in ra(rb)"));
696 else
697 src++;
698
699 regaddr (mode->mode, "ra(rb) ra");
700#if 0
701 regword (mode->mode, "ra(rb) rb");
702#endif
703 mode->mode = CLASS_BX;
704 mode->reg = regn;
705 mode->x_reg = nr;
706 reg[ARG_RX] = nr;
707 }
708 else
709 {
710 /* Got Ra(disp). */
711 if (*src == '#')
712 src++;
713 src = parse_exp (src, &(mode->exp));
714 src = checkfor (src, ')');
715 mode->mode = CLASS_BA;
716 mode->reg = regn;
717 mode->x_reg = 0;
718 imm_operand = &(mode->exp);
719 }
720 }
721 else
722 {
723 mode->reg = regn;
724 mode->x_reg = 0;
725 }
726 }
727 else
728 {
729 /* No initial reg. */
730 src = parse_exp (src, &(mode->exp));
731 if (*src == '(')
732 {
733 src++;
734 end = parse_reg (src, &(mode->mode), &regn);
735 regword (mode->mode, "addr(Ra) ra");
736 mode->mode = CLASS_X;
737 mode->reg = regn;
738 mode->x_reg = 0;
739 da_operand = &(mode->exp);
740 src = checkfor (end, ')');
741 }
742 else
743 {
744 /* Just an address. */
745 mode->mode = CLASS_DA;
746 mode->reg = 0;
747 mode->x_reg = 0;
748 da_operand = &(mode->exp);
749 }
750 }
751 }
752 *ptr = src;
753}
754
755static char *
756get_operands (opcode, op_end, operand)
757 const opcode_entry_type *opcode;
758 char *op_end;
759 op_type *operand;
760{
761 char *ptr = op_end;
762 char *savptr;
763
764 ptr++;
765 switch (opcode->noperands)
766 {
767 case 0:
768 operand[0].mode = 0;
769 operand[1].mode = 0;
770 break;
771
772 case 1:
773 if (opcode->arg_info[0] == CLASS_CC)
774 get_cc_operand (&ptr, operand + 0, 0);
775
776 else if (opcode->arg_info[0] == CLASS_FLAGS)
777 get_flags_operand (&ptr, operand + 0, 0);
778
779 else if (opcode->arg_info[0] == (CLASS_IMM + (ARG_IMM2)))
780 get_interrupt_operand (&ptr, operand + 0, 0);
781
782 else
783 get_operand (&ptr, operand + 0, 0);
784
785 operand[1].mode = 0;
786 break;
787
788 case 2:
789 savptr = ptr;
790 if (opcode->arg_info[0] == CLASS_CC)
791 get_cc_operand (&ptr, operand + 0, 0);
792
793 else if (opcode->arg_info[0] == CLASS_CTRL)
794 {
795 get_ctrl_operand (&ptr, operand + 0, 0);
796
797 if (the_ctrl == 0)
798 {
799 ptr = savptr;
800 get_operand (&ptr, operand + 0, 0);
801
802 if (ptr == 0)
803 return NULL;
804 if (*ptr == ',')
805 ptr++;
806 get_ctrl_operand (&ptr, operand + 1, 1);
807 return ptr;
808 }
809 }
810 else
811 get_operand (&ptr, operand + 0, 0);
812
813 if (ptr == 0)
814 return NULL;
815 if (*ptr == ',')
816 ptr++;
817 get_operand (&ptr, operand + 1, 1);
818 break;
819
820 case 3:
821 get_operand (&ptr, operand + 0, 0);
822 if (*ptr == ',')
823 ptr++;
824 get_operand (&ptr, operand + 1, 1);
825 if (*ptr == ',')
826 ptr++;
827 get_operand (&ptr, operand + 2, 2);
828 break;
829
830 case 4:
831 get_operand (&ptr, operand + 0, 0);
832 if (*ptr == ',')
833 ptr++;
834 get_operand (&ptr, operand + 1, 1);
835 if (*ptr == ',')
836 ptr++;
837 get_operand (&ptr, operand + 2, 2);
838 if (*ptr == ',')
839 ptr++;
840 get_cc_operand (&ptr, operand + 3, 3);
841 break;
842
843 default:
844 abort ();
845 }
846
847 return ptr;
848}
849
850/* Passed a pointer to a list of opcodes which use different
851 addressing modes. Return the opcode which matches the opcodes
852 provided. */
853
854static opcode_entry_type *
855get_specific (opcode, operands)
856 opcode_entry_type *opcode;
857 op_type *operands;
858{
859 opcode_entry_type *this_try = opcode;
860 int found = 0;
861 unsigned int noperands = opcode->noperands;
862
863 int this_index = opcode->idx;
864
865 while (this_index == opcode->idx && !found)
866 {
867 unsigned int i;
868
869 this_try = opcode++;
870 for (i = 0; i < noperands; i++)
871 {
872 unsigned int mode = operands[i].mode;
873
874 if ((mode & CLASS_MASK) != (this_try->arg_info[i] & CLASS_MASK))
875 {
876 /* It could be a pc rel operand, if this is a da mode
877 and we like disps, then insert it. */
878
879 if (mode == CLASS_DA && this_try->arg_info[i] == CLASS_DISP)
880 {
881 /* This is the case. */
882 operands[i].mode = CLASS_DISP;
883 }
884 else if (mode == CLASS_BA && this_try->arg_info[i])
885 {
886 /* Can't think of a way to turn what we've been
887 given into something that's OK. */
888 goto fail;
889 }
890 else if (this_try->arg_info[i] & CLASS_PR)
891 {
892 if (mode == CLASS_REG_LONG && segmented_mode)
893 {
894 /* OK. */
895 }
896 else if (mode == CLASS_REG_WORD && !segmented_mode)
897 {
898 /* OK. */
899 }
900 else
901 goto fail;
902 }
903 else
904 goto fail;
905 }
906 switch (mode & CLASS_MASK)
907 {
908 default:
909 break;
910 case CLASS_X:
911 case CLASS_IR:
912 case CLASS_BA:
913 case CLASS_BX:
914 case CLASS_DISP:
915 case CLASS_REG:
916 case CLASS_REG_WORD:
917 case CLASS_REG_BYTE:
918 case CLASS_REG_QUAD:
919 case CLASS_REG_LONG:
920 case CLASS_REGN0:
921 reg[this_try->arg_info[i] & ARG_MASK] = operands[i].reg;
922 break;
923 }
924 }
925
926 found = 1;
927 fail:
928 ;
929 }
930 if (found)
931 return this_try;
932 else
933 return 0;
934}
935
936#if 0 /* Not used. */
937static void
938check_operand (operand, width, string)
939 struct z8k_op *operand;
940 unsigned int width;
941 char *string;
942{
943 if (operand->exp.X_add_symbol == 0
944 && operand->exp.X_op_symbol == 0)
945 {
946
947 /* No symbol involved, let's look at offset, it's dangerous if
948 any of the high bits are not 0 or ff's, find out by oring or
949 anding with the width and seeing if the answer is 0 or all
950 fs. */
951 if ((operand->exp.X_add_number & ~width) != 0 &&
952 (operand->exp.X_add_number | width) != (~0))
953 {
954 as_warn (_("operand %s0x%x out of range."),
955 string, operand->exp.X_add_number);
956 }
957 }
958
959}
960#endif
961
962static char buffer[20];
963
964static void
965newfix (ptr, type, size, operand)
966 int ptr;
967 int type;
968 int size; /* nibbles. */
969 expressionS *operand;
970{
971 if (operand->X_add_symbol
972 || operand->X_op_symbol
973 || operand->X_add_number)
974 {
975 fix_new_exp (frag_now,
976 ptr,
977 size / 2,
978 operand,
979 0,
980 type);
981 }
982}
983
984static char *
985apply_fix (ptr, type, operand, size)
986 char *ptr;
987 int type;
988 expressionS *operand;
989 int size; /* nibbles. */
990{
991 long n = operand->X_add_number;
992
993 newfix ((ptr - buffer) / 2, type, size + 1, operand);
994 switch (size)
995 {
996 case 8: /* 8 nibbles == 32 bits. */
997 *ptr++ = n >> 28;
998 *ptr++ = n >> 24;
999 *ptr++ = n >> 20;
1000 *ptr++ = n >> 16;
1001 case 4: /* 4 nibbles == 16 bits. */
1002 *ptr++ = n >> 12;
1003 *ptr++ = n >> 8;
1004 case 2:
1005 *ptr++ = n >> 4;
1006 case 1:
1007 *ptr++ = n >> 0;
1008 break;
1009 }
1010 return ptr;
1011}
1012
1013/* Now we know what sort of opcodes it is. Let's build the bytes. */
1014
1015#define INSERT(x,y) *x++ = y>>24; *x++ = y>> 16; *x++=y>>8; *x++ =y;
1016
1017static void
1018build_bytes (this_try, operand)
1019 opcode_entry_type *this_try;
1020 struct z8k_op *operand ATTRIBUTE_UNUSED;
1021{
1022 char *output_ptr = buffer;
1023 int c;
1024 int nibble;
1025 unsigned int *class_ptr;
1026
1027 frag_wane (frag_now);
1028 frag_new (0);
1029
1030 memset (buffer, 0, sizeof (buffer));
1031 class_ptr = this_try->byte_info;
1032
1033 for (nibble = 0; (c = *class_ptr++); nibble++)
1034 {
1035
1036 switch (c & CLASS_MASK)
1037 {
1038 default:
1039 abort ();
1040
1041 case CLASS_ADDRESS:
1042 /* Direct address, we don't cope with the SS mode right now. */
1043 if (segmented_mode)
1044 {
1045 /* da_operand->X_add_number |= 0x80000000; -- Now set at relocation time. */
1046 output_ptr = apply_fix (output_ptr, R_IMM32, da_operand, 8);
1047 }
1048 else
1049 {
1050 output_ptr = apply_fix (output_ptr, R_IMM16, da_operand, 4);
1051 }
1052 da_operand = 0;
1053 break;
1054 case CLASS_DISP8:
1055 /* pc rel 8 bit */
1056 output_ptr = apply_fix (output_ptr, R_JR, da_operand, 2);
1057 da_operand = 0;
1058 break;
1059
1060 case CLASS_0DISP7:
1061 /* pc rel 7 bit */
1062 *output_ptr = 0;
1063 output_ptr = apply_fix (output_ptr, R_DISP7, da_operand, 2);
1064 da_operand = 0;
1065 break;
1066
1067 case CLASS_1DISP7:
1068 /* pc rel 7 bit */
1069 *output_ptr = 0x80;
1070 output_ptr = apply_fix (output_ptr, R_DISP7, da_operand, 2);
1071 output_ptr[-2] = 0x8;
1072 da_operand = 0;
1073 break;
1074
1075 case CLASS_BIT_1OR2:
1076 *output_ptr = c & 0xf;
1077 if (imm_operand)
1078 {
1079 if (imm_operand->X_add_number == 2)
1080 *output_ptr |= 2;
1081 else if (imm_operand->X_add_number != 1)
1082 as_bad (_("immediate must be 1 or 2"));
1083 }
1084 else
1085 as_bad (_("immediate 1 or 2 expected"));
1086 output_ptr++;
1087 break;
1088 case CLASS_CC:
1089 *output_ptr++ = the_cc;
1090 break;
1091 case CLASS_0CCC:
1092 *output_ptr++ = the_ctrl;
1093 break;
1094 case CLASS_1CCC:
1095 *output_ptr++ = the_ctrl | 0x8;
1096 break;
1097 case CLASS_00II:
1098 *output_ptr++ = (~the_interrupt & 0x3);
1099 break;
1100 case CLASS_01II:
1101 *output_ptr++ = (~the_interrupt & 0x3) | 0x4;
1102 break;
1103 case CLASS_FLAGS:
1104 *output_ptr++ = the_flags;
1105 break;
1106 case CLASS_IGNORE:
1107 case CLASS_BIT:
1108 *output_ptr++ = c & 0xf;
1109 break;
1110 case CLASS_REGN0:
1111 if (reg[c & 0xf] == 0)
1112 as_bad (_("can't use R0 here"));
1113 /* Fall through. */
1114 case CLASS_REG:
1115 case CLASS_REG_BYTE:
1116 case CLASS_REG_WORD:
1117 case CLASS_REG_LONG:
1118 case CLASS_REG_QUAD:
1119 /* Insert bit mattern of right reg. */
1120 *output_ptr++ = reg[c & 0xf];
1121 break;
1122 case CLASS_DISP:
1123 switch (c & ARG_MASK)
1124 {
1125 case ARG_DISP12:
1126 output_ptr = apply_fix (output_ptr, R_CALLR, da_operand, 4);
1127 break;
1128 case ARG_DISP16:
1129 output_ptr = apply_fix (output_ptr, R_REL16, da_operand, 4);
1130 break;
1131 default:
1132 output_ptr = apply_fix (output_ptr, R_IMM16, da_operand, 4);
1133 }
1134 da_operand = 0;
1135 break;
1136
1137 case CLASS_IMM:
1138 {
1139 switch (c & ARG_MASK)
1140 {
1141 case ARG_NIM4:
1142 if (imm_operand->X_add_number > 15)
1143 {
1144 as_bad (_("immediate value out of range"));
1145 }
1146 imm_operand->X_add_number = -imm_operand->X_add_number;
1147 output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1);
1148 break;
1149 /*case ARG_IMMNMINUS1: not used. */
1150 case ARG_IMM4M1:
1151 imm_operand->X_add_number--;
1152 /* Drop through. */
1153 case ARG_IMM4:
1154 if (imm_operand->X_add_number > 15)
1155 {
1156 as_bad (_("immediate value out of range"));
1157 }
1158 output_ptr = apply_fix (output_ptr, R_IMM4L, imm_operand, 1);
1159 break;
1160 case ARG_NIM8:
1161 imm_operand->X_add_number = -imm_operand->X_add_number;
1162 /* Drop through. */
1163 case ARG_IMM8:
1164 output_ptr = apply_fix (output_ptr, R_IMM8, imm_operand, 2);
1165 break;
1166 case ARG_IMM16:
1167 output_ptr = apply_fix (output_ptr, R_IMM16, imm_operand, 4);
1168 break;
1169 case ARG_IMM32:
1170 output_ptr = apply_fix (output_ptr, R_IMM32, imm_operand, 8);
1171 break;
1172 default:
1173 abort ();
1174 }
1175 }
1176 }
1177 }
1178
1179 /* Copy from the nibble buffer into the frag. */
1180 {
1181 int length = (output_ptr - buffer) / 2;
1182 char *src = buffer;
1183 char *fragp = frag_more (length);
1184
1185 while (src < output_ptr)
1186 {
1187 *fragp = (src[0] << 4) | src[1];
1188 src += 2;
1189 fragp++;
1190 }
1191 }
1192}
1193
1194/* This is the guts of the machine-dependent assembler. STR points to a
1195 machine dependent instruction. This function is supposed to emit
1196 the frags/bytes it assembles to. */
1197
1198void
1199md_assemble (str)
1200 char *str;
1201{
1202 char c;
1203 char *op_start;
1204 char *op_end;
1205 struct z8k_op operand[3];
1206 opcode_entry_type *opcode;
1207 opcode_entry_type *prev_opcode;
1208
1209 /* Drop leading whitespace. */
1210 while (*str == ' ')
1211 str++;
1212
1213 /* Find the op code end. */
1214 for (op_start = op_end = str;
1215 *op_end != 0 && *op_end != ' ';
1216 op_end++)
1217 ;
1218
1219 if (op_end == op_start)
1220 {
1221 as_bad (_("can't find opcode "));
1222 }
1223 c = *op_end;
1224
1225 *op_end = 0;
1226
1227 opcode = (opcode_entry_type *) hash_find (opcode_hash_control, op_start);
1228
1229 if (opcode == NULL)
1230 {
1231 as_bad (_("unknown opcode"));
1232 return;
1233 }
1234
1235 if (opcode->opcode == 250)
1236 {
1237 pseudo_typeS *p;
1238 char oc;
1239 char *old = input_line_pointer;
1240 *op_end = c;
1241
1242 /* Was really a pseudo op. */
1243
1244 input_line_pointer = op_end;
1245
1246 oc = *old;
1247 *old = '\n';
1248 while (*input_line_pointer == ' ')
1249 input_line_pointer++;
1250 p = (pseudo_typeS *) (opcode->func);
1251
1252 (p->poc_handler) (p->poc_val);
1253 input_line_pointer = old;
1254 *old = oc;
1255 }
1256 else
1257 {
1258 char *new_input_line_pointer;
1259
1260 new_input_line_pointer = get_operands (opcode, op_end, operand);
1261 if (new_input_line_pointer)
1262 input_line_pointer = new_input_line_pointer;
1263 prev_opcode = opcode; /* XXX is this used ?? */
1264
1265 opcode = get_specific (opcode, operand);
1266
1267 if (opcode == 0)
1268 {
1269 /* Couldn't find an opcode which matched the operands. */
1270 char *where = frag_more (2);
1271
1272 where[0] = 0x0;
1273 where[1] = 0x0;
1274
1275 as_bad (_("Can't find opcode to match operands"));
1276 return;
1277 }
1278
1279 build_bytes (opcode, operand);
1280 }
1281}
1282
1283void
1284tc_crawl_symbol_chain (headers)
1285 object_headers *headers ATTRIBUTE_UNUSED;
1286{
1287 printf (_("call to tc_crawl_symbol_chain \n"));
1288}
1289
1290/* We have no need to default values of symbols. */
1291
1292symbolS *
1293md_undefined_symbol (name)
1294 char *name ATTRIBUTE_UNUSED;
1295{
1296 return 0;
1297}
1298
1299void
1300tc_headers_hook (headers)
1301 object_headers *headers ATTRIBUTE_UNUSED;
1302{
1303 printf (_("call to tc_headers_hook \n"));
1304}
1305
1306/* Various routines to kill one day. */
1307/* Equal to MAX_PRECISION in atof-ieee.c. */
1308#define MAX_LITTLENUMS 6
1309
1310/* Turn a string in input_line_pointer into a floating point constant
1311 of type TYPE, and store the appropriate bytes in *LITP. The number
1312 of LITTLENUMS emitted is stored in *SIZEP. An error message is
1313 returned, or NULL on OK. */
1314
1315char *
1316md_atof (type, litP, sizeP)
1317 char type;
1318 char *litP;
1319 int *sizeP;
1320{
1321 int prec;
1322 LITTLENUM_TYPE words[MAX_LITTLENUMS];
1323 LITTLENUM_TYPE *wordP;
1324 char *t;
1325
1326 switch (type)
1327 {
1328 case 'f':
1329 case 'F':
1330 case 's':
1331 case 'S':
1332 prec = 2;
1333 break;
1334
1335 case 'd':
1336 case 'D':
1337 case 'r':
1338 case 'R':
1339 prec = 4;
1340 break;
1341
1342 case 'x':
1343 case 'X':
1344 prec = 6;
1345 break;
1346
1347 case 'p':
1348 case 'P':
1349 prec = 6;
1350 break;
1351
1352 default:
1353 *sizeP = 0;
1354 return _("Bad call to MD_ATOF()");
1355 }
1356 t = atof_ieee (input_line_pointer, type, words);
1357 if (t)
1358 input_line_pointer = t;
1359
1360 *sizeP = prec * sizeof (LITTLENUM_TYPE);
1361 for (wordP = words; prec--;)
1362 {
1363 md_number_to_chars (litP, (long) (*wordP++), sizeof (LITTLENUM_TYPE));
1364 litP += sizeof (LITTLENUM_TYPE);
1365 }
1366 return 0;
1367}
1368
1369
1370const char *md_shortopts = "z:";
1371
1372struct option md_longopts[] =
1373 {
1374#define OPTION_RELAX (OPTION_MD_BASE)
1375 {"linkrelax", no_argument, NULL, OPTION_RELAX},
1376 {NULL, no_argument, NULL, 0}
1377 };
1378
1379size_t md_longopts_size = sizeof (md_longopts);
1380
1381int
1382md_parse_option (c, arg)
1383 int c;
1384 char *arg;
1385{
1386 switch (c)
1387 {
1388 case 'z':
1389 if (!strcmp (arg, "8001"))
1390 s_segm (1);
1391 else if (!strcmp (arg, "8002"))
1392 s_segm (0);
1393 else
1394 {
1395 as_bad (_("invalid architecture -z%s"), arg);
1396 return 0;
1397 }
1398 z8k_target_from_cmdline = 1;
1399 break;
1400
1401 case OPTION_RELAX:
1402 linkrelax = 1;
1403 break;
1404
1405 default:
1406 return 0;
1407 }
1408
1409 return 1;
1410}
1411
1412void
1413md_show_usage (stream)
1414 FILE *stream;
1415{
1416 fprintf (stream, _("\
1417 Z8K options:\n\
1418 -z8001 generate segmented code\n\
1419 -z8002 generate unsegmented code\n\
1420 -linkrelax create linker relaxable code\n"));
1421}
1422
1423
1424void
1425md_convert_frag (headers, seg, fragP)
1426 object_headers *headers ATTRIBUTE_UNUSED;
1427 segT seg ATTRIBUTE_UNUSED;
1428 fragS *fragP ATTRIBUTE_UNUSED;
1429{
1430 printf (_("call to md_convert_frag\n"));
1431 abort ();
1432}
1433
1434valueT
1435md_section_align (seg, size)
1436 segT seg;
1437 valueT size;
1438{
1439 return ((size + (1 << section_alignment[(int) seg]) - 1)
1440 & (-1 << section_alignment[(int) seg]));
1441}
1442
1443void
1444md_apply_fix3 (fixP, valP, segment)
1445 fixS * fixP;
1446 valueT * valP;
1447 segT segment ATTRIBUTE_UNUSED;
1448{
1449 long val = * (long *) valP;
1450 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
1451
1452 switch (fixP->fx_r_type)
1453 {
1454 case R_IMM4L:
1455 buf[0] = (buf[0] & 0xf0) | (val & 0xf);
1456 break;
1457
1458 case R_JR:
1459 val = val - fixP->fx_frag->fr_address + fixP->fx_where - fixP->fx_size;
1460 if (val & 1)
1461 as_bad (_("cannot branch to odd address"));
1462 val /= 2;
1463 if (val > 127 || val < -128)
1464 as_bad (_("relative jump out of range"));
1465 *buf++ = val;
1466 fixP->fx_no_overflow = 1;
1467 break;
1468
1469 case R_DISP7:
1470 val = val - fixP->fx_frag->fr_address + fixP->fx_where - fixP->fx_size;
1471 if (val & 1)
1472 as_bad (_("cannot branch to odd address"));
1473 val /= 2;
1474 if (val > 0 || val < -128)
1475 as_bad (_("relative jump out of range"));
1476 *buf = (*buf & 0x80) | (val & 0x7f);
1477 fixP->fx_no_overflow = 1;
1478 break;
1479
1480 case R_CALLR:
1481 if (val > 8191 || val < -8192)
1482 as_bad (_("relative call out of range"));
1483 val = -val;
1484 *buf++ = (buf[0] & 0xf0) | ((val >> 8) & 0xf);
1485 *buf++ = val & 0xff;
1486 break;
1487
1488 case R_IMM8:
1489 *buf++ = val;
1490 break;
1491
1492 case R_IMM16:
1493 *buf++ = (val >> 8);
1494 *buf++ = val;
1495 break;
1496
1497 case R_IMM32:
1498 *buf++ = (val >> 24);
1499 *buf++ = (val >> 16);
1500 *buf++ = (val >> 8);
1501 *buf++ = val;
1502 break;
1503
1504 case R_REL16:
1505 val = val - fixP->fx_frag->fr_address + fixP->fx_where - fixP->fx_size;
1506 if (val > 32767 || val < -32768)
1507 as_bad (_("relative address out of range"));
1508 *buf++ = (val >> 8);
1509 *buf++ = val;
1510 fixP->fx_no_overflow = 1;
1511 break;
1512
1513#if 0
1514 case R_DA | R_SEG:
1515 *buf++ = (val >> 16);
1516 *buf++ = 0x00;
1517 *buf++ = (val >> 8);
1518 *buf++ = val;
1519 break;
1520#endif
1521
1522 case 0:
1523 md_number_to_chars (buf, val, fixP->fx_size);
1524 break;
1525
1526 default:
1527 printf(_("md_apply_fix3: unknown r_type 0x%x\n"), fixP->fx_r_type);
1528 abort ();
1529 }
1530
1531 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
1532 fixP->fx_done = 1;
1533}
1534
1535int
1536md_estimate_size_before_relax (fragP, segment_type)
1537 register fragS *fragP ATTRIBUTE_UNUSED;
1538 register segT segment_type ATTRIBUTE_UNUSED;
1539{
1540 printf (_("call to md_estimate_size_before_relax\n"));
1541 abort ();
1542}
1543
1544/* Put number into target byte order. */
1545
1546void
1547md_number_to_chars (ptr, use, nbytes)
1548 char *ptr;
1549 valueT use;
1550 int nbytes;
1551{
1552 number_to_chars_bigendian (ptr, use, nbytes);
1553}
1554
1555long
1556md_pcrel_from (fixP)
1557 fixS *fixP ATTRIBUTE_UNUSED;
1558{
1559 abort ();
1560}
1561
1562void
1563tc_coff_symbol_emit_hook (s)
1564 symbolS *s ATTRIBUTE_UNUSED;
1565{
1566}
1567
1568void
1569tc_reloc_mangle (fix_ptr, intr, base)
1570 fixS *fix_ptr;
1571 struct internal_reloc *intr;
1572 bfd_vma base;
1573
1574{
1575 symbolS *symbol_ptr;
1576
1577 if (fix_ptr->fx_addsy
1578 && fix_ptr->fx_subsy)
1579 {
1580 symbolS *add = fix_ptr->fx_addsy;
1581 symbolS *sub = fix_ptr->fx_subsy;
1582
1583 if (S_GET_SEGMENT (add) != S_GET_SEGMENT (sub))
1584 as_bad (_("Can't subtract symbols in different sections %s %s"),
1585 S_GET_NAME (add), S_GET_NAME (sub));
1586 else
1587 {
1588 int diff = S_GET_VALUE (add) - S_GET_VALUE (sub);
1589
1590 fix_ptr->fx_addsy = 0;
1591 fix_ptr->fx_subsy = 0;
1592 fix_ptr->fx_offset += diff;
1593 }
1594 }
1595 symbol_ptr = fix_ptr->fx_addsy;
1596
1597 /* If this relocation is attached to a symbol then it's ok
1598 to output it. */
1599 if (fix_ptr->fx_r_type == 0)
1600 {
1601 /* cons likes to create reloc32's whatever the size of the reloc. */
1602 switch (fix_ptr->fx_size)
1603 {
1604 case 2:
1605 intr->r_type = R_IMM16;
1606 break;
1607 case 1:
1608 intr->r_type = R_IMM8;
1609 break;
1610 case 4:
1611 intr->r_type = R_IMM32;
1612 break;
1613 default:
1614 abort ();
1615 }
1616 }
1617 else
1618 intr->r_type = fix_ptr->fx_r_type;
1619
1620 intr->r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where + base;
1621 intr->r_offset = fix_ptr->fx_offset;
1622
1623 if (symbol_ptr)
1624 intr->r_symndx = symbol_ptr->sy_number;
1625 else
1626 intr->r_symndx = -1;
1627}
Note: See TracBrowser for help on using the repository browser.