2005-10-28 Dave Brolley <brolley@redhat.com>
[deliverable/binutils-gdb.git] / cpu / ms1.opc
CommitLineData
b081650b
DB
1/* Morpho Technologies mRISC opcode support, for GNU Binutils. -*- C -*-
2 Copyright 2001 Free Software Foundation, Inc.
3
4 Contributed by Red Hat Inc; developed under contract from
5 Morpho Technologies.
6
7 This file is part of the GNU Binutils.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
22
23*/
24
25/*
26 Each section is delimited with start and end markers.
27
28 <arch>-opc.h additions use: "-- opc.h"
29 <arch>-opc.c additions use: "-- opc.c"
30 <arch>-asm.c additions use: "-- asm.c"
31 <arch>-dis.c additions use: "-- dis.c"
32 <arch>-ibd.h additions use: "-- ibd.h"
33*/
34\f
35/* -- opc.h */
36
37/* Check applicability of instructions against machines. */
38#define CGEN_VALIDATE_INSN_SUPPORTED
39
40/* Allows reason codes to be output when assembler errors occur. */
41#define CGEN_VERBOSE_ASSEMBLER_ERRORS
42
43/* Override disassembly hashing - there are variable bits in the top
44 byte of these instructions. */
45#define CGEN_DIS_HASH_SIZE 8
46#define CGEN_DIS_HASH(buf, value) (((* (unsigned char *) (buf)) >> 5) % CGEN_DIS_HASH_SIZE)
47
48#define CGEN_ASM_HASH_SIZE 127
49#define CGEN_ASM_HASH(insn) ms1_asm_hash (insn)
50
51extern unsigned int ms1_asm_hash (const char *);
52
53extern int ms1_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
54
55\f
56/* -- opc.c */
57#include "safe-ctype.h"
58
59/* Special check to ensure that instruction exists for given machine. */
60
61int
62ms1_cgen_insn_supported (CGEN_CPU_DESC cd,
63 const CGEN_INSN *insn)
64{
65 int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
66
67 /* No mach attribute? Assume it's supported for all machs. */
68 if (machs == 0)
69 return 1;
70
71 return ((machs & cd->machs) != 0);
72}
73
74/* A better hash function for instruction mnemonics. */
75
76unsigned int
77ms1_asm_hash (const char* insn)
78{
79 unsigned int hash;
80 const char* m = insn;
81
82 for (hash = 0; *m && ! ISSPACE (*m); m++)
83 hash = (hash * 23) ^ (0x1F & TOLOWER (*m));
84
85 /* printf ("%s %d\n", insn, (hash % CGEN_ASM_HASH_SIZE)); */
86
87 return hash % CGEN_ASM_HASH_SIZE;
88}
89
90\f
91/* -- asm.c */
b081650b
DB
92/* Range checking for signed numbers. Returns 0 if acceptable
93 and 1 if the value is out of bounds for a signed quantity. */
94
95static int
96signed_out_of_bounds (long val)
97{
98 if ((val < -32768) || (val > 32767))
99 return 1;
100 return 0;
101}
102
103static const char *
104parse_imm16 (CGEN_CPU_DESC cd,
105 const char **strp,
106 int opindex,
3ec2b351 107 void *arg)
b081650b 108{
3ec2b351 109 signed long * valuep = (signed long *) arg;
b081650b
DB
110 const char *errmsg;
111 enum cgen_parse_operand_result result_type;
112 bfd_reloc_code_real_type code = BFD_RELOC_NONE;
113 bfd_vma value;
114
115 /* Is it a control transfer instructions? */
116 if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_IMM16O)
117 {
118 code = BFD_RELOC_16_PCREL;
119 errmsg = cgen_parse_address (cd, strp, opindex, code,
120 & result_type, & value);
121 if (errmsg == NULL)
122 {
123 if (signed_out_of_bounds (value))
124 errmsg = _("Operand out of range. Must be between -32768 and 32767.");
125 }
126 *valuep = value;
127 return errmsg;
128 }
129
130 /* If it's not a control transfer instruction, then
131 we have to check for %OP relocating operators. */
132 if (strncmp (*strp, "%hi16", 5) == 0)
133 {
134 *strp += 5;
135 code = BFD_RELOC_HI16;
136 }
137 else if (strncmp (*strp, "%lo16", 5) == 0)
138 {
139 *strp += 5;
140 code = BFD_RELOC_LO16;
141 }
142
143 /* If we found a %OP relocating operator, then parse it as an address.
144 If not, we need to parse it as an integer, either signed or unsigned
145 depending on which operand type we have. */
146 if (code != BFD_RELOC_NONE)
147 {
148 /* %OP relocating operator found. */
149 errmsg = cgen_parse_address (cd, strp, opindex, code,
150 & result_type, & value);
151 if (errmsg == NULL)
152 {
153 switch (result_type)
154 {
155 case (CGEN_PARSE_OPERAND_RESULT_NUMBER):
156 if (code == BFD_RELOC_HI16)
157 value = (value >> 16) & 0xFFFF;
158 else if (code == BFD_RELOC_LO16)
159 value = value & 0xFFFF;
160 else
161 errmsg = _("Biiiig Trouble in parse_imm16!");
162 break;
163
164 case (CGEN_PARSE_OPERAND_RESULT_QUEUED):
165 /* No special processing for this case. */
166 break;
167
168 default:
169 errmsg = _("%operator operand is not a symbol");
170 break;
171 }
172 }
173 *valuep = value;
174 }
175 else
176 {
177 /* Parse hex values like 0xffff as unsigned, and sign extend
178 them manually. */
179 int parse_signed = (opindex == (CGEN_OPERAND_TYPE)MS1_OPERAND_IMM16);
180
181 if ((*strp)[0] == '0'
182 && ((*strp)[1] == 'x' || (*strp)[1] == 'X'))
183 parse_signed = 0;
184
185 /* No relocating operator. Parse as an number. */
186 if (parse_signed)
187 {
188 /* Parse as as signed integer. */
189
190 errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
191
192 if (errmsg == NULL)
193 {
194#if 0
195 /* Manual range checking is needed for the signed case. */
196 if (*valuep & 0x8000)
197 value = 0xffff0000 | *valuep;
198 else
199 value = *valuep;
200
201 if (signed_out_of_bounds (value))
202 errmsg = _("Operand out of range. Must be between -32768 and 32767.");
203 /* Truncate to 16 bits. This is necessary
204 because cgen will have sign extended *valuep. */
205 *valuep &= 0xFFFF;
206#endif
207 }
208 }
209 else
210 {
211 /* MS1_OPERAND_IMM16Z. Parse as an unsigned integer. */
3ec2b351 212 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) valuep);
b081650b 213
3ec2b351 214 if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_IMM16
b081650b
DB
215 && *valuep >= 0x8000
216 && *valuep <= 0xffff)
217 *valuep -= 0x10000;
218 }
219 }
220
221 return errmsg;
222}
223
224
225static const char *
226parse_dup (CGEN_CPU_DESC cd,
227 const char **strp,
228 int opindex,
3ec2b351 229 unsigned long *valuep)
b081650b
DB
230{
231 const char *errmsg = NULL;
232
233 if (strncmp (*strp, "dup", 3) == 0 || strncmp (*strp, "DUP", 3) == 0)
234 {
235 *strp += 3;
236 *valuep = 1;
237 }
238 else if (strncmp (*strp, "xx", 2) == 0 || strncmp (*strp, "XX", 2) == 0)
239 {
240 *strp += 2;
241 *valuep = 0;
242 }
243 else
244 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
245
246 return errmsg;
247}
248
249
250static const char *
251parse_ball (CGEN_CPU_DESC cd,
252 const char **strp,
253 int opindex,
3ec2b351 254 unsigned long *valuep)
b081650b
DB
255{
256 const char *errmsg = NULL;
257
258 if (strncmp (*strp, "all", 3) == 0 || strncmp (*strp, "ALL", 3) == 0)
259 {
260 *strp += 3;
261 *valuep = 1;
262 }
263 else if (strncmp (*strp, "one", 3) == 0 || strncmp (*strp, "ONE", 3) == 0)
264 {
265 *strp += 3;
266 *valuep = 0;
267 }
268 else
269 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
270
271 return errmsg;
272}
273
274static const char *
275parse_xmode (CGEN_CPU_DESC cd,
276 const char **strp,
277 int opindex,
3ec2b351 278 unsigned long *valuep)
b081650b
DB
279{
280 const char *errmsg = NULL;
281
282 if (strncmp (*strp, "pm", 2) == 0 || strncmp (*strp, "PM", 2) == 0)
283 {
284 *strp += 2;
285 *valuep = 1;
286 }
287 else if (strncmp (*strp, "xm", 2) == 0 || strncmp (*strp, "XM", 2) == 0)
288 {
289 *strp += 2;
290 *valuep = 0;
291 }
292 else
293 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
294
295 return errmsg;
296}
297
298static const char *
299parse_rc (CGEN_CPU_DESC cd,
300 const char **strp,
301 int opindex,
3ec2b351 302 unsigned long *valuep)
b081650b
DB
303{
304 const char *errmsg = NULL;
305
306 if (strncmp (*strp, "r", 1) == 0 || strncmp (*strp, "R", 1) == 0)
307 {
308 *strp += 1;
309 *valuep = 1;
310 }
311 else if (strncmp (*strp, "c", 1) == 0 || strncmp (*strp, "C", 1) == 0)
312 {
313 *strp += 1;
314 *valuep = 0;
315 }
316 else
317 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
318
319 return errmsg;
320}
321
322static const char *
323parse_cbrb (CGEN_CPU_DESC cd,
324 const char **strp,
325 int opindex,
3ec2b351 326 unsigned long *valuep)
b081650b
DB
327{
328 const char *errmsg = NULL;
329
330 if (strncmp (*strp, "rb", 2) == 0 || strncmp (*strp, "RB", 2) == 0)
331 {
332 *strp += 2;
333 *valuep = 1;
334 }
335 else if (strncmp (*strp, "cb", 2) == 0 || strncmp (*strp, "CB", 2) == 0)
336 {
337 *strp += 2;
338 *valuep = 0;
339 }
340 else
341 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
342
343 return errmsg;
344}
345
346static const char *
347parse_rbbc (CGEN_CPU_DESC cd,
348 const char **strp,
349 int opindex,
3ec2b351 350 unsigned long *valuep)
b081650b
DB
351{
352 const char *errmsg = NULL;
353
354 if (strncmp (*strp, "rt", 2) == 0 || strncmp (*strp, "RT", 2) == 0)
355 {
356 *strp += 2;
357 *valuep = 0;
358 }
359 else if (strncmp (*strp, "br1", 3) == 0 || strncmp (*strp, "BR1", 3) == 0)
360 {
361 *strp += 3;
362 *valuep = 1;
363 }
364 else if (strncmp (*strp, "br2", 3) == 0 || strncmp (*strp, "BR2", 3) == 0)
365 {
366 *strp += 3;
367 *valuep = 2;
368 }
369 else if (strncmp (*strp, "cs", 2) == 0 || strncmp (*strp, "CS", 2) == 0)
370 {
371 *strp += 2;
372 *valuep = 3;
373 }
374 else
375 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
376
377 return errmsg;
378}
379
380static const char *
381parse_type (CGEN_CPU_DESC cd,
382 const char **strp,
383 int opindex,
3ec2b351 384 unsigned long *valuep)
b081650b
DB
385{
386 const char *errmsg = NULL;
387
388 if (strncmp (*strp, "odd", 3) == 0 || strncmp (*strp, "ODD", 3) == 0)
389 {
390 *strp += 3;
391 *valuep = 0;
392 }
393 else if (strncmp (*strp, "even", 4) == 0 || strncmp (*strp, "EVEN", 4) == 0)
394 {
395 *strp += 4;
396 *valuep = 1;
397 }
398 else if (strncmp (*strp, "oe", 2) == 0 || strncmp (*strp, "OE", 2) == 0)
399 {
400 *strp += 2;
401 *valuep = 2;
402 }
403 else
404 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
405
406 if ((errmsg == NULL) && (*valuep == 3))
407 errmsg = _("invalid operand. type may have values 0,1,2 only.");
408
409 return errmsg;
410}
411
412/* -- dis.c */
413static void print_dollarhex (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
414
415static void
416print_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
417 void * dis_info,
418 long value,
419 unsigned int attrs ATTRIBUTE_UNUSED,
420 bfd_vma pc ATTRIBUTE_UNUSED,
421 int length ATTRIBUTE_UNUSED)
422{
423 disassemble_info *info = (disassemble_info *) dis_info;
424
0e6b69be 425 info->fprintf_func (info->stream, "$%lx", value);
b081650b
DB
426
427 if (0)
428 print_normal (cd, dis_info, value, attrs, pc, length);
429}
430
431
432/* -- */
433
434
435
436
437
This page took 0.053453 seconds and 4 git commands to generate.