source: trunk/binutils/gas/config/tc-w65.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: 21.9 KB
Line 
1/* tc-w65.c -- Assemble code for the W65816
2 Copyright 1995, 1998, 2000, 2001, 2002 Free Software Foundation, Inc.
3
4 This file is part of GAS, the GNU Assembler.
5
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 2, or (at your option)
9 any later version.
10
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.
15
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 the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
20
21/* Written By Steve Chamberlain <sac@cygnus.com>. */
22
23#include <stdio.h>
24#include "as.h"
25#include "bfd.h"
26#include "subsegs.h"
27#define DEFINE_TABLE
28#include "../opcodes/w65-opc.h"
29
30const char comment_chars[] = "!";
31const char line_separator_chars[] = ";";
32const char line_comment_chars[] = "!#";
33
34/* This table describes all the machine specific pseudo-ops the assembler
35 has to support. The fields are:
36
37 pseudo-op name without dot
38 function to call to execute this pseudo-op
39 Integer arg to pass to the function */
40
41#define OP_BCC 0x90
42#define OP_BCS 0xB0
43#define OP_BEQ 0xF0
44#define OP_BMI 0x30
45#define OP_BNE 0xD0
46#define OP_BPL 0x10
47#define OP_BRA 0x80
48#define OP_BRL 0x82
49#define OP_BVC 0x50
50#define OP_BVS 0x70
51
52static void s_longa PARAMS ((int));
53static char *parse_exp PARAMS ((char *));
54static char *get_operands PARAMS ((const struct opinfo *, char *));
55static const struct opinfo *get_specific PARAMS ((const struct opinfo *));
56static void build_Mytes PARAMS ((const struct opinfo *));
57
58
59const pseudo_typeS md_pseudo_table[] = {
60 {"int", cons, 2},
61 {"word", cons, 2},
62 {"longa", s_longa, 0},
63 {"longi", s_longa, 1},
64 {0, 0, 0}
65};
66
67#if 0
68int md_reloc_size;
69#endif
70
71const char EXP_CHARS[] = "eE";
72
73/* Chars that mean this number is a floating point constant. */
74/* As in 0f12.456 */
75/* or 0d1.2345e12 */
76const char FLT_CHARS[] = "rRsSfFdDxXpP";
77
78/* Opcode mnemonics */
79static struct hash_control *opcode_hash_control;
80
81int M; /* M flag */
82int X; /* X flag */
83
84#define C(a,b) ENCODE_RELAX(a,b)
85#define ENCODE_RELAX(what,length) (((what) << 2) + (length))
86
87#define GET_WHAT(x) ((x>>2))
88
89#define BYTE_DISP 1
90#define WORD_DISP 2
91#define UNDEF_BYTE_DISP 0
92#define UNDEF_WORD_DISP 3
93
94#define COND_BRANCH 1
95#define UNCOND_BRANCH 2
96#define END 3
97
98#define BYTE_F 127 /* How far we can branch forwards */
99#define BYTE_B -126 /* How far we can branch backwards */
100#define WORD_F 32767
101#define WORD_B 32768
102
103relax_typeS md_relax_table[C (END, 0)] = {
104 { 0, 0, 0, 0 },
105 { 0, 0, 0, 0 },
106 { 0, 0, 0, 0 },
107 { 0, 0, 0, 0 },
108
109 /* COND_BRANCH */
110 { 0, 0, 0, 0 }, /* UNDEF_BYTE_DISP */
111 { BYTE_F, BYTE_B, 2, C (COND_BRANCH, WORD_DISP) }, /* BYTE_DISP */
112 { WORD_F, WORD_B, 5, 0 }, /* WORD_DISP */
113 { 0, 0, 5, 0 }, /* UNDEF_WORD_DISP */
114
115 /* UNCOND_BRANCH */
116 { 0, 0, 0, 0 }, /* UNDEF_BYTE_DISP */
117 { BYTE_F, BYTE_B, 2, C (UNCOND_BRANCH, WORD_DISP) }, /* BYTE_DISP */
118 { WORD_F, WORD_B, 3, 0 }, /* WORD_DISP */
119 { 0, 0, 3, 0 } /* UNDEF_WORD_DISP */
120
121};
122
123/* This function is called once, at assembler startup time. This
124 should set up all the tables, etc that the MD part of the assembler
125 needs. */
126
127static void
128s_longa (xmode)
129 int xmode;
130{
131 int *p = xmode ? &X : &M;
132 while (*input_line_pointer == ' ')
133 input_line_pointer++;
134 if (strncmp (input_line_pointer, "on", 2) == 0)
135 {
136 input_line_pointer += 2;
137 *p = 0;
138 }
139 else if (strncmp (input_line_pointer, "off", 3) == 0)
140 {
141 *p = 1;
142 input_line_pointer += 3;
143 }
144 else
145 as_bad (_("need on or off."));
146 demand_empty_rest_of_line ();
147}
148
149void
150md_begin ()
151{
152 const struct opinfo *opcode;
153 char *prev_name = "";
154
155 opcode_hash_control = hash_new ();
156
157 /* Insert unique names into hash table. */
158 for (opcode = optable; opcode->name; opcode++)
159 {
160 if (strcmp (prev_name, opcode->name))
161 {
162 prev_name = opcode->name;
163 hash_insert (opcode_hash_control, opcode->name, (char *) opcode);
164 }
165 }
166
167 flag_signed_overflow_ok = 1;
168}
169
170static expressionS immediate; /* absolute expression */
171static expressionS immediate1; /* absolute expression */
172int expr_size;
173int expr_shift;
174int tc_cons_reloc;
175
176void
177w65_expression (dest)
178 expressionS *dest;
179{
180 expr_size = 0;
181 expr_shift = 0;
182 tc_cons_reloc = 0;
183 while (*input_line_pointer == ' ')
184 input_line_pointer++;
185
186 if (*input_line_pointer == '<')
187 {
188 expr_size = 1;
189 input_line_pointer++;
190 }
191 else if (*input_line_pointer == '>')
192 {
193 expr_shift = 1;
194 input_line_pointer++;
195 }
196 else if (*input_line_pointer == '^')
197 {
198 expr_shift = 2;
199 input_line_pointer++;
200 }
201
202 expr (0, dest);
203}
204
205int amode;
206
207static char *
208parse_exp (s)
209 char *s;
210{
211 char *save;
212 char *new;
213
214 save = input_line_pointer;
215 input_line_pointer = s;
216 w65_expression (&immediate);
217 if (immediate.X_op == O_absent)
218 as_bad (_("missing operand"));
219 new = input_line_pointer;
220 input_line_pointer = save;
221 return new;
222}
223
224static char *
225get_operands (info, ptr)
226 const struct opinfo *info;
227 char *ptr;
228{
229 register int override_len = 0;
230 register int bytes = 0;
231
232 while (*ptr == ' ')
233 ptr++;
234
235 if (ptr[0] == '#')
236 {
237 ptr++;
238 switch (info->amode)
239 {
240 case ADDR_IMMTOI:
241 bytes = X ? 1 : 2;
242 amode = ADDR_IMMTOI;
243 break;
244 case ADDR_IMMTOA:
245 bytes = M ? 1 : 2;
246 amode = ADDR_IMMTOA;
247 break;
248 case ADDR_IMMCOP:
249 bytes = 1;
250 amode = ADDR_IMMCOP;
251 break;
252 case ADDR_DIR:
253 bytes = 2;
254 amode = ADDR_ABS;
255 break;
256 default:
257 abort ();
258 break;
259 }
260 ptr = parse_exp (ptr);
261 }
262 else if (ptr[0] == '!')
263 {
264 ptr = parse_exp (ptr + 1);
265 if (ptr[0] == ',')
266 {
267 if (ptr[1] == 'y')
268 {
269 amode = ADDR_ABS_IDX_Y;
270 bytes = 2;
271 ptr += 2;
272 }
273 else if (ptr[1] == 'x')
274 {
275 amode = ADDR_ABS_IDX_X;
276 bytes = 2;
277 ptr += 2;
278 }
279 else
280 {
281 as_bad (_("syntax error after <exp"));
282 }
283 }
284 else
285 {
286 amode = ADDR_ABS;
287 bytes = 2;
288 }
289 }
290 else if (ptr[0] == '>')
291 {
292 ptr = parse_exp (ptr + 1);
293 if (ptr[0] == ',' && ptr[1] == 'x')
294 {
295 amode = ADDR_ABS_LONG_IDX_X;
296 bytes = 3;
297 ptr += 2;
298 }
299 else
300 {
301 amode = ADDR_ABS_LONG;
302 bytes = 3;
303 }
304 }
305 else if (ptr[0] == '<')
306 {
307 ptr = parse_exp (ptr + 1);
308 if (ptr[0] == ',')
309 {
310 if (ptr[1] == 'y')
311 {
312 amode = ADDR_DIR_IDX_Y;
313 ptr += 2;
314 bytes = 2;
315 }
316 else if (ptr[1] == 'x')
317 {
318 amode = ADDR_DIR_IDX_X;
319 ptr += 2;
320 bytes = 2;
321 }
322 else
323 {
324 as_bad (_("syntax error after <exp"));
325 }
326 }
327 else
328 {
329 amode = ADDR_DIR;
330 bytes = 1;
331 }
332 }
333 else if (ptr[0] == 'a')
334 {
335 amode = ADDR_ACC;
336 }
337 else if (ptr[0] == '(')
338 {
339 /* Look for (exp),y
340 (<exp),y
341 (exp,x)
342 (<exp,x)
343 (exp)
344 (!exp)
345 (exp)
346 (<exp)
347 (exp,x)
348 (!exp,x)
349 (exp,s)
350 (exp,s),y */
351
352 ptr++;
353 if (ptr[0] == '<')
354 {
355 override_len = 1;
356 ptr++;
357 }
358 else if (ptr[0] == '!')
359 {
360 override_len = 2;
361 ptr++;
362 }
363 else if (ptr[0] == '>')
364 {
365 override_len = 3;
366 ptr++;
367 }
368 else
369 {
370 override_len = 0;
371 }
372 ptr = parse_exp (ptr);
373
374 if (ptr[0] == ',')
375 {
376 ptr++;
377 if (ptr[0] == 'x' && ptr[1] == ')')
378 {
379 ptr += 2;
380
381 if (override_len == 1)
382 {
383 amode = ADDR_DIR_IDX_IND_X;
384 bytes = 2;
385 }
386 else
387 {
388 amode = ADDR_ABS_IND_IDX;
389 bytes = 2;
390 }
391 }
392 else if (ptr[0] == 's' && ptr[1] == ')'
393 && ptr[2] == ',' && ptr[3] == 'y')
394 {
395 amode = ADDR_STACK_REL_INDX_IDX;
396 bytes = 1;
397 ptr += 4;
398 }
399 }
400 else if (ptr[0] == ')')
401 {
402 if (ptr[1] == ',' && ptr[2] == 'y')
403 {
404 amode = ADDR_DIR_IND_IDX_Y;
405 ptr += 3;
406 bytes = 2;
407 }
408 else
409 {
410 if (override_len == 1)
411 {
412 amode = ADDR_DIR_IND;
413 bytes = 1;
414 }
415 else
416 {
417 amode = ADDR_ABS_IND;
418 bytes = 2;
419 }
420 ptr++;
421
422 }
423 }
424 }
425 else if (ptr[0] == '[')
426 {
427 ptr = parse_exp (ptr + 1);
428 if (ptr[0] == ']')
429 {
430 ptr++;
431 if (ptr[0] == ',' && ptr[1] == 'y')
432 {
433 bytes = 1;
434 amode = ADDR_DIR_IND_IDX_Y_LONG;
435 ptr += 2;
436 }
437 else
438 {
439 if (info->code == O_jmp)
440 {
441 bytes = 2;
442 amode = ADDR_ABS_IND_LONG;
443 }
444 else
445 {
446 bytes = 1;
447 amode = ADDR_DIR_IND_LONG;
448 }
449 }
450 }
451 }
452 else
453 {
454 ptr = parse_exp (ptr);
455 if (ptr[0] == ',')
456 {
457 if (ptr[1] == 'y')
458 {
459 if (override_len == 1)
460 {
461 bytes = 1;
462 amode = ADDR_DIR_IDX_Y;
463 }
464 else
465 {
466 amode = ADDR_ABS_IDX_Y;
467 bytes = 2;
468 }
469 ptr += 2;
470 }
471 else if (ptr[1] == 'x')
472 {
473 if (override_len == 1)
474 {
475 amode = ADDR_DIR_IDX_X;
476 bytes = 1;
477 }
478 else
479 {
480 amode = ADDR_ABS_IDX_X;
481 bytes = 2;
482 }
483 ptr += 2;
484 }
485 else if (ptr[1] == 's')
486 {
487 bytes = 1;
488 amode = ADDR_STACK_REL;
489 ptr += 2;
490 }
491 else
492 {
493 bytes = 1;
494 immediate1 = immediate;
495 ptr = parse_exp (ptr + 1);
496 amode = ADDR_BLOCK_MOVE;
497 }
498 }
499 else
500 {
501 switch (info->amode)
502 {
503 case ADDR_PC_REL:
504 amode = ADDR_PC_REL;
505 bytes = 1;
506 break;
507 case ADDR_PC_REL_LONG:
508 amode = ADDR_PC_REL_LONG;
509 bytes = 2;
510 break;
511 default:
512 if (override_len == 1)
513 {
514 amode = ADDR_DIR;
515 bytes = 1;
516 }
517 else if (override_len == 3)
518 {
519 bytes = 3;
520 amode = ADDR_ABS_LONG;
521 }
522 else
523 {
524 amode = ADDR_ABS;
525 bytes = 2;
526 }
527 }
528 }
529 }
530
531 switch (bytes)
532 {
533 case 1:
534 switch (expr_shift)
535 {
536 case 0:
537 if (amode == ADDR_DIR)
538 tc_cons_reloc = R_W65_DP;
539 else
540 tc_cons_reloc = R_W65_ABS8;
541 break;
542 case 1:
543 tc_cons_reloc = R_W65_ABS8S8;
544 break;
545 case 2:
546 tc_cons_reloc = R_W65_ABS8S16;
547 break;
548 }
549 break;
550 case 2:
551 switch (expr_shift)
552 {
553 case 0:
554 tc_cons_reloc = R_W65_ABS16;
555 break;
556 case 1:
557 tc_cons_reloc = R_W65_ABS16S8;
558 break;
559 case 2:
560 tc_cons_reloc = R_W65_ABS16S16;
561 break;
562 }
563 }
564 return ptr;
565}
566
567/* Passed a pointer to a list of opcodes which use different
568 addressing modes, return the opcode which matches the opcodes
569 provided. */
570
571static const struct opinfo *
572get_specific (opcode)
573 const struct opinfo *opcode;
574{
575 int ocode = opcode->code;
576
577 for (; opcode->code == ocode; opcode++)
578 {
579 if (opcode->amode == amode)
580 return opcode;
581 }
582 return 0;
583}
584
585/* Now we know what sort of opcodes it is, let's build the bytes. */
586
587static void
588build_Mytes (opcode)
589 const struct opinfo *opcode;
590{
591 int size;
592 int type;
593 int pcrel;
594 char *output;
595
596 if (opcode->amode == ADDR_IMPLIED)
597 {
598 output = frag_more (1);
599 }
600 else if (opcode->amode == ADDR_PC_REL)
601 {
602 int type;
603
604 /* This is a relaxable insn, so we do some special handling. */
605 type = opcode->val == OP_BRA ? UNCOND_BRANCH : COND_BRANCH;
606 output = frag_var (rs_machine_dependent,
607 md_relax_table[C (type, WORD_DISP)].rlx_length,
608 md_relax_table[C (type, BYTE_DISP)].rlx_length,
609 C (type, UNDEF_BYTE_DISP),
610 immediate.X_add_symbol,
611 immediate.X_add_number,
612 0);
613 }
614 else
615 {
616 switch (opcode->amode)
617 {
618 GETINFO (size, type, pcrel);
619 default:
620 abort ();
621 }
622
623 /* If something special was done in the expression modify the
624 reloc type. */
625 if (tc_cons_reloc)
626 type = tc_cons_reloc;
627
628 /* 1 byte for the opcode + the bytes for the addrmode. */
629 output = frag_more (size + 1);
630
631 if (opcode->amode == ADDR_BLOCK_MOVE)
632 {
633 /* Two relocs for this one. */
634 fix_new_exp (frag_now,
635 output + 1 - frag_now->fr_literal,
636 1,
637 &immediate,
638 0,
639 R_W65_ABS8S16);
640
641 fix_new_exp (frag_now,
642 output + 2 - frag_now->fr_literal,
643 1,
644 &immediate1,
645 0,
646 R_W65_ABS8S16);
647 }
648 else if (type >= 0
649 && opcode->amode != ADDR_IMPLIED
650 && opcode->amode != ADDR_ACC
651 && opcode->amode != ADDR_STACK)
652 {
653 fix_new_exp (frag_now,
654 output + 1 - frag_now->fr_literal,
655 size,
656 &immediate,
657 pcrel,
658 type);
659 }
660 }
661 output[0] = opcode->val;
662}
663
664/* This is the guts of the machine-dependent assembler. STR points to
665 a machine dependent instruction. This function is supposed to emit
666 the frags/bytes it assembles to. */
667
668void
669md_assemble (str)
670 char *str;
671{
672 const struct opinfo *opcode;
673 char name[20];
674
675 /* Drop leading whitespace */
676 while (*str == ' ')
677 str++;
678
679 /* all opcodes are three letters */
680 name[0] = str[0];
681 name[1] = str[1];
682 name[2] = str[2];
683 name[3] = 0;
684
685 tc_cons_reloc = 0;
686 str += 3;
687 opcode = (struct opinfo *) hash_find (opcode_hash_control, name);
688
689 if (opcode == NULL)
690 {
691 as_bad (_("unknown opcode"));
692 return;
693 }
694
695 if (opcode->amode != ADDR_IMPLIED
696 && opcode->amode != ADDR_STACK)
697 {
698 get_operands (opcode, str);
699 opcode = get_specific (opcode);
700 }
701
702 if (opcode == 0)
703 {
704 /* Couldn't find an opcode which matched the operands. */
705
706 char *where = frag_more (1);
707
708 where[0] = 0x0;
709 where[1] = 0x0;
710 as_bad (_("invalid operands for opcode"));
711 return;
712 }
713
714 build_Mytes (opcode);
715}
716
717symbolS *
718md_undefined_symbol (name)
719 char *name ATTRIBUTE_UNUSED;
720{
721 return 0;
722}
723
724/* Various routines to kill one day. */
725/* Equal to MAX_PRECISION in atof-ieee.c. */
726#define MAX_LITTLENUMS 6
727
728/* Turn a string in input_line_pointer into a floating point constant
729 of type TYPE, and store the appropriate bytes in *LITP. The number
730 of LITTLENUMS emitted is stored in *SIZEP. An error message is
731 returned, or NULL on OK. */
732
733char *
734md_atof (type, litP, sizeP)
735 char type;
736 char *litP;
737 int *sizeP;
738{
739 int prec;
740 LITTLENUM_TYPE words[MAX_LITTLENUMS];
741 LITTLENUM_TYPE *wordP;
742 char *t;
743
744 switch (type)
745 {
746 case 'f':
747 case 'F':
748 case 's':
749 case 'S':
750 prec = 2;
751 break;
752
753 case 'd':
754 case 'D':
755 case 'r':
756 case 'R':
757 prec = 4;
758 break;
759
760 case 'x':
761 case 'X':
762 prec = 6;
763 break;
764
765 case 'p':
766 case 'P':
767 prec = 6;
768 break;
769
770 default:
771 *sizeP = 0;
772 return _("Bad call to MD_NTOF()");
773 }
774 t = atof_ieee (input_line_pointer, type, words);
775 if (t)
776 input_line_pointer = t;
777
778 *sizeP = prec * sizeof (LITTLENUM_TYPE);
779 for (wordP = words + prec - 1; prec--;)
780 {
781 md_number_to_chars (litP, (valueT) (*wordP--), sizeof (LITTLENUM_TYPE));
782 litP += sizeof (LITTLENUM_TYPE);
783 }
784 return 0;
785}
786
787int
788md_parse_option (c, a)
789 int c ATTRIBUTE_UNUSED;
790 char *a ATTRIBUTE_UNUSED;
791{
792 return 0;
793}
794
795/* Called after relaxing, change the frags so they know how big they
796 are. */
797
798void
799md_convert_frag (headers, seg, fragP)
800 object_headers *headers ATTRIBUTE_UNUSED;
801 segT seg ATTRIBUTE_UNUSED;
802 fragS *fragP;
803{
804 int disp_size = 0;
805 int inst_size = 0;
806 unsigned char *buffer =
807 (unsigned char *) (fragP->fr_fix + fragP->fr_literal);
808
809 switch (fragP->fr_subtype)
810 {
811 case C (COND_BRANCH, BYTE_DISP):
812 case C (UNCOND_BRANCH, BYTE_DISP):
813 disp_size = 1;
814 inst_size = 1;
815 break;
816
817 /* Conditional branches to a known 16 bit displacement. */
818 case C (COND_BRANCH, WORD_DISP):
819 switch (buffer[0])
820 {
821 case OP_BCC:
822 case OP_BCS:
823 case OP_BEQ:
824 case OP_BMI:
825 case OP_BNE:
826 case OP_BPL:
827 case OP_BVS:
828 case OP_BVC:
829 /* Invert the sense of the test */
830 buffer[0] ^= 0x20;
831 buffer[1] = 3; /* Jump over following brl */
832 buffer[2] = OP_BRL;
833 buffer[3] = 0;
834 buffer[4] = 0;
835 disp_size = 2;
836 inst_size = 3;
837 break;
838 default:
839 abort ();
840 }
841 break;
842 case C (UNCOND_BRANCH, WORD_DISP):
843 /* Unconditional branches to a known 16 bit displacement. */
844
845 switch (buffer[0])
846 {
847 case OP_BRA:
848 buffer[0] = OP_BRL;
849 disp_size = 2;
850 inst_size = 1;
851 break;
852 default:
853 abort ();
854 }
855 break;
856 /* Got to create a branch over a reloc here. */
857 case C (COND_BRANCH, UNDEF_WORD_DISP):
858 buffer[0] ^= 0x20; /* invert test */
859 buffer[1] = 3;
860 buffer[2] = OP_BRL;
861 buffer[3] = 0;
862 buffer[4] = 0;
863 fix_new (fragP,
864 fragP->fr_fix + 3,
865 4,
866 fragP->fr_symbol,
867 fragP->fr_offset,
868 0,
869 R_W65_PCR16);
870
871 fragP->fr_fix += disp_size + inst_size;
872 fragP->fr_var = 0;
873 break;
874 case C (UNCOND_BRANCH, UNDEF_WORD_DISP):
875 buffer[0] = OP_BRL;
876 buffer[1] = 0;
877 buffer[2] = 0;
878 fix_new (fragP,
879 fragP->fr_fix + 1,
880 4,
881 fragP->fr_symbol,
882 fragP->fr_offset,
883 0,
884 R_W65_PCR16);
885
886 fragP->fr_fix += disp_size + inst_size;
887 fragP->fr_var = 0;
888 break;
889 default:
890 abort ();
891 }
892 if (inst_size)
893 {
894 /* Get the address of the end of the instruction. */
895 int next_inst = (fragP->fr_fix + fragP->fr_address
896 + disp_size + inst_size);
897 int targ_addr = (S_GET_VALUE (fragP->fr_symbol) +
898 fragP->fr_offset);
899 int disp = targ_addr - next_inst;
900
901 md_number_to_chars (buffer + inst_size, disp, disp_size);
902 fragP->fr_fix += disp_size + inst_size;
903 fragP->fr_var = 0;
904 }
905}
906
907valueT
908md_section_align (seg, size)
909 segT seg;
910 valueT size;
911{
912 return ((size + (1 << section_alignment[(int) seg]) - 1)
913 & (-1 << section_alignment[(int) seg]));
914}
915
916void
917md_apply_fix3 (fixP, valP, seg)
918 fixS *fixP;
919 valueT * valP;
920 segT seg ATTRIBUTE_UNUSED;
921{
922 long val = * (long *) valP;
923 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
924 int addr = fixP->fx_frag->fr_address + fixP->fx_where;
925
926 if (fixP->fx_r_type == 0)
927 {
928 if (fixP->fx_size == 1)
929 fixP->fx_r_type = R_W65_ABS8;
930 else
931 fixP->fx_r_type = R_W65_ABS16;
932 }
933
934 switch (fixP->fx_r_type)
935 {
936 case R_W65_ABS8S16:
937 val >>= 8;
938 case R_W65_ABS8S8:
939 val >>= 8;
940 case R_W65_ABS8:
941 *buf++ = val;
942 break;
943 case R_W65_ABS16S16:
944 val >>= 8;
945 case R_W65_ABS16S8:
946 val >>= 8;
947 case R_W65_ABS16:
948 *buf++ = val >> 0;
949 *buf++ = val >> 8;
950 break;
951 case R_W65_ABS24:
952 *buf++ = val >> 0;
953 *buf++ = val >> 8;
954 *buf++ = val >> 16;
955 break;
956 case R_W65_PCR8:
957 *buf++ = val - addr - 1;
958 break;
959 case R_W65_PCR16:
960 val = val - addr - 1;
961 *buf++ = val;
962 *buf++ = val >> 8;
963 break;
964 case R_W65_DP:
965 *buf++ = val;
966 break;
967
968 default:
969 abort ();
970 }
971
972 if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
973 fixP->fx_done = 1;
974}
975
976/* Put number into target byte order. */
977
978void
979md_number_to_chars (ptr, use, nbytes)
980 char *ptr;
981 valueT use;
982 int nbytes;
983{
984 number_to_chars_littleendian (ptr, use, nbytes);
985}
986
987long
988md_pcrel_from (fixP)
989 fixS *fixP;
990{
991 int gap = fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address - 1;
992 return gap;
993}
994
995void
996tc_coff_symbol_emit_hook (x)
997 symbolS *x ATTRIBUTE_UNUSED;
998{
999}
1000
1001short
1002tc_coff_fix2rtype (fix_ptr)
1003 fixS *fix_ptr;
1004{
1005 return fix_ptr->fx_r_type;
1006}
1007
1008void
1009tc_reloc_mangle (fix_ptr, intr, base)
1010 fixS *fix_ptr;
1011 struct internal_reloc *intr;
1012 bfd_vma base;
1013
1014{
1015 symbolS *symbol_ptr;
1016
1017 symbol_ptr = fix_ptr->fx_addsy;
1018
1019 /* If this relocation is attached to a symbol then it's ok
1020 to output it */
1021 if (fix_ptr->fx_r_type == RELOC_32)
1022 {
1023 /* cons likes to create reloc32's whatever the size of the reloc..
1024 */
1025 switch (fix_ptr->fx_size)
1026 {
1027 case 2:
1028 intr->r_type = R_IMM16;
1029 break;
1030 case 1:
1031 intr->r_type = R_IMM8;
1032 break;
1033 default:
1034 abort ();
1035 }
1036 }
1037 else
1038 {
1039 if (fix_ptr->fx_size == 4)
1040 intr->r_type = R_W65_ABS24;
1041 else
1042 intr->r_type = fix_ptr->fx_r_type;
1043 }
1044
1045 intr->r_vaddr = fix_ptr->fx_frag->fr_address + fix_ptr->fx_where + base;
1046 intr->r_offset = fix_ptr->fx_offset;
1047
1048 /* Turn the segment of the symbol into an offset. */
1049 if (symbol_ptr)
1050 {
1051 symbolS *dot;
1052
1053 dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot;
1054 if (dot)
1055 {
1056 intr->r_offset += S_GET_VALUE (symbol_ptr);
1057 intr->r_symndx = dot->sy_number;
1058 }
1059 else
1060 {
1061 intr->r_symndx = symbol_ptr->sy_number;
1062 }
1063 }
1064 else
1065 {
1066 intr->r_symndx = -1;
1067 }
1068}
1069
1070int
1071tc_coff_sizemachdep (frag)
1072 fragS *frag;
1073{
1074 return md_relax_table[frag->fr_subtype].rlx_length;
1075}
1076
1077/* Called just before address relaxation, return the length by which a
1078 fragment must grow to reach it's destination. */
1079
1080int
1081md_estimate_size_before_relax (fragP, segment_type)
1082 register fragS *fragP;
1083 register segT segment_type;
1084{
1085 int what;
1086
1087 switch (fragP->fr_subtype)
1088 {
1089 default:
1090 abort ();
1091
1092 case C (COND_BRANCH, UNDEF_BYTE_DISP):
1093 case C (UNCOND_BRANCH, UNDEF_BYTE_DISP):
1094 what = GET_WHAT (fragP->fr_subtype);
1095 /* Used to be a branch to somewhere which was unknown. */
1096 if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type)
1097 {
1098 /* Got a symbol and it's defined in this segment, become byte
1099 sized - maybe it will fix up. */
1100 fragP->fr_subtype = C (what, BYTE_DISP);
1101 }
1102 else
1103 {
1104 /* Its got a segment, but its not ours, so it will always be
1105 long. */
1106 fragP->fr_subtype = C (what, UNDEF_WORD_DISP);
1107 }
1108 break;
1109
1110 case C (COND_BRANCH, BYTE_DISP):
1111 case C (COND_BRANCH, WORD_DISP):
1112 case C (COND_BRANCH, UNDEF_WORD_DISP):
1113 case C (UNCOND_BRANCH, BYTE_DISP):
1114 case C (UNCOND_BRANCH, WORD_DISP):
1115 case C (UNCOND_BRANCH, UNDEF_WORD_DISP):
1116 /* When relaxing a section for the second time, we don't need to
1117 do anything besides return the current size. */
1118 break;
1119 }
1120
1121 fragP->fr_var = md_relax_table[fragP->fr_subtype].rlx_length;
1122 return fragP->fr_var;
1123}
1124
1125const char *md_shortopts = "";
1126struct option md_longopts[] = {
1127#define OPTION_RELAX (OPTION_MD_BASE)
1128 {NULL, no_argument, NULL, 0}
1129};
1130
1131void
1132md_show_usage (stream)
1133 FILE *stream ATTRIBUTE_UNUSED;
1134{
1135}
1136
1137size_t md_longopts_size = sizeof (md_longopts);
Note: See TracBrowser for help on using the repository browser.