Support for the Z8k
[external/binutils.git] / gas / config / tc-z8k.c
1 /* tc-z8k.c -- Assemble code for the Zilog Z800N
2    Copyright (C) 1992 Free Software Foundation.
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
18    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
19
20
21 /* 
22   Written By Steve Chamberlain
23   sac@cygnus.com
24   */
25
26 #include <stdio.h>
27 #define DEFINE_TABLE
28 #include "disasm/z8kopcode.h"
29
30 #include "as.h"
31 #include "bfd.h"
32 #include <ctype.h>
33 #include "listing.h"
34
35 char  comment_chars[]  = { ';',0 };
36 char line_separator_chars[] = { '$' ,0};
37
38 extern int machine;
39 extern int coff_flags;
40 int segmented_mode;
41 int  md_reloc_size ;
42
43 /* This table describes all the machine specific pseudo-ops the assembler
44    has to support.  The fields are:
45    pseudo-op name without dot
46    function to call to execute this pseudo-op
47    Integer arg to pass to the function
48    */
49
50 void cons();
51
52
53 void s_segm()
54 {
55   segmented_mode = 1;
56   machine = bfd_mach_z8001;
57   coff_flags = F_Z8001;
58 }
59
60 void s_unseg()
61 {
62   segmented_mode = 0;
63   machine = bfd_mach_z8002;
64   coff_flags = F_Z8002;
65 }
66 const pseudo_typeS md_pseudo_table[] = 
67 {
68 { "int",        cons,           2       },
69 { "data.b",     cons,           1      },
70 { "data.w",     cons,            2      },
71 { "data.l",     cons,           4      },
72 { "form",       listing_psize,  0      },
73 { "heading",    listing_title,  0},
74 { "import",     s_ignore,       0},
75 { "page",       listing_eject,  0},
76 { "program",    s_ignore,       0},
77 { "SEGM",       s_segm,         0},
78 { "UNSEG",       s_unseg,         0},
79 { 0,0,0 }
80 };
81
82
83 const char EXP_CHARS[] = "eE";
84
85 /* Chars that mean this number is a floating point constant */
86 /* As in 0f12.456 */
87 /* or    0d1.2345e12 */
88 char FLT_CHARS[] = "rRsSfFdDxXpP";
89
90
91 const relax_typeS md_relax_table[1];
92
93
94 static struct hash_control *opcode_hash_control;        /* Opcode mnemonics */
95
96
97
98 void md_begin () 
99 {
100   opcode_entry_type *opcode;
101   char *prev_name= "";
102   int idx = 0;
103         
104   opcode_hash_control = hash_new();
105
106         
107   for (opcode = z8k_table; opcode->name; opcode++) 
108   {
109     /* Only enter unique codes into the table */
110     char *src= opcode->name;
111
112     if (strcmp(opcode->name, prev_name)) 
113     {
114       hash_insert(opcode_hash_control, opcode->name, (char *)opcode);
115       idx++;
116     }
117     opcode->idx = idx;
118     prev_name = opcode->name;
119   }
120         
121 }
122
123
124 struct z8k_exp {
125         char *e_beg;
126         char *e_end;
127         expressionS e_exp;
128 };
129 typedef struct z8k_op 
130 {
131   char regsize;   /* 'b','w','r','q' */
132   unsigned int reg; /* 0..15 */
133
134   int mode;
135
136   unsigned int x_reg;/* any other register associated with the mode */
137   expressionS exp; /* any expression */
138 } op_type;
139
140
141
142 static op_type *da_address;
143 static op_type *imm_operand;
144
145 int the_cc;
146
147 char * 
148 DEFUN(whatreg,(reg, src),
149       int *reg AND
150       char *src)
151 {
152   if (isdigit(src[1])) 
153   {
154     *reg = (src[0] - '0') * 10 +src[1] - '0';
155     return src+2;
156   }
157   else
158   {
159     *reg = (src[0] - '0');
160     return src+1;
161   }
162 return 0;
163 }
164
165 /*
166   parse operands        
167
168   rh0-rh7, rl0-rl7
169   r0-r15
170   rr0-rr14
171   rq0--rq12
172   WREG r0,r1,r2,r3,r4,r5,r6,r7,fp,sp
173   r0l,r0h,..r7l,r7h
174   @WREG
175   @WREG+
176   @-WREG
177   #const
178   
179   */
180
181
182 /* try and parse a reg name, returns number of chars consumed */
183 char*
184 DEFUN(parse_reg,(src, mode, reg),
185       char *src AND
186       int * mode AND
187       unsigned int *reg)
188 {
189   char *res = 0;
190   if (src[0] == 'R') 
191   {
192     if (src[1] == 'R')
193     {
194       *mode = CLASS_REG_LONG;
195       res =   whatreg(reg, src+2);
196     }
197     else  if (src[1] == 'H')
198     {
199       *mode = CLASS_REG_BYTE;
200       res = whatreg(reg, src+2);
201     }
202     else if (src[1] == 'L')
203     {
204       *mode = CLASS_REG_BYTE;
205       res = whatreg(reg, src+2);
206     }
207     else if (src[1] == 'Q')
208     {
209     * mode = CLASS_REG_QUAD;
210       res = whatreg(reg, src+2);
211     }
212     else 
213     {
214       *mode = CLASS_REG_WORD;
215       res = whatreg(reg, src+1);
216     }
217   }
218   return res;
219
220
221 }
222
223 char *
224 DEFUN(parse_exp,(s, op),
225       char *s AND
226       expressionS *op)
227 {
228         char *save = input_line_pointer;
229         char *new;
230         segT seg;
231         input_line_pointer = s;
232         seg = expr(0,op);
233         new = input_line_pointer;
234         input_line_pointer = save;
235         if (SEG_NORMAL(seg)) 
236             return new;
237         switch (seg) {
238         case SEG_ABSOLUTE:
239         case SEG_UNKNOWN:
240         case SEG_DIFFERENCE:
241         case SEG_BIG:
242         case SEG_REGISTER:
243                 return new;
244         case SEG_ABSENT:
245                 as_bad("Missing operand");
246                 return new;
247         default:
248                 as_bad("Don't understand operand of type %s", segment_name (seg));
249                 return new;
250         }
251 }
252
253
254 /* The many forms of operand:
255    
256    <rb>
257    <r>
258    <rr>
259    <rq>
260    @r
261    #exp 
262    exp
263    exp(r)
264    r(#exp)
265    r(r)
266
267
268    
269    */
270
271 static
272 char *
273 DEFUN(checkfor,(ptr, what),
274       char *ptr AND
275       char what)
276 {
277 if (*ptr == what) ptr++;
278 else {
279 as_bad("expected %c", what);
280 }
281 return ptr;
282 }
283
284 /* Make sure the mode supplied is the size of a word */
285 static void 
286 DEFUN(regword,(mode, string),
287       int mode AND 
288       char *string)
289 {
290   int ok;
291   ok = CLASS_REG_WORD;
292   if (ok != mode) 
293   {  
294     as_bad("register is wrong size for a word %s", string);
295   }
296 }
297
298 /* Make sure the mode supplied is the size of an address */
299 static void 
300 DEFUN(regaddr,(mode, string),
301       int mode AND
302       char *string)
303 {
304   int ok;
305   ok = segmented_mode ? CLASS_REG_LONG : CLASS_REG_WORD;
306   if (ok != mode) 
307   {  
308     as_bad("register is wrong size for address %s", string);
309   }
310 }
311
312 struct cc_names {
313 int value;
314 char *name;
315
316
317 };
318
319 struct cc_names table[] = 
320 {
321   0x0,"F",
322   0x6,"Z",
323   0xe,"NZ",
324   0x7,"C",
325   0xf,"NC",
326   0xd,"PL",
327   0x5,"MI",
328   0xe,"NE",
329   0x6,"EQ",
330   0x4,"OV",
331   0xc,"NOV",
332   0x4,"PE",
333   0xC,"PO",
334   0x9,"GE",
335   0x1,"LT",
336   0xa,"GT",
337   0x2,"LE",
338   0xf,"UGE",
339   0x7,"ULT",
340   0xb,"UGT",
341   0x3,"ULE",
342   0,0
343  };
344
345 static void
346 DEFUN(get_cc_operand,(ptr, mode, dst),
347       char **ptr AND 
348       struct z8k_op *mode AND 
349       unsigned int dst)
350 {
351   char *src = *ptr;
352   int r;
353   int i;
354   mode->mode = CLASS_CC;
355   for (i = 0; table[i].name; i++)
356   {
357     int j;
358     for (j = 0; table[i].name[j]; j++) 
359     {
360       if (table[i].name[j] != src[j])
361        goto fail;
362     }
363    the_cc = table[i].value;
364     *ptr = src + j;
365     return;
366    fail:;
367   }
368 the_cc = 0x8;
369   return ;
370 }
371
372 static void 
373 DEFUN(get_operand,(ptr, mode, dst),
374       char **ptr AND 
375       struct z8k_op *mode AND 
376       unsigned int dst)
377 {
378   char *src = *ptr;
379   char *end;
380   unsigned   int num;
381   unsigned  int len;
382   unsigned int size;
383   mode->mode = 0;
384
385   if (*src == '#') 
386   {
387     mode->mode = CLASS_IMM;
388     imm_operand = mode;
389     src = parse_exp(src+1, &(mode->exp));
390   }     
391   else if (*src == '@') {
392     int d;
393     mode->mode = CLASS_IR;
394     src= parse_reg(src+1, &d, &mode->reg);
395   }
396   else 
397   {
398     int reg;
399     end = parse_reg(src, &mode->mode, &reg);
400
401     if (end)
402     {
403       int nw, nr;
404       src = end;
405       if (*src == '(') 
406       {
407         src++;
408         end = parse_reg(src, &nw, &nr);
409         if (end) 
410         {
411           /* Got Ra(Rb) */
412           src = end;
413
414           if (*src != ')')
415           {
416             as_bad("Missing ) in ra(rb)");
417           }
418           else
419           {
420             src++;
421           }
422           
423           regaddr(mode->mode,"ra(rb) ra");
424           regword(mode->mode,"ra(rb) rb");
425           mode->mode = CLASS_BX;
426           mode->reg = reg;
427           mode->x_reg = nr;
428
429         }
430         else 
431         {
432           /* Got Ra(disp) */
433           if (*src == '#')
434            src++;
435           src = parse_exp(src, &(mode->exp));
436           src = checkfor(src, ')');
437           mode->mode = CLASS_BA;
438           mode->reg = reg;
439           mode->x_reg = 0;
440         }
441       }
442       else
443       {
444         mode->reg = reg;
445         mode->x_reg = 0;
446       }
447     }
448     else 
449     {
450       /* No initial reg */
451       src = parse_exp(src, &(mode->exp));
452       if (*src == '(') 
453       {
454         src++;
455         end = parse_reg(src, &(mode->mode), &reg);
456         regword(mode->mode,"addr(Ra) ra");
457         mode->mode = CLASS_X;
458         mode->reg = reg;
459         mode->x_reg =0;
460         da_address = mode;
461         src = checkfor(end, ')');
462       }
463       else 
464       {
465         /* Just an address */
466         mode->mode = CLASS_DA;
467         mode->reg = 0;
468         mode->x_reg = 0;
469         da_address = mode;
470       }
471     }
472   }
473   *ptr = src;
474 }
475
476 static
477 char *
478 DEFUN(get_operands,(operand, op_end, operand),
479         opcode_entry_type *opcode AND
480           char *op_end AND
481           op_type *operand) 
482 {
483   char *ptr = op_end;
484   switch (opcode->noperands) 
485   {
486    case 0:
487     operand[0].mode = 0;
488     operand[1].mode = 0;
489     break;
490                     
491    case 1:    
492     ptr++;
493     get_operand(& ptr, operand +0,0);
494     operand[1].mode =0;
495     break;
496                     
497    case 2:
498     ptr++;
499     if (opcode->arg_info[0] == CLASS_CC) 
500     {
501       get_cc_operand(&ptr, operand+0,0);
502     }
503     else
504     {
505       get_operand(& ptr, operand +0,0);
506     }
507     if (*ptr == ',') ptr++;
508     get_operand(& ptr, operand +1, 1);
509     break;
510                     
511    default:
512     abort();    
513   }
514         
515         
516   return ptr;    
517 }
518
519 /* Passed a pointer to a list of opcodes which use different
520    addressing modes, return the opcode which matches the opcodes
521    provided
522    */
523
524 int reg[16];
525 expressionS disp;
526
527 static
528 opcode_entry_type *
529 DEFUN(get_specific,(opcode,  operands),
530       opcode_entry_type *opcode AND
531       op_type *operands)
532
533 {
534   opcode_entry_type *this_try = opcode ;
535   int found = 0;
536   unsigned int noperands = opcode->noperands;
537         
538   unsigned int dispreg;
539   unsigned int this_index = opcode->idx;
540
541   while (this_index == opcode->idx && !found) 
542   {
543     unsigned int i;
544                     
545     this_try  = opcode ++;
546     for (i = 0; i < noperands; i++) 
547     {
548       int mode = operands[i].mode;
549
550       if ((mode&CLASS_MASK) != (this_try->arg_info[i] & CLASS_MASK)) goto fail;
551
552       reg[this_try->arg_info[i] & ARG_MASK] = operands[i].reg;
553     }
554
555     found =1;
556    fail: ;
557   }
558   if (found) 
559    return this_try;
560   else 
561    return 0;
562 }
563
564 static void
565 DEFUN(check_operand,(operand, width, string),
566           struct z8k_op *operand AND
567           unsigned int width AND
568           char *string)
569 {
570   if (operand->exp.X_add_symbol == 0 
571       && operand->exp.X_subtract_symbol == 0)
572   {
573                     
574     /* No symbol involved, let's look at offset, it's dangerous if any of
575        the high bits are not 0 or ff's, find out by oring or anding with
576        the width and seeing if the answer is 0 or all fs*/
577     if ((operand->exp.X_add_number & ~width) != 0 &&
578         (operand->exp.X_add_number | width)!= (~0))
579     {
580       as_warn("operand %s0x%x out of range.", string, operand->exp.X_add_number);
581     }
582   }
583         
584 }
585
586 static void 
587 DEFUN(newfix,(ptr, type, operand),
588       int byte AND
589       int type AND
590       op_type *operand)
591 {
592
593   fix_new(frag_now,
594           byte,
595           1,
596           operand->exp.X_add_symbol,
597           operand->exp.X_subtract_symbol,
598           operand->exp.X_add_number,
599           0,
600           type);
601 }
602
603
604 /* Now we know what sort of opcodes it is, lets build the bytes -
605  */
606 static void 
607     DEFUN (build_bytes,(this_try, operand),
608            opcode_entry_type *this_try AND
609            struct z8k_op *operand)
610 {
611   unsigned int i;
612   char buffer[20];
613   int length;
614   char *output;
615   char *output_ptr = buffer;
616   char part;
617   int c;
618   char high;
619   int nib;
620   int nibble;
621   unsigned short *class_ptr;
622   length = this_try->length;
623   if (segmented_mode && da_address) 
624   {
625     /* two more bytes when in segmented mode and using da address
626        mode */
627     length += 2;        
628   }
629   output  = frag_more(this_try->length);
630 memset(buffer, 20, 0);  
631   class_ptr = this_try->byte_info;
632  top: ;
633
634   for (nibble = 0; c = *class_ptr++; nibble++)
635   {
636
637     switch (c & CLASS_MASK) 
638     {
639      default:
640       abort();
641      case CLASS_ADDRESS:
642       /* Direct address, we don't cope with the SS mode right now */
643       if (segmented_mode) {
644         newfix(nibble/2, R_DA | R_SEG, da_address);
645         output_ptr += 4;
646       }
647       else {
648         newfix(nibble/2, R_DA, da_address);
649         output_ptr += 2;
650       }
651       da_address = 0;
652       break;
653      case CLASS_CC:
654       *output_ptr++ = the_cc;
655       break;
656      case CLASS_BIT:
657       *output_ptr++ = c & 0xf;
658       break;
659      case CLASS_REGN0:
660       if (reg[c&0xf] == 0) 
661       {
662         as_bad("can't use R0 here");
663       }
664      case CLASS_REG:
665      case CLASS_REG_BYTE:
666      case CLASS_REG_WORD:
667      case CLASS_REG_LONG:
668      case CLASS_REG_QUAD:
669       /* Insert bit mattern of
670          right reg */
671       *output_ptr++ =  reg[c & 0xf];
672       break;
673      case CLASS_IMM:
674      {
675        nib = 0;
676        switch (c & ARG_MASK)
677        {
678         case ARG_IMM4:
679          newfix(nibble/2, R_IMM4L, imm_operand);
680          *output_ptr++ = 0;
681          break;
682
683         case   ARG_IMM8:  
684          newfix(nibble/2, R_IMM8, imm_operand);
685          *output_ptr++ = 0;
686          *output_ptr++ = 0;
687
688         case   ARG_IMM16:  
689          newfix(nibble/2, R_IMM16, imm_operand);
690          *output_ptr++ = 0;
691          *output_ptr++ = 0;
692          *output_ptr++ = 0;
693          *output_ptr++ = 0;
694          break;
695
696         case   ARG_IMM32:  
697          newfix(nibble/2, R_IMM32, imm_operand);
698          *output_ptr++ = 0;
699          *output_ptr++ = 0;
700          *output_ptr++ = 0;
701          *output_ptr++ = 0;
702
703          *output_ptr++ = 0;
704          *output_ptr++ = 0;
705          *output_ptr++ = 0;
706          *output_ptr++ = 0;
707
708          output_ptr +=8;
709          break;
710
711         default:
712          abort();
713
714
715        }
716      }
717     }
718   }
719
720   /* Copy from the nibble buffer into the frag */
721
722  {
723    char *src = buffer;
724    char *fragp = output;
725    while (src < output_ptr) 
726    {
727      *fragp = (src[0] << 4) | src[1];
728      src+=2;
729      fragp++;
730    }
731
732         
733  }
734
735 }
736
737 /* This is the guts of the machine-dependent assembler.  STR points to a
738    machine dependent instruction.  This funciton is supposed to emit
739    the frags/bytes it assembles to.
740    */
741
742
743
744 void 
745     DEFUN(md_assemble,(str),
746           char *str)
747 {
748   char *op_start;
749   char *op_end;
750   unsigned int i;
751   struct       z8k_op operand[2];  
752   opcode_entry_type *opcode;
753   opcode_entry_type * prev_opcode;
754         
755   char *dot = 0;
756   char c;    
757   /* Drop leading whitespace */
758   while (*str == ' ')
759    str++;
760         
761   /* find the op code end */
762   for (op_start = op_end = str;
763        *op_end != 0 && *op_end != ' ';
764        op_end ++) 
765   {
766   }
767         
768   ;
769         
770   if (op_end == op_start) 
771   {
772     as_bad("can't find opcode ");
773   }
774   c = *op_end;
775         
776   *op_end = 0;
777         
778   opcode = (opcode_entry_type *) hash_find(opcode_hash_control,
779                                            op_start);
780         
781   if (opcode == NULL) 
782   {
783     as_bad("unknown opcode");
784     return;
785   }
786         
787
788   input_line_pointer =   get_operands(opcode, op_end,
789                                       operand);
790   *op_end = c;
791   prev_opcode = opcode;
792         
793   opcode = get_specific(opcode,  operand);
794         
795   if (opcode == 0)  
796   {
797     /* Couldn't find an opcode which matched the operands */
798     char *where =frag_more(2);
799     where[0] = 0x0;
800     where[1] = 0x0;
801
802     as_bad("error");
803     return;
804   }
805         
806   build_bytes(opcode, operand);
807 }       
808
809
810 void 
811     DEFUN(tc_crawl_symbol_chain, (headers),
812           object_headers *headers)
813 {
814         printf("call to tc_crawl_symbol_chain \n");
815 }
816
817 symbolS *DEFUN(md_undefined_symbol,(name),
818                char *name)
819 {
820         return 0;
821 }
822
823 void 
824     DEFUN(tc_headers_hook,(headers),
825           object_headers *headers)
826 {
827         printf("call to tc_headers_hook \n"); 
828 }
829 void
830     DEFUN_VOID(md_end) 
831 {
832 }
833
834 /* Various routines to kill one day */
835 /* Equal to MAX_PRECISION in atof-ieee.c */
836 #define MAX_LITTLENUMS 6
837
838 /* Turn a string in input_line_pointer into a floating point constant of type
839    type, and store the appropriate bytes in *litP.  The number of LITTLENUMS
840    emitted is stored in *sizeP .  An error message is returned, or NULL on OK.
841    */
842 char *
843     md_atof(type,litP,sizeP)
844 char type;
845 char *litP;
846 int *sizeP;
847 {
848         int     prec;
849         LITTLENUM_TYPE words[MAX_LITTLENUMS];
850         LITTLENUM_TYPE *wordP;
851         char    *t;
852         char    *atof_ieee();
853         
854         switch(type) {
855         case 'f':
856         case 'F':
857         case 's':
858         case 'S':
859                 prec = 2;
860                 break;
861                 
862         case 'd':
863         case 'D':
864         case 'r':
865         case 'R':
866                 prec = 4;
867                 break;
868                 
869         case 'x':
870         case 'X':
871                 prec = 6;
872                 break;
873                 
874         case 'p':
875         case 'P':
876                 prec = 6;
877                 break;
878                 
879         default:
880                 *sizeP=0;
881                 return "Bad call to MD_ATOF()";
882         }
883         t=atof_ieee(input_line_pointer,type,words);
884         if(t)
885             input_line_pointer=t;
886         
887         *sizeP=prec * sizeof(LITTLENUM_TYPE);
888         for(wordP=words;prec--;) {
889                 md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
890                 litP+=sizeof(LITTLENUM_TYPE);
891         }
892         return "";      /* Someone should teach Dean about null pointers */
893 }
894
895 int
896     md_parse_option(argP, cntP, vecP)
897 char **argP;
898 int *cntP;
899 char ***vecP;
900
901 {
902         return 0;
903         
904 }
905
906 int md_short_jump_size;
907
908 void tc_aout_fix_to_chars () { printf("call to tc_aout_fix_to_chars \n");
909                                abort(); }
910 void md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol)
911 char *ptr;
912 long from_addr;
913 long to_addr;
914 fragS *frag;
915 symbolS *to_symbol;
916 {
917         as_fatal("failed sanity check.");
918 }
919
920 void
921     md_create_long_jump(ptr,from_addr,to_addr,frag,to_symbol)
922 char *ptr;
923 long from_addr, to_addr;
924 fragS *frag;
925 symbolS *to_symbol;
926 {
927         as_fatal("failed sanity check.");
928 }
929
930 void
931     md_convert_frag(headers, fragP)
932 object_headers *headers;
933 fragS * fragP;
934
935 { printf("call to md_convert_frag \n"); abort(); }
936
937 long
938     DEFUN(md_section_align,(seg, size),
939           segT seg AND
940           long size)
941 {
942         return((size + (1 << section_alignment[(int) seg]) - 1) & (-1 << section_alignment[(int) seg]));
943         
944 }
945
946 void
947     md_apply_fix(fixP, val)
948 fixS *fixP;
949 long val;
950 {
951   char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
952         
953   switch(fixP->fx_size) {
954    case 1:
955     *buf++=val;
956     break;
957    case 2:
958     *buf++=(val>>8);
959     *buf++=val;
960     break;
961    case 4:
962     *buf++=(val>>24);
963     *buf++=(val>>16);
964     *buf++=(val>>8);
965     *buf++=val;
966     break;
967    default:
968     abort();
969                 
970   }
971 }
972
973 void DEFUN(md_operand, (expressionP),expressionS *expressionP) 
974 { }
975
976 int  md_long_jump_size;
977 int
978     md_estimate_size_before_relax(fragP, segment_type)
979 register fragS *fragP;
980 register segT segment_type;
981
982         printf("call tomd_estimate_size_before_relax \n"); abort(); }
983 /* Put number into target byte order */
984
985 void DEFUN(md_number_to_chars,(ptr, use, nbytes),
986            char *ptr AND
987            long use AND
988            int nbytes)
989 {
990         switch (nbytes) {
991         case 4: *ptr++ = (use >> 24) & 0xff;
992         case 3: *ptr++ = (use >> 16) & 0xff;
993         case 2: *ptr++ = (use >> 8) & 0xff;
994         case 1: *ptr++ = (use >> 0) & 0xff;
995                 break;
996         default:
997                 abort();
998         }
999 }
1000 long md_pcrel_from(fixP) 
1001 fixS *fixP; { abort(); }
1002
1003 void tc_coff_symbol_emit_hook() { }
1004
1005
1006 void tc_reloc_mangle(fix_ptr, intr, base)
1007 fixS *fix_ptr;
1008 struct internal_reloc *intr;
1009 bfd_vma base;
1010
1011 {
1012   symbolS *symbol_ptr;
1013         
1014   symbol_ptr = fix_ptr->fx_addsy;
1015         
1016   /* If this relocation is attached to a symbol then it's ok
1017      to output it */
1018   if (fix_ptr->fx_r_type == RELOC_32) {
1019     /* cons likes to create reloc32's whatever the size of the reloc..
1020      */
1021     switch (fix_ptr->fx_size) 
1022     {
1023                             
1024      case 2:
1025       intr->r_type = R_IMM16;
1026       break;
1027      case 1:
1028       intr->r_type = R_IMM8;
1029       break;
1030      default:
1031       abort();
1032                             
1033     }
1034                 
1035   }
1036   else {  
1037     intr->r_type = fix_ptr->fx_r_type;
1038   }
1039         
1040   intr->r_vaddr = fix_ptr->fx_frag->fr_address +  fix_ptr->fx_where  +base;
1041   intr->r_offset = fix_ptr->fx_offset;
1042         
1043   if (symbol_ptr)
1044    intr->r_symndx = symbol_ptr->sy_number;
1045   else
1046    intr->r_symndx = -1;
1047         
1048         
1049 }
1050
1051