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