OSDN Git Service

From 2001-03-01 Tom Rix <trix@redhat.com>:
[pf3gnuchains/pf3gnuchains3x.git] / cgen / sparc.opc
1 /* SPARC opcode support.  -*- C -*-
2    Copyright (C) 2000 Red Hat, Inc.
3    This file is part of CGEN.
4    This file is copyrighted with the GNU General Public License.
5    See file COPYING for details.  */
6
7 /* This file is an addendum to sparc.cpu.  Heavy use of C code isn't
8    appropriate in .cpu files, so it resides here.  This especially applies
9    to assembly/disassembly where parsing/printing can be quite involved.
10    Such things aren't really part of the specification of the cpu, per se,
11    so .cpu files provide the general framework and .opc files handle the
12    nitty-gritty details as necessary.
13
14    Each section is delimited with start and end markers.
15
16    <cpu>-opc.h additions use: "-- opc.h"
17    <cpu>-opc.c additions use: "-- opc.c"
18    <cpu>-asm.c additions use: "-- asm.c"
19    <cpu>-dis.c additions use: "-- dis.c"
20 */
21 \f
22 /* -- opc.h */
23
24 #undef CGEN_DIS_HASH_SIZE
25 #define CGEN_DIS_HASH_SIZE 256
26 #undef CGEN_DIS_HASH
27 extern const unsigned int sparc_cgen_opcode_bits[];
28 #define CGEN_DIS_HASH(buffer, insn) \
29 ((((insn) >> 24) & 0xc0) \
30  | (((insn) & sparc_cgen_opcode_bits[((insn) >> 30) & 3]) >> 19))
31
32 /* -- */
33 \f
34 /* -- asm.c */
35
36 /* It is important that we only look at insn code bits as that is how the
37    opcode table is hashed.  OPCODE_BITS is a table of valid bits for each
38    of the main types (0,1,2,3).  */
39 const unsigned int sparc_cgen_opcode_bits[4] = {
40   0x01c00000, 0x0, 0x01f80000, 0x01f80000
41 };
42
43 /* Handle %lo().  */
44
45 static const char *
46 parse_lo10 (cd, strp, opindex, valuep)
47      CGEN_CPU_DESC cd;
48      const char **strp;
49      int opindex;
50      long *valuep;
51 {
52   const char *errmsg;
53   enum cgen_parse_operand_result result_type;
54   bfd_vma value;
55
56   if (strncasecmp (*strp, "%lo(", 4) == 0)
57     {
58       *strp += 4;
59       errmsg = cgen_parse_address (od, strp, opindex, BFD_RELOC_LO10,
60                                    &result_type, &value);
61       if (**strp != ')')
62         return "missing `)'";
63       ++*strp;
64       value &= 0x3ff;
65       *valuep = value;
66       return errmsg;
67     }
68
69   return cgen_parse_unsigned_integer (od, strp, opindex, valuep);
70 }
71
72 static const char *
73 parse_lo13 (cd, strp, opindex, valuep)
74      CGEN_CPU_DESC cd;
75      const char **strp;
76      int opindex;
77      long *valuep;
78 {
79   const char *errmsg;
80   enum cgen_parse_operand_result result_type;
81   bfd_vma value;
82
83   if (strncasecmp (*strp, "%lo(", 4) == 0)
84     {
85       *strp += 4;
86       errmsg = cgen_parse_address (od, strp, opindex, BFD_RELOC_LO10,
87                                    &result_type, &value);
88       if (**strp != ')')
89         return "missing `)'";
90       ++*strp;
91       value &= 0x3ff;
92       *valuep = value;
93       return errmsg;
94     }
95
96   return cgen_parse_unsigned_integer (od, strp, opindex, valuep);
97 }
98
99 /* Handle %hi().  */
100
101 static const char *
102 parse_hi22 (cd, strp, opindex, valuep)
103      CGEN_CPU_DESC cd;
104      const char **strp;
105      int opindex;
106      unsigned long *valuep;
107 {
108   const char *errmsg;
109   enum cgen_parse_operand_result result_type;
110   bfd_vma value;
111
112   if (strncasecmp (*strp, "%hi(", 4) == 0)
113     {
114       *strp += 4;
115       errmsg = cgen_parse_address (od, strp, opindex, BFD_RELOC_HI22,
116                                    &result_type, &value);
117       if (**strp != ')')
118         return "missing `)'";
119       ++*strp;
120       if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
121         value >>= 10;
122       *valuep = value;
123       return errmsg;
124     }
125
126   return cgen_parse_unsigned_integer (od, strp, opindex, valuep);
127 }
128
129 /* -- */
130 \f
131 /* -- dis.c */
132
133 /* Include "%hi(foo)" in sethi output.  */
134
135 static void
136 print_hi22 (cd, dis_info, value, attrs, pc, length)
137      CGEN_CPU_DESC cd;
138      PTR dis_info;
139      long value;
140      unsigned int attrs;
141      bfd_vma pc;
142      int length;
143 {
144   disassemble_info *info = (disassemble_info *) dis_info;
145   (*info->fprintf_func) (info->stream, "%%hi(0x%lx)", value << 10);
146 }
147
148 #undef CGEN_PRINT_INSN
149 #define CGEN_PRINT_INSN my_print_insn
150
151 static int
152 my_print_insn (cd, pc, info)
153      CGEN_CPU_DESC cd;
154      bfd_vma pc;
155      disassemble_info *info;
156 {
157   char buffer[CGEN_MAX_INSN_SIZE];
158   char *buf = buffer;
159   int status;
160   unsigned long insn_value;
161   int len;
162
163   /* Read the base part of the insn.  */
164
165   status = (*info->read_memory_func) (pc, buf, 4, info);
166   if (status != 0)
167     {
168       (*info->memory_error_func) (status, pc, info);
169       return -1;
170     }
171
172   len = print_insn (od, pc, info, buf, 4);
173   if (len != 0)
174     return len;
175
176   /* CGEN doesn't handle this insn yet.  Fall back on old way.  */
177   return old_print_insn_sparc (pc, info);
178 }
179
180 /* -- */