* elf64-ppc.c (ppc64_elf_size_stubs): Don't consider non-ppc64 input.
[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
6f84a2a6
NS
103static const char *
104parse_loopsize (CGEN_CPU_DESC cd,
105 const char **strp,
106 int opindex,
107 void *arg)
108{
109 signed long * valuep = (signed long *) arg;
110 const char *errmsg;
111 bfd_reloc_code_real_type code = BFD_RELOC_NONE;
112 enum cgen_parse_operand_result result_type;
113 bfd_vma value;
114
115 /* Is it a control transfer instructions? */
116 if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_LOOPSIZE)
117 {
118 code = BFD_RELOC_MS1_PCINSN8;
119 errmsg = cgen_parse_address (cd, strp, opindex, code,
120 & result_type, & value);
121 *valuep = value;
122 return errmsg;
123 }
124
125 abort ();
126}
127
b081650b
DB
128static const char *
129parse_imm16 (CGEN_CPU_DESC cd,
130 const char **strp,
131 int opindex,
3ec2b351 132 void *arg)
b081650b 133{
3ec2b351 134 signed long * valuep = (signed long *) arg;
b081650b
DB
135 const char *errmsg;
136 enum cgen_parse_operand_result result_type;
137 bfd_reloc_code_real_type code = BFD_RELOC_NONE;
138 bfd_vma value;
139
140 /* Is it a control transfer instructions? */
141 if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_IMM16O)
142 {
143 code = BFD_RELOC_16_PCREL;
144 errmsg = cgen_parse_address (cd, strp, opindex, code,
145 & result_type, & value);
146 if (errmsg == NULL)
147 {
148 if (signed_out_of_bounds (value))
149 errmsg = _("Operand out of range. Must be between -32768 and 32767.");
150 }
151 *valuep = value;
152 return errmsg;
153 }
154
155 /* If it's not a control transfer instruction, then
156 we have to check for %OP relocating operators. */
6f84a2a6
NS
157 if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_IMM16L)
158 ;
159 else if (strncmp (*strp, "%hi16", 5) == 0)
b081650b
DB
160 {
161 *strp += 5;
162 code = BFD_RELOC_HI16;
163 }
164 else if (strncmp (*strp, "%lo16", 5) == 0)
165 {
166 *strp += 5;
167 code = BFD_RELOC_LO16;
168 }
169
170 /* If we found a %OP relocating operator, then parse it as an address.
171 If not, we need to parse it as an integer, either signed or unsigned
172 depending on which operand type we have. */
173 if (code != BFD_RELOC_NONE)
174 {
175 /* %OP relocating operator found. */
176 errmsg = cgen_parse_address (cd, strp, opindex, code,
177 & result_type, & value);
178 if (errmsg == NULL)
179 {
180 switch (result_type)
181 {
182 case (CGEN_PARSE_OPERAND_RESULT_NUMBER):
183 if (code == BFD_RELOC_HI16)
184 value = (value >> 16) & 0xFFFF;
185 else if (code == BFD_RELOC_LO16)
186 value = value & 0xFFFF;
187 else
188 errmsg = _("Biiiig Trouble in parse_imm16!");
189 break;
190
191 case (CGEN_PARSE_OPERAND_RESULT_QUEUED):
192 /* No special processing for this case. */
193 break;
194
195 default:
196 errmsg = _("%operator operand is not a symbol");
197 break;
198 }
199 }
200 *valuep = value;
201 }
202 else
203 {
204 /* Parse hex values like 0xffff as unsigned, and sign extend
205 them manually. */
206 int parse_signed = (opindex == (CGEN_OPERAND_TYPE)MS1_OPERAND_IMM16);
207
208 if ((*strp)[0] == '0'
209 && ((*strp)[1] == 'x' || (*strp)[1] == 'X'))
210 parse_signed = 0;
211
212 /* No relocating operator. Parse as an number. */
213 if (parse_signed)
214 {
215 /* Parse as as signed integer. */
216
217 errmsg = cgen_parse_signed_integer (cd, strp, opindex, valuep);
218
219 if (errmsg == NULL)
220 {
221#if 0
222 /* Manual range checking is needed for the signed case. */
223 if (*valuep & 0x8000)
224 value = 0xffff0000 | *valuep;
225 else
226 value = *valuep;
227
228 if (signed_out_of_bounds (value))
229 errmsg = _("Operand out of range. Must be between -32768 and 32767.");
230 /* Truncate to 16 bits. This is necessary
231 because cgen will have sign extended *valuep. */
232 *valuep &= 0xFFFF;
233#endif
234 }
235 }
236 else
237 {
238 /* MS1_OPERAND_IMM16Z. Parse as an unsigned integer. */
3ec2b351 239 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, (unsigned long *) valuep);
b081650b 240
3ec2b351 241 if (opindex == (CGEN_OPERAND_TYPE) MS1_OPERAND_IMM16
b081650b
DB
242 && *valuep >= 0x8000
243 && *valuep <= 0xffff)
244 *valuep -= 0x10000;
245 }
246 }
247
248 return errmsg;
249}
250
251
252static const char *
253parse_dup (CGEN_CPU_DESC cd,
254 const char **strp,
255 int opindex,
3ec2b351 256 unsigned long *valuep)
b081650b
DB
257{
258 const char *errmsg = NULL;
259
260 if (strncmp (*strp, "dup", 3) == 0 || strncmp (*strp, "DUP", 3) == 0)
261 {
262 *strp += 3;
263 *valuep = 1;
264 }
265 else if (strncmp (*strp, "xx", 2) == 0 || strncmp (*strp, "XX", 2) == 0)
266 {
267 *strp += 2;
268 *valuep = 0;
269 }
270 else
271 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
272
273 return errmsg;
274}
275
276
277static const char *
278parse_ball (CGEN_CPU_DESC cd,
279 const char **strp,
280 int opindex,
3ec2b351 281 unsigned long *valuep)
b081650b
DB
282{
283 const char *errmsg = NULL;
284
285 if (strncmp (*strp, "all", 3) == 0 || strncmp (*strp, "ALL", 3) == 0)
286 {
287 *strp += 3;
288 *valuep = 1;
289 }
290 else if (strncmp (*strp, "one", 3) == 0 || strncmp (*strp, "ONE", 3) == 0)
291 {
292 *strp += 3;
293 *valuep = 0;
294 }
295 else
296 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
297
298 return errmsg;
299}
300
301static const char *
302parse_xmode (CGEN_CPU_DESC cd,
303 const char **strp,
304 int opindex,
3ec2b351 305 unsigned long *valuep)
b081650b
DB
306{
307 const char *errmsg = NULL;
308
309 if (strncmp (*strp, "pm", 2) == 0 || strncmp (*strp, "PM", 2) == 0)
310 {
311 *strp += 2;
312 *valuep = 1;
313 }
314 else if (strncmp (*strp, "xm", 2) == 0 || strncmp (*strp, "XM", 2) == 0)
315 {
316 *strp += 2;
317 *valuep = 0;
318 }
319 else
320 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
321
322 return errmsg;
323}
324
325static const char *
326parse_rc (CGEN_CPU_DESC cd,
327 const char **strp,
328 int opindex,
3ec2b351 329 unsigned long *valuep)
b081650b
DB
330{
331 const char *errmsg = NULL;
332
333 if (strncmp (*strp, "r", 1) == 0 || strncmp (*strp, "R", 1) == 0)
334 {
335 *strp += 1;
336 *valuep = 1;
337 }
338 else if (strncmp (*strp, "c", 1) == 0 || strncmp (*strp, "C", 1) == 0)
339 {
340 *strp += 1;
341 *valuep = 0;
342 }
343 else
344 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
345
346 return errmsg;
347}
348
349static const char *
350parse_cbrb (CGEN_CPU_DESC cd,
351 const char **strp,
352 int opindex,
3ec2b351 353 unsigned long *valuep)
b081650b
DB
354{
355 const char *errmsg = NULL;
356
357 if (strncmp (*strp, "rb", 2) == 0 || strncmp (*strp, "RB", 2) == 0)
358 {
359 *strp += 2;
360 *valuep = 1;
361 }
362 else if (strncmp (*strp, "cb", 2) == 0 || strncmp (*strp, "CB", 2) == 0)
363 {
364 *strp += 2;
365 *valuep = 0;
366 }
367 else
368 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
369
370 return errmsg;
371}
372
373static const char *
374parse_rbbc (CGEN_CPU_DESC cd,
375 const char **strp,
376 int opindex,
3ec2b351 377 unsigned long *valuep)
b081650b
DB
378{
379 const char *errmsg = NULL;
380
381 if (strncmp (*strp, "rt", 2) == 0 || strncmp (*strp, "RT", 2) == 0)
382 {
383 *strp += 2;
384 *valuep = 0;
385 }
386 else if (strncmp (*strp, "br1", 3) == 0 || strncmp (*strp, "BR1", 3) == 0)
387 {
388 *strp += 3;
389 *valuep = 1;
390 }
391 else if (strncmp (*strp, "br2", 3) == 0 || strncmp (*strp, "BR2", 3) == 0)
392 {
393 *strp += 3;
394 *valuep = 2;
395 }
396 else if (strncmp (*strp, "cs", 2) == 0 || strncmp (*strp, "CS", 2) == 0)
397 {
398 *strp += 2;
399 *valuep = 3;
400 }
401 else
402 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
403
404 return errmsg;
405}
406
407static const char *
408parse_type (CGEN_CPU_DESC cd,
409 const char **strp,
410 int opindex,
3ec2b351 411 unsigned long *valuep)
b081650b
DB
412{
413 const char *errmsg = NULL;
414
415 if (strncmp (*strp, "odd", 3) == 0 || strncmp (*strp, "ODD", 3) == 0)
416 {
417 *strp += 3;
418 *valuep = 0;
419 }
420 else if (strncmp (*strp, "even", 4) == 0 || strncmp (*strp, "EVEN", 4) == 0)
421 {
422 *strp += 4;
423 *valuep = 1;
424 }
425 else if (strncmp (*strp, "oe", 2) == 0 || strncmp (*strp, "OE", 2) == 0)
426 {
427 *strp += 2;
428 *valuep = 2;
429 }
430 else
431 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, valuep);
432
433 if ((errmsg == NULL) && (*valuep == 3))
434 errmsg = _("invalid operand. type may have values 0,1,2 only.");
435
436 return errmsg;
437}
438
439/* -- dis.c */
440static void print_dollarhex (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
6f84a2a6 441static void print_pcrel (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
b081650b
DB
442
443static void
444print_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
445 void * dis_info,
446 long value,
447 unsigned int attrs ATTRIBUTE_UNUSED,
448 bfd_vma pc ATTRIBUTE_UNUSED,
449 int length ATTRIBUTE_UNUSED)
450{
451 disassemble_info *info = (disassemble_info *) dis_info;
452
0e6b69be 453 info->fprintf_func (info->stream, "$%lx", value);
b081650b
DB
454
455 if (0)
456 print_normal (cd, dis_info, value, attrs, pc, length);
457}
458
6f84a2a6
NS
459static void
460print_pcrel (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
461 void * dis_info,
462 long value,
463 unsigned int attrs ATTRIBUTE_UNUSED,
464 bfd_vma pc ATTRIBUTE_UNUSED,
465 int length ATTRIBUTE_UNUSED)
466{
467 print_address (cd, dis_info, value + pc, attrs, pc, length);
468}
b081650b
DB
469
470/* -- */
471
472
473
474
475
This page took 0.052419 seconds and 4 git commands to generate.