File: sparc.opc

package info (click to toggle)
gnat-gdb 5.3.gnat.0.0.20030225-8
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 75,144 kB
  • ctags: 101,348
  • sloc: ansic: 873,511; exp: 46,950; sh: 16,123; makefile: 11,757; yacc: 6,092; asm: 5,027; cpp: 4,044; perl: 2,624; lex: 877; sed: 550; lisp: 394; awk: 170; pascal: 57; java: 7; fortran: 5
file content (180 lines) | stat: -rw-r--r-- 4,400 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/* SPARC opcode support.  -*- C -*-
   Copyright (C) 2000 Red Hat, Inc.
   This file is part of CGEN.
   This file is copyrighted with the GNU General Public License.
   See file COPYING for details.  */

/* This file is an addendum to sparc.cpu.  Heavy use of C code isn't
   appropriate in .cpu files, so it resides here.  This especially applies
   to assembly/disassembly where parsing/printing can be quite involved.
   Such things aren't really part of the specification of the cpu, per se,
   so .cpu files provide the general framework and .opc files handle the
   nitty-gritty details as necessary.

   Each section is delimited with start and end markers.

   <cpu>-opc.h additions use: "-- opc.h"
   <cpu>-opc.c additions use: "-- opc.c"
   <cpu>-asm.c additions use: "-- asm.c"
   <cpu>-dis.c additions use: "-- dis.c"
*/

/* -- opc.h */

#undef CGEN_DIS_HASH_SIZE
#define CGEN_DIS_HASH_SIZE 256
#undef CGEN_DIS_HASH
extern const unsigned int sparc_cgen_opcode_bits[];
#define CGEN_DIS_HASH(buffer, insn) \
((((insn) >> 24) & 0xc0) \
 | (((insn) & sparc_cgen_opcode_bits[((insn) >> 30) & 3]) >> 19))

/* -- */

/* -- asm.c */

/* It is important that we only look at insn code bits as that is how the
   opcode table is hashed.  OPCODE_BITS is a table of valid bits for each
   of the main types (0,1,2,3).  */
const unsigned int sparc_cgen_opcode_bits[4] = {
  0x01c00000, 0x0, 0x01f80000, 0x01f80000
};

/* Handle %lo().  */

static const char *
parse_lo10 (cd, strp, opindex, valuep)
     CGEN_CPU_DESC cd;
     const char **strp;
     int opindex;
     long *valuep;
{
  const char *errmsg;
  enum cgen_parse_operand_result result_type;
  bfd_vma value;

  if (strncasecmp (*strp, "%lo(", 4) == 0)
    {
      *strp += 4;
      errmsg = cgen_parse_address (od, strp, opindex, BFD_RELOC_LO10,
				   &result_type, &value);
      if (**strp != ')')
	return "missing `)'";
      ++*strp;
      value &= 0x3ff;
      *valuep = value;
      return errmsg;
    }

  return cgen_parse_unsigned_integer (od, strp, opindex, valuep);
}

static const char *
parse_lo13 (cd, strp, opindex, valuep)
     CGEN_CPU_DESC cd;
     const char **strp;
     int opindex;
     long *valuep;
{
  const char *errmsg;
  enum cgen_parse_operand_result result_type;
  bfd_vma value;

  if (strncasecmp (*strp, "%lo(", 4) == 0)
    {
      *strp += 4;
      errmsg = cgen_parse_address (od, strp, opindex, BFD_RELOC_LO10,
				   &result_type, &value);
      if (**strp != ')')
	return "missing `)'";
      ++*strp;
      value &= 0x3ff;
      *valuep = value;
      return errmsg;
    }

  return cgen_parse_unsigned_integer (od, strp, opindex, valuep);
}

/* Handle %hi().  */

static const char *
parse_hi22 (cd, strp, opindex, valuep)
     CGEN_CPU_DESC cd;
     const char **strp;
     int opindex;
     unsigned long *valuep;
{
  const char *errmsg;
  enum cgen_parse_operand_result result_type;
  bfd_vma value;

  if (strncasecmp (*strp, "%hi(", 4) == 0)
    {
      *strp += 4;
      errmsg = cgen_parse_address (od, strp, opindex, BFD_RELOC_HI22,
				   &result_type, &value);
      if (**strp != ')')
	return "missing `)'";
      ++*strp;
      if (result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
	value >>= 10;
      *valuep = value;
      return errmsg;
    }

  return cgen_parse_unsigned_integer (od, strp, opindex, valuep);
}

/* -- */

/* -- dis.c */

/* Include "%hi(foo)" in sethi output.  */

static void
print_hi22 (cd, dis_info, value, attrs, pc, length)
     CGEN_CPU_DESC cd;
     PTR dis_info;
     long value;
     unsigned int attrs;
     bfd_vma pc;
     int length;
{
  disassemble_info *info = (disassemble_info *) dis_info;
  (*info->fprintf_func) (info->stream, "%%hi(0x%lx)", value << 10);
}

#undef CGEN_PRINT_INSN
#define CGEN_PRINT_INSN my_print_insn

static int
my_print_insn (cd, pc, info)
     CGEN_CPU_DESC cd;
     bfd_vma pc;
     disassemble_info *info;
{
  char buffer[CGEN_MAX_INSN_SIZE];
  char *buf = buffer;
  int status;
  unsigned long insn_value;
  int len;

  /* Read the base part of the insn.  */

  status = (*info->read_memory_func) (pc, buf, 4, info);
  if (status != 0)
    {
      (*info->memory_error_func) (status, pc, info);
      return -1;
    }

  len = print_insn (od, pc, info, buf, 4);
  if (len != 0)
    return len;

  /* CGEN doesn't handle this insn yet.  Fall back on old way.  */
  return old_print_insn_sparc (pc, info);
}

/* -- */