1/* tc-msp430.c -- Assembler code for the Texas Instruments MSP430
2
3  Copyright (C) 2002, 2003 Free Software Foundation, Inc.
4  Contributed by Dmitry Diky <diwil@mail.ru>
5
6  This file is part of GAS, the GNU Assembler.
7
8  GAS is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2, or (at your option)
11  any later version.
12
13  GAS is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  GNU General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with GAS; see the file COPYING.  If not, write to
20  the Free Software Foundation, 59 Temple Place - Suite 330,
21  Boston, MA 02111-1307, USA.  */
22
23#include <stdio.h>
24#include <string.h>
25#include <stdlib.h>
26#include <limits.h>
27
28#define PUSH_1X_WORKAROUND
29#include "as.h"
30#include "subsegs.h"
31#include "opcode/msp430.h"
32#include "safe-ctype.h"
33
34const char comment_chars[] = ";";
35const char line_comment_chars[] = "#";
36const char line_separator_chars[] = "";
37const char EXP_CHARS[] = "eE";
38const char FLT_CHARS[] = "dD";
39
40/* Handle  long expressions.  */
41extern LITTLENUM_TYPE generic_bignum[];
42
43static struct hash_control *msp430_hash;
44
45static unsigned int msp430_operands
46  PARAMS ((struct msp430_opcode_s *, char *));
47static int msp430_srcoperand
48  PARAMS ((struct msp430_operand_s *, char *, int, int *));
49static int msp430_dstoperand
50  PARAMS ((struct msp430_operand_s *, char *, int));
51static char *parse_exp
52  PARAMS ((char *, expressionS *));
53static inline char *skip_space
54  PARAMS ((char *));
55static int check_reg
56  PARAMS ((char *));
57static void msp430_set_arch
58  PARAMS ((int));
59static void show_mcu_list
60  PARAMS ((FILE *));
61static void del_spaces
62  PARAMS ((char *));
63
64#define MAX_OP_LEN	256
65
66struct mcu_type_s
67{
68  char *name;
69  int isa;
70  int mach;
71};
72
73#define MSP430_ISA_11   11
74#define MSP430_ISA_110	110
75#define MSP430_ISA_12   12
76#define MSP430_ISA_13   13
77#define MSP430_ISA_14   14
78#define MSP430_ISA_15   15
79#define MSP430_ISA_16   16
80#define MSP430_ISA_31   31
81#define MSP430_ISA_32   32
82#define MSP430_ISA_33   33
83#define MSP430_ISA_41   41
84#define MSP430_ISA_42   42
85#define MSP430_ISA_43   43
86#define MSP430_ISA_44   44
87
88#define CHECK_RELOC_MSP430 		((imm_op || byte_op)?BFD_RELOC_MSP430_16_BYTE:BFD_RELOC_MSP430_16)
89#define CHECK_RELOC_MSP430_PCREL	((imm_op || byte_op)?BFD_RELOC_MSP430_16_PCREL_BYTE:BFD_RELOC_MSP430_16_PCREL)
90
91static struct mcu_type_s mcu_types[] =
92{
93  {"msp1",       MSP430_ISA_11, bfd_mach_msp11},
94  {"msp2",       MSP430_ISA_14, bfd_mach_msp14},
95  {"msp430x110", MSP430_ISA_11, bfd_mach_msp11},
96  {"msp430x112", MSP430_ISA_11, bfd_mach_msp11},
97  {"msp430x1101",MSP430_ISA_110, bfd_mach_msp110},
98  {"msp430x1111",MSP430_ISA_110, bfd_mach_msp110},
99  {"msp430x1121",MSP430_ISA_110, bfd_mach_msp110},
100  {"msp430x1122",MSP430_ISA_11, bfd_mach_msp110},
101  {"msp430x1132",MSP430_ISA_11, bfd_mach_msp110},
102
103  {"msp430x122", MSP430_ISA_12, bfd_mach_msp12},
104  {"msp430x123", MSP430_ISA_12, bfd_mach_msp12},
105  {"msp430x1222",MSP430_ISA_12, bfd_mach_msp12},
106  {"msp430x1232",MSP430_ISA_12, bfd_mach_msp12},
107
108  {"msp430x133", MSP430_ISA_13, bfd_mach_msp13},
109  {"msp430x135", MSP430_ISA_13, bfd_mach_msp13},
110  {"msp430x1331",MSP430_ISA_13, bfd_mach_msp13},
111  {"msp430x1351",MSP430_ISA_13, bfd_mach_msp13},
112  {"msp430x147", MSP430_ISA_14, bfd_mach_msp14},
113  {"msp430x148", MSP430_ISA_14, bfd_mach_msp14},
114  {"msp430x149", MSP430_ISA_14, bfd_mach_msp14},
115
116  {"msp430x155", MSP430_ISA_15, bfd_mach_msp15},
117  {"msp430x156", MSP430_ISA_15, bfd_mach_msp15},
118  {"msp430x157", MSP430_ISA_15, bfd_mach_msp15},
119  {"msp430x167", MSP430_ISA_16, bfd_mach_msp16},
120  {"msp430x168", MSP430_ISA_16, bfd_mach_msp16},
121  {"msp430x169", MSP430_ISA_16, bfd_mach_msp16},
122
123  {"msp430x311", MSP430_ISA_31, bfd_mach_msp31},
124  {"msp430x312", MSP430_ISA_31, bfd_mach_msp31},
125  {"msp430x313", MSP430_ISA_31, bfd_mach_msp31},
126  {"msp430x314", MSP430_ISA_31, bfd_mach_msp31},
127  {"msp430x315", MSP430_ISA_31, bfd_mach_msp31},
128  {"msp430x323", MSP430_ISA_32, bfd_mach_msp32},
129  {"msp430x325", MSP430_ISA_32, bfd_mach_msp32},
130  {"msp430x336", MSP430_ISA_33, bfd_mach_msp33},
131  {"msp430x337", MSP430_ISA_33, bfd_mach_msp33},
132
133  {"msp430x412", MSP430_ISA_41, bfd_mach_msp41},
134  {"msp430x413", MSP430_ISA_41, bfd_mach_msp41},
135
136  {"msp430xE423", MSP430_ISA_42, bfd_mach_msp42},
137  {"msp430xE425", MSP430_ISA_42, bfd_mach_msp42},
138  {"msp430xE427", MSP430_ISA_42, bfd_mach_msp42},
139  {"msp430xW423", MSP430_ISA_42, bfd_mach_msp42},
140  {"msp430xW425", MSP430_ISA_42, bfd_mach_msp42},
141  {"msp430xW427", MSP430_ISA_42, bfd_mach_msp42},
142
143  {"msp430x435", MSP430_ISA_43, bfd_mach_msp43},
144  {"msp430x436", MSP430_ISA_43, bfd_mach_msp43},
145  {"msp430x437", MSP430_ISA_43, bfd_mach_msp43},
146  {"msp430x447", MSP430_ISA_44, bfd_mach_msp44},
147  {"msp430x448", MSP430_ISA_44, bfd_mach_msp44},
148  {"msp430x449", MSP430_ISA_44, bfd_mach_msp44},
149
150  {NULL, 0, 0}
151};
152
153
154static struct mcu_type_s default_mcu =
155    { "msp430x11", MSP430_ISA_11, bfd_mach_msp11 };
156
157static struct mcu_type_s *msp430_mcu = &default_mcu;
158
159const pseudo_typeS md_pseudo_table[] =
160{
161  {"arch", msp430_set_arch, 0},
162  {NULL, NULL, 0}
163};
164
165#define OPTION_MMCU 'm'
166
167const char *md_shortopts = "m:";
168
169struct option md_longopts[] =
170{
171  {"mmcu", required_argument, NULL, OPTION_MMCU},
172  {NULL, no_argument, NULL, 0}
173};
174
175size_t md_longopts_size = sizeof (md_longopts);
176
177static void
178show_mcu_list (stream)
179     FILE *stream;
180{
181  int i;
182
183  fprintf (stream, _("Known MCU names:\n"));
184
185  for (i = 0; mcu_types[i].name; i++)
186    fprintf (stream, _("\t %s\n"), mcu_types[i].name);
187
188  fprintf (stream, "\n");
189}
190
191void
192md_show_usage (stream)
193     FILE *stream;
194{
195  fprintf (stream,
196	   _("MSP430 options:\n"
197	     "  -mmcu=[msp430-name] select microcontroller type\n"
198	     "                  msp430x110  msp430x112\n"
199	     "                  msp430x1101 msp430x1111\n"
200	     "                  msp430x1121 msp430x1122 msp430x1132\n"
201	     "                  msp430x122  msp430x123\n"
202	     "                  msp430x1222 msp430x1232\n"
203	     "                  msp430x133  msp430x135\n"
204	     "                  msp430x1331 msp430x1351\n"
205	     "                  msp430x147  msp430x148  msp430x149\n"
206	     "                  msp430x155  msp430x156  msp430x157\n"
207	     "                  msp430x167  msp430x168  msp430x169\n"
208	     "                  msp430x311  msp430x312  msp430x313  msp430x314  msp430x315\n"
209	     "                  msp430x323  msp430x325\n"
210	     "                  msp430x336  msp430x337\n"
211	     "                  msp430x412  msp430x413\n"
212	     "                  msp430xE423 msp430xE425 msp430E427\n"
213	     "                  msp430xW423 msp430xW425 msp430W427\n"
214	     "                  msp430x435  msp430x436  msp430x437\n"
215	     "                  msp430x447  msp430x448  msp430x449\n"));
216
217  show_mcu_list (stream);
218}
219
220static char *
221extract_word (char *from, char *to, int limit)
222{
223  char *op_start;
224  char *op_end;
225  int size = 0;
226
227  /* Drop leading whitespace.  */
228  from = skip_space (from);
229  *to = 0;
230
231  /* Find the op code end.  */
232  for (op_start = op_end = from; *op_end != 0 && is_part_of_name (*op_end);)
233    {
234      to[size++] = *op_end++;
235      if (size + 1 >= limit)
236	break;
237    }
238
239  to[size] = 0;
240  return op_end;
241}
242
243static void
244msp430_set_arch (dummy)
245     int dummy ATTRIBUTE_UNUSED;
246{
247  char *str = (char *) alloca (32);	/* 32 for good measure.  */
248
249  input_line_pointer = extract_word (input_line_pointer, str, 32);
250
251  md_parse_option (OPTION_MMCU, str);
252  bfd_set_arch_mach (stdoutput, TARGET_ARCH, msp430_mcu->mach);
253}
254
255int
256md_parse_option (c, arg)
257     int c;
258     char *arg;
259{
260  int i;
261
262  switch (c)
263    {
264    case OPTION_MMCU:
265      for (i = 0; mcu_types[i].name; ++i)
266	if (strcmp (mcu_types[i].name, arg) == 0)
267	  break;
268
269      if (!mcu_types[i].name)
270	{
271	  show_mcu_list (stderr);
272	  as_fatal (_("unknown MCU: %s\n"), arg);
273	}
274
275      if (msp430_mcu == &default_mcu || msp430_mcu->mach == mcu_types[i].mach)
276	msp430_mcu = &mcu_types[i];
277      else
278	as_fatal (_("redefinition of mcu type %s' to %s'"),
279		  msp430_mcu->name, mcu_types[i].name);
280      return 1;
281    }
282
283  return 0;
284}
285
286symbolS *
287md_undefined_symbol (name)
288     char *name ATTRIBUTE_UNUSED;
289{
290  return 0;
291}
292
293static inline char *
294skip_space (s)
295     char *s;
296{
297  while (ISSPACE (*s))
298    ++s;
299  return s;
300}
301
302/* Delete spaces from s: X ( r 1  2)  => X(r12).  */
303
304static void
305del_spaces (s)
306     char *s;
307{
308  while (*s)
309    {
310      if (ISSPACE (*s))
311	{
312	  char *m = s + 1;
313
314	  while (ISSPACE (*m) && *m)
315	    m++;
316	  memmove (s, m, strlen (m) + 1);
317	}
318      else
319	s++;
320    }
321}
322
323/* Extract one word from FROM and copy it to TO. Delimeters are ",;\n"  */
324
325static char *
326extract_operand (char *from, char *to, int limit)
327{
328  int size = 0;
329
330  /* Drop leading whitespace.  */
331  from = skip_space (from);
332
333  while (size < limit && *from)
334    {
335      *(to + size) = *from;
336      if (*from == ',' || *from == ';' || *from == '\n')
337	break;
338      from++;
339      size++;
340    }
341
342  *(to + size) = 0;
343  del_spaces (to);
344
345  from++;
346
347  return from;
348}
349
350static char *
351extract_cmd (char *from, char *to, int limit)
352{
353  int size = 0;
354
355  while (*from && ! ISSPACE (*from) && *from != '.' && limit > size)
356    {
357      *(to + size) = *from;
358      from++;
359      size++;
360    }
361
362  *(to + size) = 0;
363
364  return from;
365}
366
367/* Turn a string in input_line_pointer into a floating point constant
368   of type TYPE, and store the appropriate bytes in *LITP.  The number
369   of LITTLENUMS emitted is stored in *SIZEP.  An error message is
370   returned, or NULL on OK.  */
371
372char *
373md_atof (type, litP, sizeP)
374     int type;
375     char *litP;
376     int *sizeP;
377{
378  int prec;
379  LITTLENUM_TYPE words[4];
380  LITTLENUM_TYPE *wordP;
381  char *t;
382
383  switch (type)
384    {
385    case 'f':
386      prec = 2;
387      break;
388    case 'd':
389      prec = 4;
390      break;
391    default:
392      *sizeP = 0;
393      return _("bad call to md_atof");
394    }
395
396  t = atof_ieee (input_line_pointer, type, words);
397  if (t)
398    input_line_pointer = t;
399
400  *sizeP = prec * sizeof (LITTLENUM_TYPE);
401
402  /* This loop outputs the LITTLENUMs in REVERSE order.  */
403  for (wordP = words + prec - 1; prec--;)
404    {
405      md_number_to_chars (litP, (valueT) (*wordP--), sizeof (LITTLENUM_TYPE));
406      litP += sizeof (LITTLENUM_TYPE);
407    }
408
409  return NULL;
410}
411
412void
413md_convert_frag (abfd, sec, fragP)
414     bfd *abfd ATTRIBUTE_UNUSED;
415     asection *sec ATTRIBUTE_UNUSED;
416     fragS *fragP ATTRIBUTE_UNUSED;
417{
418  abort ();
419}
420
421void
422md_begin ()
423{
424  struct msp430_opcode_s *opcode;
425  msp430_hash = hash_new ();
426
427  for (opcode = msp430_opcodes; opcode->name; opcode++)
428    hash_insert (msp430_hash, opcode->name, (char *) opcode);
429
430  bfd_set_arch_mach (stdoutput, TARGET_ARCH, msp430_mcu->mach);
431}
432
433void
434md_assemble (str)
435     char *str;
436{
437  struct msp430_opcode_s *opcode;
438  char cmd[32];
439  unsigned int i = 0;
440
441  str = skip_space (str);	/* Skip leading spaces.  */
442  str = extract_cmd (str, cmd, sizeof (cmd));
443
444  while (cmd[i] && i < sizeof (cmd))
445    {
446      char a = TOLOWER (cmd[i]);
447      cmd[i] = a;
448      i++;
449    }
450
451  if (!cmd[0])
452    {
453      as_bad (_("can't find opcode "));
454      return;
455    }
456
457  opcode = (struct msp430_opcode_s *) hash_find (msp430_hash, cmd);
458
459  if (opcode == NULL)
460    {
461      as_bad (_("unknown opcode `%s'"), cmd);
462      return;
463    }
464
465  {
466    char *__t = input_line_pointer;
467    msp430_operands (opcode, str);
468    input_line_pointer = __t;
469  }
470}
471
472/* Parse instruction operands.
473   Return binary opcode.  */
474
475static unsigned int
476msp430_operands (opcode, line)
477     struct msp430_opcode_s *opcode;
478     char *line;
479{
480  int bin = opcode->bin_opcode;	/* opcode mask.  */
481  int __is;
482  char l1[MAX_OP_LEN], l2[MAX_OP_LEN];
483  char *frag;
484  int where;
485  struct msp430_operand_s op1, op2;
486  int res = 0;
487  static short ZEROS = 0;
488  int byte_op, imm_op;
489
490  /* opcode is the one from opcodes table
491     line contains something like
492     [.w] @r2+, 5(R1)
493     or
494     .b @r2+, 5(R1).  */
495
496  /* Check if byte or word operation.  */
497  if (*line == '.' && TOLOWER (*(line + 1)) == 'b')
498    {
499      bin |= BYTE_OPERATION;
500      byte_op = 1;
501    }
502  else
503    byte_op = 0;
504
505  /* skip .[bwBW].  */
506  while (! ISSPACE (*line) && *line)
507    line++;
508
509  if (opcode->insn_opnumb && (!*line || *line == '\n'))
510    {
511      as_bad (_("instruction %s requires %d operand(s)"),
512	      opcode->name, opcode->insn_opnumb);
513      return 0;
514    }
515
516  memset (l1, 0, sizeof (l1));
517  memset (l2, 0, sizeof (l2));
518  memset (&op1, 0, sizeof (op1));
519  memset (&op2, 0, sizeof (op2));
520
521  imm_op = 0;
522
523  switch (opcode->fmt)
524    {
525    case 0:			/* Emulated.  */
526      switch (opcode->insn_opnumb)
527	{
528	case 0:
529	  /* Set/clear bits instructions.  */
530	  __is = 2;
531	  frag = frag_more (__is);
532	  bfd_putl16 ((bfd_vma) bin, frag);
533	  break;
534	case 1:
535	  /* Something which works with destination operand.  */
536	  line = extract_operand (line, l1, sizeof (l1));
537	  res = msp430_dstoperand (&op1, l1, opcode->bin_opcode);
538	  if (res)
539	    break;
540
541	  bin |= (op1.reg | (op1.am << 7));
542	  __is = 1 + op1.ol;
543	  frag = frag_more (2 * __is);
544	  where = frag - frag_now->fr_literal;
545	  bfd_putl16 ((bfd_vma) bin, frag);
546
547	  if (op1.mode == OP_EXP)
548	    {
549	      where += 2;
550	      bfd_putl16 ((bfd_vma) ZEROS, frag + 2);
551
552	      if (op1.reg)
553		fix_new_exp (frag_now, where, 2,
554			     &(op1.exp), FALSE, CHECK_RELOC_MSP430);
555	      else
556		fix_new_exp (frag_now, where, 2,
557			     &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
558	    }
559	  break;
560
561	case 2:
562	  {
563	    /* Shift instruction.  */
564	    line = extract_operand (line, l1, sizeof (l1));
565	    strncpy (l2, l1, sizeof (l2));
566	    l2[sizeof (l2) - 1] = '\0';
567	    res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op);
568	    res += msp430_dstoperand (&op2, l2, opcode->bin_opcode);
569
570	    if (res)
571	      break;	/* An error occurred.  All warnings were done before.  */
572
573	    bin |= (op2.reg | (op1.reg << 8) | (op1.am << 4) | (op2.am << 7));
574
575	    __is = 1 + op1.ol + op2.ol;	/* insn size in words.  */
576	    frag = frag_more (2 * __is);
577	    where = frag - frag_now->fr_literal;
578	    bfd_putl16 ((bfd_vma) bin, frag);
579
580	    if (op1.mode == OP_EXP)
581	      {
582		where += 2;	/* Advance 'where' as we do not know _where_.  */
583		bfd_putl16 ((bfd_vma) ZEROS, frag + 2);
584
585		if (op1.reg || (op1.reg == 0 && op1.am == 3))	/* Not PC relative.  */
586		  fix_new_exp (frag_now, where, 2,
587			       &(op1.exp), FALSE, CHECK_RELOC_MSP430);
588		else
589		  fix_new_exp (frag_now, where, 2,
590			       &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
591	      }
592
593	    if (op2.mode == OP_EXP)
594	      {
595		imm_op = 0;
596		bfd_putl16 ((bfd_vma) ZEROS, frag + 2 + ((__is == 3) ? 2 : 0));
597
598		if (op2.reg)	/* Not PC relative.  */
599		  fix_new_exp (frag_now, where + 2, 2,
600			       &(op2.exp), FALSE, CHECK_RELOC_MSP430);
601		else
602		  fix_new_exp (frag_now, where + 2, 2,
603			       &(op2.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
604	      }
605	    break;
606	  }
607	case 3:
608	  /* Branch instruction => mov dst, r0.  */
609	  line = extract_operand (line, l1, sizeof (l1));
610
611	  res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op);
612	  if (res)
613	    break;
614
615	  byte_op = 0;
616	  imm_op = 0;
617
618	  bin |= ((op1.reg << 8) | (op1.am << 4));
619	  __is = 1 + op1.ol;
620	  frag = frag_more (2 * __is);
621	  where = frag - frag_now->fr_literal;
622	  bfd_putl16 ((bfd_vma) bin, frag);
623
624	  if (op1.mode == OP_EXP)
625	    {
626	      where += 2;
627	      bfd_putl16 ((bfd_vma) ZEROS, frag + 2);
628
629	      if (op1.reg || (op1.reg == 0 && op1.am == 3))
630		fix_new_exp (frag_now, where, 2,
631			     &(op1.exp), FALSE, CHECK_RELOC_MSP430);
632	      else
633		fix_new_exp (frag_now, where, 2,
634			     &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
635	    }
636	  break;
637	}
638      break;
639
640    case 1:			/* Format 1, double operand.  */
641      line = extract_operand (line, l1, sizeof (l1));
642      line = extract_operand (line, l2, sizeof (l2));
643      res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op);
644      res += msp430_dstoperand (&op2, l2, opcode->bin_opcode);
645
646      if (res)
647	break;			/* Error occurred.  All warnings were done before.  */
648
649      bin |= (op2.reg | (op1.reg << 8) | (op1.am << 4) | (op2.am << 7));
650
651      __is = 1 + op1.ol + op2.ol;	/* insn size in words.  */
652      frag = frag_more (2 * __is);
653      where = frag - frag_now->fr_literal;
654      bfd_putl16 ((bfd_vma) bin, frag);
655
656      if (op1.mode == OP_EXP)
657	{
658	  where += 2;		/* Advance where as we do not know _where_.  */
659	  bfd_putl16 ((bfd_vma) ZEROS, frag + 2);
660
661	  if (op1.reg || (op1.reg == 0 && op1.am == 3))	/* Not PC relative.  */
662	    fix_new_exp (frag_now, where, 2,
663			 &(op1.exp), FALSE, CHECK_RELOC_MSP430);
664	  else
665	    fix_new_exp (frag_now, where, 2,
666			 &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
667	}
668
669      if (op2.mode == OP_EXP)
670	{
671	  imm_op = 0;
672	  bfd_putl16 ((bfd_vma) ZEROS, frag + 2 + ((__is == 3) ? 2 : 0));
673
674	  if (op2.reg)		/* Not PC relative.  */
675	    fix_new_exp (frag_now, where + 2, 2,
676			 &(op2.exp), FALSE, CHECK_RELOC_MSP430);
677	  else
678	    fix_new_exp (frag_now, where + 2, 2,
679			 &(op2.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
680	}
681      break;
682
683    case 2:			/* Single-operand mostly instr.  */
684      if (opcode->insn_opnumb == 0)
685	{
686	  /* reti instruction.  */
687	  frag = frag_more (2);
688	  bfd_putl16 ((bfd_vma) bin, frag);
689	  break;
690	}
691
692      line = extract_operand (line, l1, sizeof (l1));
693      res = msp430_srcoperand (&op1, l1, opcode->bin_opcode, &imm_op);
694      if (res)
695	break;		/* Error in operand.  */
696
697      bin |= op1.reg | (op1.am << 4);
698      __is = 1 + op1.ol;
699      frag = frag_more (2 * __is);
700      where = frag - frag_now->fr_literal;
701      bfd_putl16 ((bfd_vma) bin, frag);
702
703      if (op1.mode == OP_EXP)
704	{
705	  bfd_putl16 ((bfd_vma) ZEROS, frag + 2);
706
707	  if (op1.reg || (op1.reg == 0 && op1.am == 3))	/* Not PC relative.  */
708	    fix_new_exp (frag_now, where + 2, 2,
709			 &(op1.exp), FALSE, CHECK_RELOC_MSP430);
710	  else
711	    fix_new_exp (frag_now, where + 2, 2,
712			 &(op1.exp), TRUE, CHECK_RELOC_MSP430_PCREL);
713	}
714      break;
715
716    case 3:			/* Conditional jumps instructions.  */
717      line = extract_operand (line, l1, sizeof (l1));
718      /* l1 is a label.  */
719      if (l1[0])
720	{
721	  char *m = l1;
722	  expressionS exp;
723
724	  if (*m == '$')
725	    m++;
726
727	  parse_exp (m, &exp);
728	  frag = frag_more (2);	/* Instr size is 1 word.  */
729
730	  /* In order to handle something like:
731
732	     and #0x8000, r5
733	     tst r5
734	     jz   4     ;       skip next 4 bytes
735	     inv r5
736	     inc r5
737	     nop        ;       will jump here if r5 positive or zero
738
739	     jCOND      -n      ;assumes jump n bytes backward:
740
741	     mov r5,r6
742	     jmp -2
743
744	     is equal to:
745	     lab:
746	     mov r5,r6
747	     jmp lab
748
749	     jCOND      $n      ; jump from PC in either direction.  */
750
751	  if (exp.X_op == O_constant)
752	    {
753	      int x = exp.X_add_number;
754
755	      if (x & 1)
756		{
757		  as_warn (_("Even number required. Rounded to %d"), x + 1);
758		  x++;
759		}
760
761	      if ((*l1 == '$' && x > 0) || x < 0)
762		x -= 2;
763
764	      x >>= 1;
765
766	      if (x > 512 || x < -511)
767		{
768		  as_bad (_("Wrong displacement  %d"), x << 1);
769		  break;
770		}
771
772	      bin |= x & 0x3ff;
773	      bfd_putl16 ((bfd_vma) bin, frag);
774	    }
775	  else if (exp.X_op == O_symbol && *l1 != '$')
776	    {
777	      where = frag - frag_now->fr_literal;
778	      fix_new_exp (frag_now, where, 2,
779			   &exp, TRUE, BFD_RELOC_MSP430_10_PCREL);
780
781	      bfd_putl16 ((bfd_vma) bin, frag);
782	    }
783	  else if (*l1 == '$')
784	    {
785	      as_bad (_("instruction requires label sans '$'"));
786	      break;
787	    }
788	  else
789	    {
790	      as_bad (_
791		      ("instruction requires label or value in range -511:512"));
792	      break;
793	    }
794	}
795      else
796	{
797	  as_bad (_("instruction requires label"));
798	  break;
799	}
800      break;
801
802    default:
803      as_bad (_("Ilegal instruction or not implmented opcode."));
804    }
805
806  input_line_pointer = line;
807  return 0;
808}
809
810static int
811msp430_dstoperand (op, l, bin)
812     struct msp430_operand_s *op;
813     char *l;
814     int bin;
815{
816  int dummy;
817  int ret = msp430_srcoperand (op, l, bin, &dummy);
818  if (ret)
819    return ret;
820
821  if (op->am == 2)
822    {
823      char *__tl = "0";
824
825      op->mode = OP_EXP;
826      op->am = 1;
827      op->ol = 1;
828      parse_exp (__tl, &(op->exp));
829      if (op->exp.X_op != O_constant || op->exp.X_add_number != 0)
830	{
831	  as_bad (_("Internal bug. Try to use 0(r%d) instead of @r%d"),
832		  op->reg, op->reg);
833	  return 1;
834	}
835      return 0;
836    }
837
838  if (op->am > 1)
839    {
840      as_bad (_
841	      ("this addressing mode is not applicable for destination operand"));
842      return 1;
843    }
844  return 0;
845}
846
847
848static int
849check_reg (t)
850     char *t;
851{
852  /* If this is a reg numb, str 't' must be a number from 0 - 15.  */
853
854  if (strlen (t) > 2 && *(t + 2) != '+')
855    return 1;
856
857  while (*t)
858    {
859      if ((*t < '0' || *t > '9') && *t != '+')
860	break;
861      t++;
862    }
863
864  if (*t)
865    return 1;
866
867  return 0;
868}
869
870
871static int
872msp430_srcoperand (op, l, bin, imm_op)
873     struct msp430_operand_s *op;
874     char *l;
875     int bin;
876     int *imm_op;
877{
878  char *__tl = l;
879
880  /* Check if an immediate #VALUE.  The hash sign should be only at the beginning!  */
881  if (*l == '#')
882    {
883      char *h = l;
884      int vshift = -1;
885      int rval = 0;
886
887      /* Check if there is:
888	 llo(x) - least significant 16 bits, x &= 0xffff
889	 lhi(x) - x = (x >> 16) & 0xffff,
890	 hlo(x) - x = (x >> 32) & 0xffff,
891	 hhi(x) - x = (x >> 48) & 0xffff
892	 The value _MUST_ be constant expression: #hlo(1231231231).  */
893
894      *imm_op = 1;
895
896      if (strncasecmp (h, "#llo(", 5) == 0)
897	{
898	  vshift = 0;
899	  rval = 3;
900	}
901      else if (strncasecmp (h, "#lhi(", 5) == 0)
902	{
903	  vshift = 1;
904	  rval = 3;
905	}
906      else if (strncasecmp (h, "#hlo(", 5) == 0)
907	{
908	  vshift = 2;
909	  rval = 3;
910	}
911      else if (strncasecmp (h, "#hhi(", 5) == 0)
912	{
913	  vshift = 3;
914	  rval = 3;
915	}
916      else if (strncasecmp (h, "#lo(", 4) == 0)
917	{
918	  vshift = 0;
919	  rval = 2;
920	}
921      else if (strncasecmp (h, "#hi(", 4) == 0)
922	{
923	  vshift = 1;
924	  rval = 2;
925	}
926
927      op->reg = 0;		/* Reg PC.  */
928      op->am = 3;
929      op->ol = 1;		/* Immediate  will follow an instruction.  */
930      __tl = h + 1 + rval;
931      op->mode = OP_EXP;
932      parse_exp (__tl, &(op->exp));
933      if (op->exp.X_op == O_constant)
934	{
935	  int x = op->exp.X_add_number;
936
937	  if (vshift == 0)
938	    {
939	      x = x & 0xffff;
940	      op->exp.X_add_number = x;
941	    }
942	  else if (vshift == 1)
943	    {
944	      x = (x >> 16) & 0xffff;
945	      op->exp.X_add_number = x;
946	    }
947	  else if (vshift > 1)
948	    {
949	      if (x < 0)
950		op->exp.X_add_number = -1;
951	      else
952		op->exp.X_add_number = 0;	/* Nothing left.  */
953	      x = op->exp.X_add_number;
954	    }
955
956	  if (op->exp.X_add_number > 65535 || op->exp.X_add_number < -32768)
957	    {
958	      as_bad (_("value %ld out of range. Use #lo() or #hi()"), x);
959	      return 1;
960	    }
961
962	  /* Now check constants.  */
963	  /* Substitute register mode with a constant generator if applicable.  */
964
965	  x = (short) x;	/* Extend sign.  */
966
967	  if (x == 0)
968	    {
969	      op->reg = 3;
970	      op->am = 0;
971	      op->ol = 0;
972	      op->mode = OP_REG;
973	    }
974	  else if (x == 1)
975	    {
976	      op->reg = 3;
977	      op->am = 1;
978	      op->ol = 0;
979	      op->mode = OP_REG;
980	    }
981	  else if (x == 2)
982	    {
983	      op->reg = 3;
984	      op->am = 2;
985	      op->ol = 0;
986	      op->mode = OP_REG;
987	    }
988	  else if (x == -1)
989	    {
990	      op->reg = 3;
991	      op->am = 3;
992	      op->ol = 0;
993	      op->mode = OP_REG;
994	    }
995	  else if (x == 4)
996	    {
997#ifdef PUSH_1X_WORKAROUND
998	      if (bin == 0x1200)
999		{
1000		  /* Remove warning as confusing.
1001		     as_warn(_("Hardware push bug workaround")); */
1002		}
1003	      else
1004#endif
1005		{
1006		  op->reg = 2;
1007		  op->am = 2;
1008		  op->ol = 0;
1009		  op->mode = OP_REG;
1010		}
1011	    }
1012	  else if (x == 8)
1013	    {
1014#ifdef PUSH_1X_WORKAROUND
1015	      if (bin == 0x1200)
1016		{
1017		  /* Remove warning as confusing.
1018		     as_warn(_("Hardware push bug workaround")); */
1019		}
1020	      else
1021#endif
1022		{
1023		  op->reg = 2;
1024		  op->am = 3;
1025		  op->ol = 0;
1026		  op->mode = OP_REG;
1027		}
1028	    }
1029	}
1030      else if (op->exp.X_op == O_symbol)
1031	{
1032	  op->mode = OP_EXP;
1033	}
1034      else if (op->exp.X_op == O_big)
1035	{
1036	  short x;
1037	  if (vshift != -1)
1038	    {
1039	      op->exp.X_op = O_constant;
1040	      op->exp.X_add_number = 0xffff & generic_bignum[vshift];
1041	      x = op->exp.X_add_number;
1042	    }
1043	  else
1044	    {
1045	      as_bad (_
1046		      ("unknown expression in operand %s. use #llo() #lhi() #hlo() #hhi() "),
1047		      l);
1048	      return 1;
1049	    }
1050
1051	  if (x == 0)
1052	    {
1053	      op->reg = 3;
1054	      op->am = 0;
1055	      op->ol = 0;
1056	      op->mode = OP_REG;
1057	    }
1058	  else if (x == 1)
1059	    {
1060	      op->reg = 3;
1061	      op->am = 1;
1062	      op->ol = 0;
1063	      op->mode = OP_REG;
1064	    }
1065	  else if (x == 2)
1066	    {
1067	      op->reg = 3;
1068	      op->am = 2;
1069	      op->ol = 0;
1070	      op->mode = OP_REG;
1071	    }
1072	  else if (x == -1)
1073	    {
1074	      op->reg = 3;
1075	      op->am = 3;
1076	      op->ol = 0;
1077	      op->mode = OP_REG;
1078	    }
1079	  else if (x == 4)
1080	    {
1081	      op->reg = 2;
1082	      op->am = 2;
1083	      op->ol = 0;
1084	      op->mode = OP_REG;
1085	    }
1086	  else if (x == 8)
1087	    {
1088	      op->reg = 2;
1089	      op->am = 3;
1090	      op->ol = 0;
1091	      op->mode = OP_REG;
1092	    }
1093	}
1094      else
1095	{
1096	  as_bad (_("unknown operand %s"), l);
1097	}
1098      return 0;
1099    }
1100
1101  /* Check if absolute &VALUE (assume that we can construct something like ((a&b)<<7 + 25).  */
1102  if (*l == '&')
1103    {
1104      char *h = l;
1105
1106      op->reg = 2;		/* reg 2 in absolute addr mode.  */
1107      op->am = 1;		/* mode As == 01 bin.  */
1108      op->ol = 1;		/* Immediate value followed by instruction.  */
1109      __tl = h + 1;
1110      parse_exp (__tl, &(op->exp));
1111      op->mode = OP_EXP;
1112      if (op->exp.X_op == O_constant)
1113	{
1114	  int x = op->exp.X_add_number;
1115	  if (x > 65535 || x < -32768)
1116	    {
1117	      as_bad (_("value out of range: %d"), x);
1118	      return 1;
1119	    }
1120	}
1121      else if (op->exp.X_op == O_symbol)
1122	{
1123	}
1124      else
1125	{
1126	  as_bad (_("unknown expression in operand %s"), l);
1127	  return 1;
1128	}
1129      return 0;
1130    }
1131
1132  /* Check if indirect register mode @Rn / postincrement @Rn+.  */
1133  if (*l == '@')
1134    {
1135      char *t = l;
1136      char *m = strchr (l, '+');
1137
1138      if (t != l)
1139	{
1140	  as_bad (_("unknown addressing mode %s"), l);
1141	  return 1;
1142	}
1143
1144      t++;
1145      if (*t != 'r' && *t != 'R')
1146	{
1147	  as_bad (_("unknown addressing mode %s"), l);
1148	  return 1;
1149	}
1150
1151      t++;	/* Points to the reg value.  */
1152
1153      if (check_reg (t))
1154	{
1155	  as_bad (_("Bad register name r%s"), t);
1156	  return 1;
1157	}
1158
1159      op->mode = OP_REG;
1160      op->am = m ? 3 : 2;
1161      op->ol = 0;
1162      if (m)
1163	*m = 0;			/* strip '+' */
1164      op->reg = atoi (t);
1165      if (op->reg < 0 || op->reg > 15)
1166	{
1167	  as_bad (_("MSP430 does not have %d registers"), op->reg);
1168	  return 1;
1169	}
1170
1171      return 0;
1172    }
1173
1174  /* Check if register indexed X(Rn).  */
1175  do
1176    {
1177      char *h = strrchr (l, '(');
1178      char *m = strrchr (l, ')');
1179      char *t;
1180
1181      *imm_op = 1;
1182
1183      if (!h)
1184	break;
1185      if (!m)
1186	{
1187	  as_bad (_("')' required"));
1188	  return 1;
1189	}
1190
1191      t = h;
1192      op->am = 1;
1193      op->ol = 1;
1194      /* Extract a register.  */
1195      t++;	/* Advance pointer.  */
1196
1197      if (*t != 'r' && *t != 'R')
1198	{
1199	  as_bad (_
1200		  ("unknown operator %s. Did you mean X(Rn) or #[hl][hl][oi](CONST) ?"),
1201		  l);
1202	  return 1;
1203	}
1204      t++;
1205
1206      op->reg = *t - '0';
1207      if (op->reg > 9 || op->reg < 0)
1208	{
1209	  as_bad (_("unknown operator (r%s substituded as a register name"),
1210		  t);
1211	  return 1;
1212	}
1213      t++;
1214      if (*t != ')')
1215	{
1216	  op->reg = op->reg * 10;
1217	  op->reg += *t - '0';
1218
1219	  if (op->reg > 15)
1220	    {
1221	      as_bad (_("unknown operator %s"), l);
1222	      return 1;
1223	    }
1224	  if (op->reg == 2)
1225	    {
1226	      as_bad (_("r2 should not be used in indexed addressing mode"));
1227	      return 1;
1228	    }
1229
1230	  if (*(t + 1) != ')')
1231	    {
1232	      as_bad (_("unknown operator %s"), l);
1233	      return 1;
1234	    }
1235	}
1236
1237      /* Extract constant.  */
1238      __tl = l;
1239      *h = 0;
1240      op->mode = OP_EXP;
1241      parse_exp (__tl, &(op->exp));
1242      if (op->exp.X_op == O_constant)
1243	{
1244	  int x = op->exp.X_add_number;
1245
1246	  if (x > 65535 || x < -32768)
1247	    {
1248	      as_bad (_("value out of range: %d"), x);
1249	      return 1;
1250	    }
1251
1252	  if (x == 0)
1253	    {
1254	      op->mode = OP_REG;
1255	      op->am = 2;
1256	      op->ol = 0;
1257	      return 0;
1258	    }
1259	}
1260      else if (op->exp.X_op == O_symbol)
1261	{
1262	}
1263      else
1264	{
1265	  as_bad (_("unknown expression in operand %s"), l);
1266	  return 1;
1267	}
1268
1269      return 0;
1270    }
1271  while (0);
1272
1273  /* Register mode 'mov r1,r2'.  */
1274  do
1275    {
1276      char *t = l;
1277
1278      /* Operand should be a register.  */
1279      if (*t == 'r' || *t == 'R')
1280	{
1281	  int x = atoi (t + 1);
1282
1283	  if (check_reg (t + 1))
1284	    break;
1285
1286	  if (x < 0 || x > 15)
1287	    break;		/* Symbolic mode.  */
1288
1289	  op->mode = OP_REG;
1290	  op->am = 0;
1291	  op->ol = 0;
1292	  op->reg = x;
1293	  return 0;
1294	}
1295    }
1296  while (0);
1297
1298  /* Symbolic mode 'mov a, b' == 'mov x(pc), y(pc)'.  */
1299  do
1300    {
1301      char *t = l;
1302
1303      __tl = l;
1304
1305      while (*t)
1306	{
1307	  /* alpha/number    underline     dot for labels.  */
1308	  if (! ISALNUM (*t) && *t != '_' && *t != '.')
1309	    {
1310	      as_bad (_("unknown operand %s"), l);
1311	      return 1;
1312	    }
1313	  t++;
1314	}
1315
1316      op->mode = OP_EXP;
1317      op->reg = 0;		/* PC relative... be careful.  */
1318      op->am = 1;
1319      op->ol = 1;
1320      __tl = l;
1321      parse_exp (__tl, &(op->exp));
1322      return 0;
1323    }
1324  while (0);
1325
1326  /* Unreachable.  */
1327  as_bad (_("unknown addressing mode for operand %s"), l);
1328  return 1;
1329}
1330
1331
1332/* GAS will call this function for each section at the end of the assembly,
1333   to permit the CPU backend to adjust the alignment of a section.  */
1334
1335valueT
1336md_section_align (seg, addr)
1337     asection *seg;
1338     valueT addr;
1339{
1340  int align = bfd_get_section_alignment (stdoutput, seg);
1341
1342  return ((addr + (1 << align) - 1) & (-1 << align));
1343}
1344
1345/* If you define this macro, it should return the offset between the
1346   address of a PC relative fixup and the position from which the PC
1347   relative adjustment should be made.  On many processors, the base
1348   of a PC relative instruction is the next instruction, so this
1349   macro would return the length of an instruction.  */
1350
1351long
1352md_pcrel_from_section (fixp, sec)
1353     fixS *fixp;
1354     segT sec;
1355{
1356  if (fixp->fx_addsy != (symbolS *) NULL
1357      && (!S_IS_DEFINED (fixp->fx_addsy)
1358	  || (S_GET_SEGMENT (fixp->fx_addsy) != sec)))
1359    return 0;
1360
1361  return fixp->fx_frag->fr_address + fixp->fx_where;
1362}
1363
1364/* GAS will call this for each fixup.  It should store the correct
1365   value in the object file.  */
1366
1367void
1368md_apply_fix3 (fixp, valuep, seg)
1369     fixS *fixp;
1370     valueT *valuep;
1371     segT seg;
1372{
1373  unsigned char *where;
1374  unsigned long insn;
1375  long value;
1376
1377  if (fixp->fx_addsy == (symbolS *) NULL)
1378    {
1379      value = *valuep;
1380      fixp->fx_done = 1;
1381    }
1382  else if (fixp->fx_pcrel)
1383    {
1384      segT s = S_GET_SEGMENT (fixp->fx_addsy);
1385
1386      if (fixp->fx_addsy && (s == seg || s == absolute_section))
1387	{
1388	  value = S_GET_VALUE (fixp->fx_addsy) + *valuep;
1389	  fixp->fx_done = 1;
1390	}
1391      else
1392	value = *valuep;
1393    }
1394  else
1395    {
1396      value = fixp->fx_offset;
1397
1398      if (fixp->fx_subsy != (symbolS *) NULL)
1399	{
1400	  if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
1401	    {
1402	      value -= S_GET_VALUE (fixp->fx_subsy);
1403	      fixp->fx_done = 1;
1404	    }
1405	  else
1406	    {
1407	      /* We don't actually support subtracting a symbol.  */
1408	      as_bad_where (fixp->fx_file, fixp->fx_line,
1409			    _("expression too complex"));
1410	    }
1411	}
1412    }
1413
1414  switch (fixp->fx_r_type)
1415    {
1416    default:
1417      fixp->fx_no_overflow = 1;
1418      break;
1419    case BFD_RELOC_MSP430_10_PCREL:
1420      break;
1421    }
1422
1423  if (fixp->fx_done)
1424    {
1425      /* Fetch the instruction, insert the fully resolved operand
1426	 value, and stuff the instruction back again.  */
1427
1428      where = fixp->fx_frag->fr_literal + fixp->fx_where;
1429
1430      insn = bfd_getl16 (where);
1431
1432      switch (fixp->fx_r_type)
1433	{
1434	case BFD_RELOC_MSP430_10_PCREL:
1435	  if (value & 1)
1436	    as_bad_where (fixp->fx_file, fixp->fx_line,
1437			  _("odd address operand: %ld"), value);
1438
1439	  /* Jumps are in words.  */
1440	  value >>= 1;
1441	  --value;		/* Correct PC.  */
1442
1443	  if (value < -512 || value > 511)
1444	    as_bad_where (fixp->fx_file, fixp->fx_line,
1445			  _("operand out of range: %ld"), value);
1446
1447	  value &= 0x3ff;	/* get rid of extended sign */
1448	  bfd_putl16 ((bfd_vma) (value | insn), where);
1449	  break;
1450
1451	case BFD_RELOC_MSP430_16_PCREL:
1452	  if (value & 1)
1453	    as_bad_where (fixp->fx_file, fixp->fx_line,
1454			  _("odd address operand: %ld"), value);
1455
1456	  /* Nothing to be corrected here.  */
1457	  if (value < -32768 || value > 65536)
1458	    as_bad_where (fixp->fx_file, fixp->fx_line,
1459			  _("operand out of range: %ld"), value);
1460
1461	  value &= 0xffff;	/* Get rid of extended sign.  */
1462	  bfd_putl16 ((bfd_vma) value, where);
1463	  break;
1464
1465	case BFD_RELOC_MSP430_16_PCREL_BYTE:
1466	  /* Nothing to be corrected here.  */
1467	  if (value < -32768 || value > 65536)
1468	    as_bad_where (fixp->fx_file, fixp->fx_line,
1469			  _("operand out of range: %ld"), value);
1470
1471	  value &= 0xffff;	/* Get rid of extended sign.  */
1472	  bfd_putl16 ((bfd_vma) value, where);
1473	  break;
1474
1475	case BFD_RELOC_32:
1476	  bfd_putl16 ((bfd_vma) value, where);
1477	  break;
1478
1479	case BFD_RELOC_MSP430_16:
1480	case BFD_RELOC_16:
1481	case BFD_RELOC_MSP430_16_BYTE:
1482	  value &= 0xffff;
1483	  bfd_putl16 ((bfd_vma) value, where);
1484	  break;
1485
1486	default:
1487	  as_fatal (_("line %d: unknown relocation type: 0x%x"),
1488		    fixp->fx_line, fixp->fx_r_type);
1489	  break;
1490	}
1491    }
1492  else
1493    {
1494      fixp->fx_addnumber = value;
1495    }
1496}
1497
1498/* A `BFD_ASSEMBLER' GAS will call this to generate a reloc.  GAS
1499   will pass the resulting reloc to `bfd_install_relocation'.  This
1500   currently works poorly, as `bfd_install_relocation' often does the
1501   wrong thing, and instances of `tc_gen_reloc' have been written to
1502   work around the problems, which in turns makes it difficult to fix
1503   `bfd_install_relocation'.  */
1504
1505/* If while processing a fixup, a reloc really needs to be created
1506   then it is done here.  */
1507
1508arelent *
1509tc_gen_reloc (seg, fixp)
1510     asection *seg ATTRIBUTE_UNUSED;
1511     fixS *fixp;
1512{
1513  arelent *reloc;
1514
1515  reloc = (arelent *) xmalloc (sizeof (arelent));
1516
1517  reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
1518  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
1519
1520  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
1521  reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
1522  if (reloc->howto == (reloc_howto_type *) NULL)
1523    {
1524      as_bad_where (fixp->fx_file, fixp->fx_line,
1525		    _("reloc %d not supported by object file format"),
1526		    (int) fixp->fx_r_type);
1527      return NULL;
1528    }
1529
1530  if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
1531      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
1532    reloc->address = fixp->fx_offset;
1533
1534  reloc->addend = fixp->fx_offset;
1535
1536  return reloc;
1537}
1538
1539/* Parse ordinary expression.  */
1540
1541static char *
1542parse_exp (s, op)
1543     char *s;
1544     expressionS *op;
1545{
1546  input_line_pointer = s;
1547  expression (op);
1548  if (op->X_op == O_absent)
1549    as_bad (_("missing operand"));
1550  return input_line_pointer;
1551}
1552
1553
1554int
1555md_estimate_size_before_relax (fragp, seg)
1556     fragS *fragp ATTRIBUTE_UNUSED;
1557     asection *seg ATTRIBUTE_UNUSED;
1558{
1559  abort ();
1560  return 0;
1561}
1562