* Makefile.am (libopcodes_la_LDFLAGS): Define.
[deliverable/binutils-gdb.git] / opcodes / cgen-opc.in
CommitLineData
ab0bd049
DE
1/* Generic opcode table support for targets using CGEN. -*- C -*-
2 CGEN: Cpu tools GENerator
3
4This file is used to generate @arch@-opc.c.
5
6Copyright (C) 1998 Free Software Foundation, Inc.
7
8This file is part of the GNU Binutils and GDB, the GNU debugger.
9
10This program is free software; you can redistribute it and/or modify
11it under the terms of the GNU General Public License as published by
12the Free Software Foundation; either version 2, or (at your option)
13any later version.
14
15This program is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23
24#include "sysdep.h"
25#include <stdio.h>
26#include "ansidecl.h"
27#include "libiberty.h"
28#include "bfd.h"
29#include "symcat.h"
30#include "@arch@-opc.h"
31
32/* Look up instruction INSN_VALUE and extract its fields.
33 If non-null INSN is the insn table entry.
34 Otherwise INSN_VALUE is examined to compute it.
35 LENGTH is the bit length of INSN_VALUE if known, otherwise 0.
390bd87d 36 ALIAS_P is non-zero if alias insns are to be included in the search.
ab0bd049
DE
37 The result a pointer to the insn table entry, or NULL if the instruction
38 wasn't recognized. */
39
40const CGEN_INSN *
390bd87d 41@arch@_cgen_lookup_insn (insn, insn_value, length, fields, alias_p)
ab0bd049
DE
42 const CGEN_INSN *insn;
43 cgen_insn_t insn_value;
44 int length;
45 CGEN_FIELDS *fields;
46{
390bd87d 47 char buf[16];
ab0bd049
DE
48
49 if (!insn)
50 {
51 const CGEN_INSN_LIST *insn_list;
52
53#ifdef CGEN_INT_INSN
54 switch (length)
55 {
56 case 8:
57 buf[0] = insn_value;
58 break;
59 case 16:
60 if (cgen_current_endian == CGEN_ENDIAN_BIG)
61 bfd_putb16 (insn_value, buf);
62 else
63 bfd_putl16 (insn_value, buf);
64 break;
65 case 32:
66 if (cgen_current_endian == CGEN_ENDIAN_BIG)
67 bfd_putb32 (insn_value, buf);
68 else
69 bfd_putl32 (insn_value, buf);
70 break;
71 default:
72 abort ();
73 }
74#else
75 abort (); /* FIXME: unfinished */
76#endif
77
78 /* The instructions are stored in hash lists.
79 Pick the first one and keep trying until we find the right one. */
80
81 insn_list = CGEN_DIS_LOOKUP_INSN (buf, insn_value);
82 while (insn_list != NULL)
83 {
84 insn = insn_list->insn;
85
390bd87d
DE
86 if (alias_p
87 || ! CGEN_INSN_ATTR (insn, CGEN_INSN_ALIAS))
ab0bd049 88 {
390bd87d
DE
89 /* Basic bit mask must be correct. */
90 /* ??? May wish to allow target to defer this check until the
91 extract handler. */
92 if ((insn_value & CGEN_INSN_MASK (insn)) == CGEN_INSN_VALUE (insn))
93 {
94 length = (*CGEN_EXTRACT_FN (insn)) (insn, NULL, insn_value, fields);
95 if (length > 0)
96 return insn;
97 }
ab0bd049
DE
98 }
99
100 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
101 }
102 }
103 else
104 {
390bd87d
DE
105 /* Sanity check: can't pass an alias insn if ! alias_p. */
106 if (! alias_p
107 && CGEN_INSN_ATTR (insn, CGEN_INSN_ALIAS))
108 abort ();
109
ab0bd049
DE
110 length = (*CGEN_EXTRACT_FN (insn)) (insn, NULL, insn_value, fields);
111 if (length > 0)
112 return insn;
113 }
114
115 return NULL;
116}
117
118/* Fill in the operand instances used by insn INSN_VALUE.
119 If non-null INS is the insn table entry.
120 Otherwise INSN_VALUE is examined to compute it.
121 LENGTH is the number of bits in INSN_VALUE if known, otherwise 0.
122 INDICES is a pointer to a buffer of MAX_OPERANDS ints to be filled in.
123 The result a pointer to the insn table entry, or NULL if the instruction
124 wasn't recognized. */
125
126const CGEN_INSN *
127@arch@_cgen_get_insn_operands (insn, insn_value, length, indices)
128 const CGEN_INSN *insn;
129 cgen_insn_t insn_value;
130 int length;
131 int *indices;
132{
133 CGEN_FIELDS fields;
134 const CGEN_OPERAND_INSTANCE *opinst;
135 int i;
136
390bd87d
DE
137 /* FIXME: ALIAS insns are in transition from being record in the insn table
138 to being recorded separately as macros. They don't have semantic code
139 so they can't be used here. Thus we currently always ignore the INSN
140 argument. */
141 insn = @arch@_cgen_lookup_insn (NULL, insn_value, length, &fields, 0);
ab0bd049
DE
142 if (! insn)
143 return NULL;
144
145 for (i = 0, opinst = CGEN_INSN_OPERANDS (insn);
146 CGEN_OPERAND_INSTANCE_TYPE (opinst) != CGEN_OPERAND_INSTANCE_END;
147 ++i, ++opinst)
148 {
149 const CGEN_OPERAND *op = CGEN_OPERAND_INSTANCE_OPERAND (opinst);
150 if (op == NULL)
151 indices[i] = CGEN_OPERAND_INSTANCE_INDEX (opinst);
152 else
153 indices[i] = @arch@_cgen_get_operand (CGEN_OPERAND_INDEX (op), &fields);
154 }
155
156 return insn;
157}
This page took 0.03222 seconds and 4 git commands to generate.