Cache result of scan for __start_* and __stop_* sections
[external/binutils.git] / cpu / xstormy16.opc
1 /* XSTORMY16 opcode support.  -*- C -*-
2    Copyright 2011 Free Software Foundation, Inc.
3
4    Contributed by Red Hat Inc;
5
6    This file is part of the GNU Binutils.
7
8    This program 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 3 of the License, or
11    (at your option) any later version.
12
13    This program 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 this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21    MA 02110-1301, USA.  */
22
23 /* This file is an addendum to xstormy16.cpu.  Heavy use of C code isn't
24    appropriate in .cpu files, so it resides here.  This especially applies
25    to assembly/disassembly where parsing/printing can be quite involved.
26    Such things aren't really part of the specification of the cpu, per se,
27    so .cpu files provide the general framework and .opc files handle the
28    nitty-gritty details as necessary.
29
30    Each section is delimited with start and end markers.
31
32    <arch>-opc.h additions use: "-- opc.h"
33    <arch>-opc.c additions use: "-- opc.c"
34    <arch>-asm.c additions use: "-- asm.c"
35    <arch>-dis.c additions use: "-- dis.c"
36    <arch>-ibd.h additions use: "-- ibd.h".  */
37 \f
38 /* -- opc.h */
39
40 /* Allows reason codes to be output when assembler errors occur.  */
41 #define CGEN_VERBOSE_ASSEMBLER_ERRORS
42
43 /* We can't use the default hash size because many bits are used by
44    operands.  */
45 #define CGEN_DIS_HASH_SIZE 1
46 #define CGEN_DIS_HASH(buf, value) 0
47 /* -- */
48 \f
49 /* -- asm.c */
50
51 /* The machine-independent code doesn't know how to disambiguate
52      mov (foo),r3
53    and
54      mov (r2),r3
55    where 'foo' is a label.  This helps it out. */
56
57 static const char *
58 parse_mem8 (CGEN_CPU_DESC cd,
59             const char **strp,
60             int opindex,
61             unsigned long *valuep)
62 {
63   if (**strp == '(')
64     {
65       const char *s = *strp;
66       
67       if (s[1] == '-' && s[2] == '-')
68         return _("Bad register in preincrement");
69
70       while (ISALNUM (*++s))
71         ;
72       if (s[0] == '+' && s[1] == '+' && (s[2] == ')' || s[2] == ','))
73         return _("Bad register in postincrement");
74       if (s[0] == ',' || s[0] == ')')
75         return _("Bad register name");
76     }
77   else if (cgen_parse_keyword (cd, strp, & xstormy16_cgen_opval_gr_names, 
78                                (long *) valuep) == NULL)
79     return _("Label conflicts with register name");
80   else if (strncasecmp (*strp, "rx,", 3) == 0
81            || strncasecmp (*strp, "rxl,", 3) == 0
82            || strncasecmp (*strp, "rxh,", 3) == 0)
83     return _("Label conflicts with `Rx'");
84   else if (**strp == '#')
85     return _("Bad immediate expression");
86   
87   return cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
88 }
89
90 /* For the add and subtract instructions, there are two immediate forms,
91    one for small operands and one for large ones.  We want to use
92    the small one when possible, but we do not want to generate relocs
93    of the small size.  This is somewhat tricky.  */
94    
95 static const char *
96 parse_small_immediate (CGEN_CPU_DESC cd,
97                        const char **strp,
98                        int opindex,
99                        unsigned long *valuep)
100 {
101   bfd_vma value;
102   enum cgen_parse_operand_result result;
103   const char *errmsg;
104
105   if (**strp == '@')
106     return _("No relocation for small immediate");
107
108   errmsg = (* cd->parse_operand_fn)
109     (cd, CGEN_PARSE_OPERAND_INTEGER, strp, opindex, BFD_RELOC_NONE,
110      & result, & value);
111   
112   if (errmsg)
113     return errmsg;
114
115   if (result != CGEN_PARSE_OPERAND_RESULT_NUMBER)
116     return _("Small operand was not an immediate number");
117
118   *valuep = value;
119   return NULL;
120 }
121
122 /* Literal scan be either a normal literal, a @hi() or @lo relocation.  */
123    
124 static const char *
125 parse_immediate16 (CGEN_CPU_DESC cd,
126                    const char **strp,
127                    int opindex,
128                    unsigned long *valuep)
129 {
130   const char *errmsg;
131   enum cgen_parse_operand_result result;
132   bfd_reloc_code_real_type code = BFD_RELOC_NONE;
133   bfd_vma value;
134
135   if (strncmp (*strp, "@hi(", 4) == 0)
136     {
137       *strp += 4;
138       code = BFD_RELOC_HI16;
139     }
140   else
141   if (strncmp (*strp, "@lo(", 4) == 0)
142     {
143       *strp += 4;
144       code = BFD_RELOC_LO16;
145     }
146
147   if (code == BFD_RELOC_NONE)
148     errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
149   else
150     {
151       errmsg = cgen_parse_address (cd, strp, opindex, code, &result, &value);
152       if ((errmsg == NULL) &&
153           (result != CGEN_PARSE_OPERAND_RESULT_QUEUED))
154         errmsg = _("Operand is not a symbol");
155
156       *valuep = value;
157       if ((code == BFD_RELOC_HI16 || code == BFD_RELOC_LO16)
158           && **strp == ')')        
159         *strp += 1;
160       else
161         {
162           errmsg = _("Syntax error: No trailing ')'");
163           return errmsg;
164         }
165     }
166   return errmsg;
167 }
168 /* -- */