~vcs-imports/qemu/git

7417 by Edgar E. Iglesias
microblaze: Add disassembler.
1
/* Disassemble Xilinx microblaze instructions.
2
   Copyright (C) 1993, 1999, 2000 Free Software Foundation, Inc.
3
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; either version 2 of the License, or
7
(at your option) any later version.
8
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
GNU General Public License for more details.
13
14
You should have received a copy of the GNU General Public License
7863 by Blue Swirl
Update to a hopefully more future proof FSF address
15
along with this program; if not, see <http://www.gnu.org/licenses/>.  */
7417 by Edgar E. Iglesias
microblaze: Add disassembler.
16
17
/*
18
 * Copyright (c) 2001 Xilinx, Inc.  All rights reserved. 
19
 *
20
 * Redistribution and use in source and binary forms are permitted
21
 * provided that the above copyright notice and this paragraph are
22
 * duplicated in all such forms and that any documentation,
23
 * advertising materials, and other materials related to such
24
 * distribution and use acknowledge that the software was developed
25
 * by Xilinx, Inc.  The name of the Company may not be used to endorse 
26
 * or promote products derived from this software without specific prior 
27
 * written permission.
28
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
29
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
30
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
31
 *
32
 *	Xilinx, Inc.
33
 */
34
35
36
#include <stdio.h>
37
#define STATIC_TABLE
38
#define DEFINE_TABLE
39
40
#ifndef MICROBLAZE_OPC
41
#define MICROBLAZE_OPC
42
/* Assembler instructions for Xilinx's microblaze processor
43
   Copyright (C) 1999, 2000 Free Software Foundation, Inc.
44
45
   
46
This program is free software; you can redistribute it and/or modify
47
it under the terms of the GNU General Public License as published by
48
the Free Software Foundation; either version 2 of the License, or
49
(at your option) any later version.
50
51
This program is distributed in the hope that it will be useful,
52
but WITHOUT ANY WARRANTY; without even the implied warranty of
53
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
54
GNU General Public License for more details.
55
56
You should have received a copy of the GNU General Public License
7863 by Blue Swirl
Update to a hopefully more future proof FSF address
57
along with this program; if not, see <http://www.gnu.org/licenses/>.  */
7417 by Edgar E. Iglesias
microblaze: Add disassembler.
58
59
/*
60
 * Copyright (c) 2001 Xilinx, Inc.  All rights reserved. 
61
 *
62
 * Redistribution and use in source and binary forms are permitted
63
 * provided that the above copyright notice and this paragraph are
64
 * duplicated in all such forms and that any documentation,
65
 * advertising materials, and other materials related to such
66
 * distribution and use acknowledge that the software was developed
67
 * by Xilinx, Inc.  The name of the Company may not be used to endorse 
68
 * or promote products derived from this software without specific prior 
69
 * written permission.
70
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
71
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
72
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
73
 *
74
 *	Xilinx, Inc.
75
 */
76
77
78
#ifndef MICROBLAZE_OPCM
79
#define MICROBLAZE_OPCM
80
81
/*
82
 * Copyright (c) 2001 Xilinx, Inc.  All rights reserved. 
83
 *
84
 * Redistribution and use in source and binary forms are permitted
85
 * provided that the above copyright notice and this paragraph are
86
 * duplicated in all such forms and that any documentation,
87
 * advertising materials, and other materials related to such
88
 * distribution and use acknowledge that the software was developed
89
 * by Xilinx, Inc.  The name of the Company may not be used to endorse 
90
 * or promote products derived from this software without specific prior 
91
 * written permission.
92
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
93
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
94
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
95
 *
96
 *	Xilinx, Inc.
97
 * $Header:
98
 */
99
100
enum microblaze_instr {
101
   add, rsub, addc, rsubc, addk, rsubk, addkc, rsubkc, cmp, cmpu,
102
   addi, rsubi, addic, rsubic, addik, rsubik, addikc, rsubikc, mul,
103
   idiv, idivu, bsll, bsra, bsrl, get, put, nget, nput, cget, cput,
104
   ncget, ncput, muli, bslli, bsrai, bsrli, mului, or, and, xor,
105
   andn, pcmpbf, pcmpbc, pcmpeq, pcmpne, sra, src, srl, sext8, sext16, wic, wdc, mts, mfs, br, brd,
106
   brld, bra, brad, brald, microblaze_brk, beq, beqd, bne, bned, blt,
107
   bltd, ble, bled, bgt, bgtd, bge, bged, ori, andi, xori, andni,
108
   imm, rtsd, rtid, rtbd, rted, bri, brid, brlid, brai, braid, bralid,
109
   brki, beqi, beqid, bnei, bneid, blti, bltid, blei, bleid, bgti,
110
   bgtid, bgei, bgeid, lbu, lhu, lw, sb, sh, sw, lbui, lhui, lwi,
111
   sbi, shi, swi, msrset, msrclr, tuqula, fadd, frsub, fmul, fdiv, 
112
   fcmp_lt, fcmp_eq, fcmp_le, fcmp_gt, fcmp_ne, fcmp_ge, fcmp_un, invalid_inst } ;
113
114
enum microblaze_instr_type {
115
   arithmetic_inst, logical_inst, mult_inst, div_inst, branch_inst,
116
   return_inst, immediate_inst, special_inst, memory_load_inst,
117
   memory_store_inst, barrel_shift_inst, anyware_inst };
118
119
#define INST_WORD_SIZE 4
120
121
/* gen purpose regs go from 0 to 31 */
122
/* mask is reg num - max_reg_num, ie reg_num - 32 in this case */
123
124
#define REG_PC_MASK 0x8000
125
#define REG_MSR_MASK 0x8001
126
#define REG_EAR_MASK 0x8003
127
#define REG_ESR_MASK 0x8005
128
#define REG_FSR_MASK 0x8007
129
130
#define MIN_REGNUM 0
131
#define MAX_REGNUM 31
132
133
#define REG_PC  32 /* PC */
134
#define REG_MSR 33 /* machine status reg */
135
#define REG_EAR 35 /* Exception reg */
136
#define REG_ESR 37 /* Exception reg */
137
#define REG_FSR 39 /* FPU Status reg */
138
139
/* alternate names for gen purpose regs */
140
#define REG_SP  1 /* stack pointer */
141
#define REG_ROSDP 2 /* read-only small data pointer */
142
#define REG_RWSDP 13 /* read-write small data pointer */
143
144
/* Assembler Register - Used in Delay Slot Optimization */
145
#define REG_AS    18
146
#define REG_ZERO  0
147
 
148
#define RD_LOW  21 /* low bit for RD */
149
#define RA_LOW  16 /* low bit for RA */
150
#define RB_LOW  11 /* low bit for RB */
151
#define IMM_LOW  0 /* low bit for immediate */
152
153
#define RD_MASK 0x03E00000
154
#define RA_MASK 0x001F0000
155
#define RB_MASK 0x0000F800
156
#define IMM_MASK 0x0000FFFF
157
158
// imm mask for barrel shifts
159
#define IMM5_MASK 0x0000001F
160
161
162
// imm mask for get, put instructions
163
#define  IMM12_MASK 0x00000FFF
164
165
// imm mask for msrset, msrclr instructions
166
#define  IMM14_MASK 0x00003FFF
167
168
#endif /* MICROBLAZE-OPCM */
169
170
#define INST_TYPE_RD_R1_R2 0
171
#define INST_TYPE_RD_R1_IMM 1
172
#define INST_TYPE_RD_R1_UNSIGNED_IMM 2
173
#define INST_TYPE_RD_R1 3
174
#define INST_TYPE_RD_R2 4
175
#define INST_TYPE_RD_IMM 5
176
#define INST_TYPE_R2 6
177
#define INST_TYPE_R1_R2 7
178
#define INST_TYPE_R1_IMM 8
179
#define INST_TYPE_IMM 9
180
#define INST_TYPE_SPECIAL_R1 10
181
#define INST_TYPE_RD_SPECIAL 11
182
#define INST_TYPE_R1 12
183
  // new instn type for barrel shift imms
184
#define INST_TYPE_RD_R1_IMM5  13
185
#define INST_TYPE_RD_IMM12    14
186
#define INST_TYPE_R1_IMM12    15
187
188
  // new insn type for insn cache
189
#define INST_TYPE_RD_R1_SPECIAL 16
190
191
// new insn type for msrclr, msrset insns.
192
#define INST_TYPE_RD_IMM14    17
193
194
// new insn type for tuqula rd - addik rd, r0, 42
195
#define INST_TYPE_RD    18
196
197
#define INST_TYPE_NONE 25
198
199
200
201
#define INST_PC_OFFSET 1 /* instructions where the label address is resolved as a PC offset (for branch label)*/
202
#define INST_NO_OFFSET 0 /* instructions where the label address is resolved as an absolute value (for data mem or abs address)*/
203
204
#define IMMVAL_MASK_NON_SPECIAL 0x0000
205
#define IMMVAL_MASK_MTS 0x4000
206
#define IMMVAL_MASK_MFS 0x0000
207
208
#define OPCODE_MASK_H   0xFC000000 /* High 6 bits only */
209
#define OPCODE_MASK_H1  0xFFE00000 /* High 11 bits */
210
#define OPCODE_MASK_H2  0xFC1F0000 /* High 6 and bits 20-16 */
211
#define OPCODE_MASK_H12 0xFFFF0000 /* High 16 */
212
#define OPCODE_MASK_H4  0xFC0007FF /* High 6 and low 11 bits */
213
#define OPCODE_MASK_H13S 0xFFE0FFF0 /* High 11 and 15:1 bits and last nibble of last byte for spr */
214
#define OPCODE_MASK_H23S 0xFC1FFFF0 /* High 6, 20-16 and 15:1 bits and last nibble of last byte for spr */
215
#define OPCODE_MASK_H34 0xFC00FFFF /* High 6 and low 16 bits */
216
#define OPCODE_MASK_H14 0xFFE007FF /* High 11 and low 11 bits */
217
#define OPCODE_MASK_H24 0xFC1F07FF /* High 6, bits 20-16 and low 11 bits */
218
#define OPCODE_MASK_H124  0xFFFF07FF /* High 16, and low 11 bits */
219
#define OPCODE_MASK_H1234 0xFFFFFFFF /* All 32 bits */
220
#define OPCODE_MASK_H3  0xFC000600 /* High 6 bits and bits 21, 22 */  
221
#define OPCODE_MASK_H32 0xFC00F000 /* High 6 bits and bit 16, 17, 18 and 19*/
222
#define OPCODE_MASK_H34B   0xFC0000FF /* High 6 bits and low 8 bits */
223
224
// New Mask for msrset, msrclr insns.
225
#define OPCODE_MASK_H23N  0xFC1FC000 /* High 6 and bits 12 - 18 */
226
227
#define DELAY_SLOT 1
228
#define NO_DELAY_SLOT 0
229
230
#define MAX_OPCODES 149
231
232
struct op_code_struct {
233
  const char *name;
234
  short inst_type; /* registers and immediate values involved */
235
  short inst_offset_type; /* immediate vals offset from PC? (= 1 for branches) */
236
  short delay_slots; /* info about delay slots needed after this instr. */
237
  short immval_mask;
238
  unsigned long bit_sequence; /* all the fixed bits for the op are set and all the variable bits (reg names, imm vals) are set to 0 */ 
239
  unsigned long opcode_mask; /* which bits define the opcode */
240
  enum microblaze_instr instr;
241
  enum microblaze_instr_type instr_type;
242
  /* more info about output format here */
243
} opcodes[MAX_OPCODES] = 
244
245
{ 
246
  {"add",   INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x00000000, OPCODE_MASK_H4, add, arithmetic_inst },
247
  {"rsub",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x04000000, OPCODE_MASK_H4, rsub, arithmetic_inst },
248
  {"addc",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x08000000, OPCODE_MASK_H4, addc, arithmetic_inst },
249
  {"rsubc", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x0C000000, OPCODE_MASK_H4, rsubc, arithmetic_inst },
250
  {"addk",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x10000000, OPCODE_MASK_H4, addk, arithmetic_inst },
251
  {"rsubk", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x14000000, OPCODE_MASK_H4, rsubk, arithmetic_inst },
252
  {"cmp",   INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x14000001, OPCODE_MASK_H4, cmp, arithmetic_inst },
253
  {"cmpu",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x14000003, OPCODE_MASK_H4, cmpu, arithmetic_inst },
254
  {"addkc", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x18000000, OPCODE_MASK_H4, addkc, arithmetic_inst },
255
  {"rsubkc",INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x1C000000, OPCODE_MASK_H4, rsubkc, arithmetic_inst },
256
  {"addi",  INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x20000000, OPCODE_MASK_H, addi, arithmetic_inst },
257
  {"rsubi", INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x24000000, OPCODE_MASK_H, rsubi, arithmetic_inst },
258
  {"addic", INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x28000000, OPCODE_MASK_H, addic, arithmetic_inst },
259
  {"rsubic",INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x2C000000, OPCODE_MASK_H, rsubic, arithmetic_inst },
260
  {"addik", INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x30000000, OPCODE_MASK_H, addik, arithmetic_inst },
261
  {"rsubik",INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x34000000, OPCODE_MASK_H, rsubik, arithmetic_inst },
262
  {"addikc",INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x38000000, OPCODE_MASK_H, addikc, arithmetic_inst },
263
  {"rsubikc",INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x3C000000, OPCODE_MASK_H, rsubikc, arithmetic_inst },
264
  {"mul",   INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x40000000, OPCODE_MASK_H4, mul, mult_inst },
265
  {"idiv",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x48000000, OPCODE_MASK_H4, idiv, div_inst },
266
  {"idivu", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x48000002, OPCODE_MASK_H4, idivu, div_inst },
267
  {"bsll",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x44000400, OPCODE_MASK_H3, bsll, barrel_shift_inst },
268
  {"bsra",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x44000200, OPCODE_MASK_H3, bsra, barrel_shift_inst },
269
  {"bsrl",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x44000000, OPCODE_MASK_H3, bsrl, barrel_shift_inst },
270
  {"get",   INST_TYPE_RD_IMM12, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6C000000, OPCODE_MASK_H32, get, anyware_inst },
271
  {"put",   INST_TYPE_R1_IMM12, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6C008000, OPCODE_MASK_H32, put, anyware_inst },
272
  {"nget",  INST_TYPE_RD_IMM12, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6C004000, OPCODE_MASK_H32, nget, anyware_inst },
273
  {"nput",  INST_TYPE_R1_IMM12, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6C00C000, OPCODE_MASK_H32, nput, anyware_inst },
274
  {"cget",  INST_TYPE_RD_IMM12, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6C002000, OPCODE_MASK_H32, cget, anyware_inst },
275
  {"cput",  INST_TYPE_R1_IMM12, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6C00A000, OPCODE_MASK_H32, cput, anyware_inst },
276
  {"ncget", INST_TYPE_RD_IMM12, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6C006000, OPCODE_MASK_H32, ncget, anyware_inst },
277
  {"ncput", INST_TYPE_R1_IMM12, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x6C00E000, OPCODE_MASK_H32, ncput, anyware_inst },
278
  {"muli",  INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x60000000, OPCODE_MASK_H, muli, mult_inst },
279
  {"bslli", INST_TYPE_RD_R1_IMM5, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64000400, OPCODE_MASK_H3, bslli, barrel_shift_inst },
280
  {"bsrai", INST_TYPE_RD_R1_IMM5, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64000200, OPCODE_MASK_H3, bsrai, barrel_shift_inst },
281
  {"bsrli", INST_TYPE_RD_R1_IMM5, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x64000000, OPCODE_MASK_H3, bsrli, barrel_shift_inst },
282
  {"or",    INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x80000000, OPCODE_MASK_H4, or, logical_inst },
283
  {"and",   INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x84000000, OPCODE_MASK_H4, and, logical_inst },
284
  {"xor",   INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x88000000, OPCODE_MASK_H4, xor, logical_inst },
285
  {"andn",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x8C000000, OPCODE_MASK_H4, andn, logical_inst },
286
  {"pcmpbf",INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x80000400, OPCODE_MASK_H4, pcmpbf, logical_inst },
287
  {"pcmpbc",INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x84000400, OPCODE_MASK_H4, pcmpbc, logical_inst },
288
  {"pcmpeq",INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x88000400, OPCODE_MASK_H4, pcmpeq, logical_inst },
289
  {"pcmpne",INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x8C000400, OPCODE_MASK_H4, pcmpne, logical_inst },
290
  {"sra",   INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000001, OPCODE_MASK_H34, sra, logical_inst },
291
  {"src",   INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000021, OPCODE_MASK_H34, src, logical_inst },
292
  {"srl",   INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000041, OPCODE_MASK_H34, srl, logical_inst },
293
  {"sext8", INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000060, OPCODE_MASK_H34, sext8, logical_inst },
294
  {"sext16",INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000061, OPCODE_MASK_H34, sext16, logical_inst },
295
  {"wic",   INST_TYPE_RD_R1_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000068, OPCODE_MASK_H34B, wic, special_inst },
296
  {"wdc",   INST_TYPE_RD_R1_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x90000064, OPCODE_MASK_H34B, wdc, special_inst },
297
  {"mts",   INST_TYPE_SPECIAL_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_MTS, 0x9400C000, OPCODE_MASK_H13S, mts, special_inst },
298
  {"mfs",   INST_TYPE_RD_SPECIAL, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_MFS, 0x94008000, OPCODE_MASK_H23S, mfs, special_inst },
299
  {"br",    INST_TYPE_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x98000000, OPCODE_MASK_H124, br, branch_inst },
300
  {"brd",   INST_TYPE_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x98100000, OPCODE_MASK_H124, brd, branch_inst },
301
  {"brld",  INST_TYPE_RD_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x98140000, OPCODE_MASK_H24, brld, branch_inst },
302
  {"bra",   INST_TYPE_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x98080000, OPCODE_MASK_H124, bra, branch_inst },
303
  {"brad",  INST_TYPE_R2, INST_NO_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x98180000, OPCODE_MASK_H124, brad, branch_inst },
304
  {"brald", INST_TYPE_RD_R2, INST_NO_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x981C0000, OPCODE_MASK_H24, brald, branch_inst },
305
  {"brk",   INST_TYPE_RD_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x980C0000, OPCODE_MASK_H24, microblaze_brk, branch_inst },
306
  {"beq",   INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9C000000, OPCODE_MASK_H14, beq, branch_inst },
307
  {"beqd",  INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9E000000, OPCODE_MASK_H14, beqd, branch_inst },
308
  {"bne",   INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9C200000, OPCODE_MASK_H14, bne, branch_inst },
309
  {"bned",  INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9E200000, OPCODE_MASK_H14, bned, branch_inst },
310
  {"blt",   INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9C400000, OPCODE_MASK_H14, blt, branch_inst },
311
  {"bltd",  INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9E400000, OPCODE_MASK_H14, bltd, branch_inst },
312
  {"ble",   INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9C600000, OPCODE_MASK_H14, ble, branch_inst },
313
  {"bled",  INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9E600000, OPCODE_MASK_H14, bled, branch_inst },
314
  {"bgt",   INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9C800000, OPCODE_MASK_H14, bgt, branch_inst },
315
  {"bgtd",  INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9E800000, OPCODE_MASK_H14, bgtd, branch_inst },
316
  {"bge",   INST_TYPE_R1_R2, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9CA00000, OPCODE_MASK_H14, bge, branch_inst },
317
  {"bged",  INST_TYPE_R1_R2, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x9EA00000, OPCODE_MASK_H14, bged, branch_inst },
318
  {"ori",   INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xA0000000, OPCODE_MASK_H, ori, logical_inst },
319
  {"andi",  INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xA4000000, OPCODE_MASK_H, andi, logical_inst },
320
  {"xori",  INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xA8000000, OPCODE_MASK_H, xori, logical_inst },
321
  {"andni", INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xAC000000, OPCODE_MASK_H, andni, logical_inst },
322
  {"imm",   INST_TYPE_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB0000000, OPCODE_MASK_H12, imm, immediate_inst },
323
  {"rtsd",  INST_TYPE_R1_IMM, INST_NO_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB6000000, OPCODE_MASK_H1, rtsd, return_inst },
324
  {"rtid",  INST_TYPE_R1_IMM, INST_NO_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB6200000, OPCODE_MASK_H1, rtid, return_inst },
325
  {"rtbd",  INST_TYPE_R1_IMM, INST_NO_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB6400000, OPCODE_MASK_H1, rtbd, return_inst },
326
  {"rted",  INST_TYPE_R1_IMM, INST_NO_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB6800000, OPCODE_MASK_H1, rted, return_inst },
327
  {"bri",   INST_TYPE_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB8000000, OPCODE_MASK_H12, bri, branch_inst },
328
  {"brid",  INST_TYPE_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB8100000, OPCODE_MASK_H12, brid, branch_inst },
329
  {"brlid", INST_TYPE_RD_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB8140000, OPCODE_MASK_H2, brlid, branch_inst },
330
  {"brai",  INST_TYPE_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB8080000, OPCODE_MASK_H12, brai, branch_inst },
331
  {"braid", INST_TYPE_IMM, INST_NO_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB8180000, OPCODE_MASK_H12, braid, branch_inst },
332
  {"bralid",INST_TYPE_RD_IMM, INST_NO_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB81C0000, OPCODE_MASK_H2, bralid, branch_inst },
333
  {"brki",  INST_TYPE_RD_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB80C0000, OPCODE_MASK_H2, brki, branch_inst },
334
  {"beqi",  INST_TYPE_R1_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBC000000, OPCODE_MASK_H1, beqi, branch_inst },
335
  {"beqid", INST_TYPE_R1_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBE000000, OPCODE_MASK_H1, beqid, branch_inst },
336
  {"bnei",  INST_TYPE_R1_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBC200000, OPCODE_MASK_H1, bnei, branch_inst },
337
  {"bneid", INST_TYPE_R1_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBE200000, OPCODE_MASK_H1, bneid, branch_inst },
338
  {"blti",  INST_TYPE_R1_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBC400000, OPCODE_MASK_H1, blti, branch_inst },
339
  {"bltid", INST_TYPE_R1_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBE400000, OPCODE_MASK_H1, bltid, branch_inst },
340
  {"blei",  INST_TYPE_R1_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBC600000, OPCODE_MASK_H1, blei, branch_inst },
341
  {"bleid", INST_TYPE_R1_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBE600000, OPCODE_MASK_H1, bleid, branch_inst },
342
  {"bgti",  INST_TYPE_R1_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBC800000, OPCODE_MASK_H1, bgti, branch_inst },
343
  {"bgtid", INST_TYPE_R1_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBE800000, OPCODE_MASK_H1, bgtid, branch_inst },
344
  {"bgei",  INST_TYPE_R1_IMM, INST_PC_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBCA00000, OPCODE_MASK_H1, bgei, branch_inst },
345
  {"bgeid", INST_TYPE_R1_IMM, INST_PC_OFFSET, DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xBEA00000, OPCODE_MASK_H1, bgeid, branch_inst },
346
  {"lbu",   INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xC0000000, OPCODE_MASK_H4, lbu, memory_load_inst },
347
  {"lhu",   INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xC4000000, OPCODE_MASK_H4, lhu, memory_load_inst },
348
  {"lw",    INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xC8000000, OPCODE_MASK_H4, lw, memory_load_inst },
349
  {"sb",    INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xD0000000, OPCODE_MASK_H4, sb, memory_store_inst },
350
  {"sh",    INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xD4000000, OPCODE_MASK_H4, sh, memory_store_inst },
351
  {"sw",    INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xD8000000, OPCODE_MASK_H4, sw, memory_store_inst },
352
  {"lbui",  INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xE0000000, OPCODE_MASK_H, lbui, memory_load_inst },
353
  {"lhui",  INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xE4000000, OPCODE_MASK_H, lhui, memory_load_inst },
354
  {"lwi",   INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xE8000000, OPCODE_MASK_H, lwi, memory_load_inst },
355
  {"sbi",   INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xF0000000, OPCODE_MASK_H, sbi, memory_store_inst },
356
  {"shi",   INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xF4000000, OPCODE_MASK_H, shi, memory_store_inst },
357
  {"swi",   INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xF8000000, OPCODE_MASK_H, swi, memory_store_inst },
358
  {"nop",   INST_TYPE_NONE, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x80000000, OPCODE_MASK_H1234, invalid_inst, logical_inst }, /* translates to or r0, r0, r0 */
359
  {"la",    INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x30000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* la translates to addik */
360
  {"tuqula",INST_TYPE_RD, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x3000002A, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* tuqula rd translates to addik rd, r0, 42 */
361
  {"not",   INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xA800FFFF, OPCODE_MASK_H34, invalid_inst, logical_inst }, /* not translates to xori rd,ra,-1 */
362
  {"neg",   INST_TYPE_RD_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x04000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* neg translates to rsub rd, ra, r0 */
363
  {"rtb",   INST_TYPE_R1, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xB6000004, OPCODE_MASK_H1, invalid_inst, return_inst }, /* rtb translates to rts rd, 4 */
364
  {"sub",   INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x04000000, OPCODE_MASK_H, invalid_inst, arithmetic_inst }, /* sub translates to rsub rd, rb, ra */
365
  {"lmi",   INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xE8000000, OPCODE_MASK_H, invalid_inst, memory_load_inst },
366
  {"smi",   INST_TYPE_RD_R1_IMM, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0xF8000000, OPCODE_MASK_H, invalid_inst, memory_store_inst },
367
  {"msrset",INST_TYPE_RD_IMM14, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x94100000, OPCODE_MASK_H23N, msrset, special_inst },
368
  {"msrclr",INST_TYPE_RD_IMM14, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x94110000, OPCODE_MASK_H23N, msrclr, special_inst },
369
  {"fadd",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000000, OPCODE_MASK_H4, fadd, arithmetic_inst },
370
  {"frsub",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000080, OPCODE_MASK_H4, frsub, arithmetic_inst },
371
  {"fmul",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000100, OPCODE_MASK_H4, fmul, arithmetic_inst },
372
  {"fdiv",  INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000180, OPCODE_MASK_H4, fdiv, arithmetic_inst },
373
  {"fcmp.lt", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000210, OPCODE_MASK_H4, fcmp_lt, arithmetic_inst },
374
  {"fcmp.eq", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000220, OPCODE_MASK_H4, fcmp_eq, arithmetic_inst },
375
  {"fcmp.le", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000230, OPCODE_MASK_H4, fcmp_le, arithmetic_inst },
376
  {"fcmp.gt", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000240, OPCODE_MASK_H4, fcmp_gt, arithmetic_inst },
377
  {"fcmp.ne", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000250, OPCODE_MASK_H4, fcmp_ne, arithmetic_inst },
378
  {"fcmp.ge", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000260, OPCODE_MASK_H4, fcmp_ge, arithmetic_inst },
379
  {"fcmp.un", INST_TYPE_RD_R1_R2, INST_NO_OFFSET, NO_DELAY_SLOT, IMMVAL_MASK_NON_SPECIAL, 0x58000200, OPCODE_MASK_H4, fcmp_un, arithmetic_inst },
380
  {""}
381
};
382
383
/* prefix for register names */
384
char register_prefix[] = "r";
385
char special_register_prefix[] = "spr";
386
char fsl_register_prefix[] = "rfsl";
387
388
389
/* #defines for valid immediate range */
390
#define MIN_IMM  0x80000000
391
#define MAX_IMM  0x7fffffff 
392
393
#define MIN_IMM12  0x000
394
#define MAX_IMM12  0x7ff
395
396
#define MIN_IMM14  0x0000
397
#define MAX_IMM14  0x1fff
398
399
#endif /* MICROBLAZE_OPC */
400
401
#include "dis-asm.h"
402
#include <strings.h>
403
404
#define get_field_rd(instr) get_field(instr, RD_MASK, RD_LOW)
405
#define get_field_r1(instr) get_field(instr, RA_MASK, RA_LOW)
406
#define get_field_r2(instr) get_field(instr, RB_MASK, RB_LOW)
407
#define get_int_field_imm(instr) ((instr & IMM_MASK) >> IMM_LOW)
408
#define get_int_field_r1(instr) ((instr & RA_MASK) >> RA_LOW)
409
410
static char *
411
get_field (long instr, long mask, unsigned short low) 
412
{
413
  char tmpstr[25];
414
  sprintf(tmpstr, "%s%d", register_prefix, (int)((instr & mask) >> low));
415
  return(strdup(tmpstr));
416
}
417
418
static char *
419
get_field_imm (long instr) 
420
{
421
  char tmpstr[25];
422
  sprintf(tmpstr, "%d", (short)((instr & IMM_MASK) >> IMM_LOW));
423
  return(strdup(tmpstr));
424
}
425
426
static char *
427
get_field_imm5 (long instr) 
428
{
429
  char tmpstr[25];
430
  sprintf(tmpstr, "%d", (short)((instr & IMM5_MASK) >> IMM_LOW));
431
  return(strdup(tmpstr));
432
}
433
434
static char *
435
get_field_imm12 (long instr) 
436
{
437
  char tmpstr[25];
438
  sprintf(tmpstr, "%s%d", fsl_register_prefix, (short)((instr & IMM12_MASK) >> IMM_LOW));
439
  return(strdup(tmpstr));
440
}
441
442
static char *
443
get_field_imm14 (long instr) 
444
{
445
  char tmpstr[25];
446
  sprintf(tmpstr, "%d", (short)((instr & IMM14_MASK) >> IMM_LOW));
447
  return(strdup(tmpstr));
448
}
449
450
#if 0
451
static char *
452
get_field_unsigned_imm (long instr) 
453
{
454
  char tmpstr[25];
455
  sprintf(tmpstr, "%d", (int)((instr & IMM_MASK) >> IMM_LOW));
456
  return(strdup(tmpstr));
457
}
458
#endif
459
460
/*
461
  char *
462
  get_field_special (instr) 
463
  long instr;
464
  {
465
  char tmpstr[25];
466
  
467
  sprintf(tmpstr, "%s%s", register_prefix, (((instr & IMM_MASK) >> IMM_LOW) & REG_MSR_MASK) == 0 ? "pc" : "msr");
468
  
469
  return(strdup(tmpstr));
470
  }
471
*/
472
473
static char *
474
get_field_special (long instr, struct op_code_struct * op) 
475
{
476
   char tmpstr[25];
477
   char spr[5];
478
479
   switch ( (((instr & IMM_MASK) >> IMM_LOW) ^ op->immval_mask) ) {
480
   case REG_MSR_MASK :
481
      strcpy(spr, "msr");
482
      break;
483
   case REG_PC_MASK :
484
      strcpy(spr, "pc");
485
      break;
486
   case REG_EAR_MASK :
487
      strcpy(spr, "ear");
488
      break;
489
   case REG_ESR_MASK :
490
      strcpy(spr, "esr");
491
      break;
492
   case REG_FSR_MASK :
493
      strcpy(spr, "fsr");
494
      break;      
495
   default :
496
      strcpy(spr, "pc");
497
      break;
498
   }
499
   
500
   sprintf(tmpstr, "%s%s", register_prefix, spr);
501
   return(strdup(tmpstr));
502
}
503
504
static unsigned long
505
read_insn_microblaze(bfd_vma memaddr, struct disassemble_info *info,
506
                     struct op_code_struct ** opr)
507
{
508
  unsigned char       ibytes[4];
509
  int                 status;
510
  struct op_code_struct * op;
511
  unsigned long inst;
512
513
  status = info->read_memory_func (memaddr, ibytes, 4, info);
514
515
  if (status != 0) 
516
    {
517
      info->memory_error_func (status, memaddr, info);
518
      return 0;
519
    }
520
521
  if (info->endian == BFD_ENDIAN_BIG)
522
    inst = (ibytes[0] << 24) | (ibytes[1] << 16) | (ibytes[2] << 8) | ibytes[3];
523
  else if (info->endian == BFD_ENDIAN_LITTLE)
524
    inst = (ibytes[3] << 24) | (ibytes[2] << 16) | (ibytes[1] << 8) | ibytes[0];
525
  else
526
    abort ();
527
528
  /* Just a linear search of the table.  */
529
  for (op = opcodes; op->name != 0; op ++)
530
    if (op->bit_sequence == (inst & op->opcode_mask))
531
      break;
532
533
  *opr = op;
534
  return inst;
535
}
536
537
538
int 
539
print_insn_microblaze (bfd_vma memaddr, struct disassemble_info * info)
540
{
541
  fprintf_ftype       fprintf = info->fprintf_func;
542
  void *              stream = info->stream;
543
  unsigned long       inst, prev_inst;
544
  struct op_code_struct * op, *pop;
545
  int                 immval = 0;
546
  boolean             immfound = false;
547
  static bfd_vma prev_insn_addr = -1; /*init the prev insn addr */
548
  static int     prev_insn_vma = -1;  /*init the prev insn vma */
549
  int            curr_insn_vma = info->buffer_vma;
550
551
  info->bytes_per_chunk = 4;
552
553
  inst = read_insn_microblaze (memaddr, info, &op);
554
  if (inst == 0)
555
    return -1;
556
  
557
  if (prev_insn_vma == curr_insn_vma) {
558
  if (memaddr-(info->bytes_per_chunk) == prev_insn_addr) {
559
    prev_inst = read_insn_microblaze (prev_insn_addr, info, &pop);
560
    if (prev_inst == 0)
561
      return -1;
562
    if (pop->instr == imm) {
563
      immval = (get_int_field_imm(prev_inst) << 16) & 0xffff0000;
564
      immfound = true;
565
    }
566
    else {
567
      immval = 0;
568
      immfound = false;
569
    }
570
  }
571
  }
572
  /* make curr insn as prev insn */
573
  prev_insn_addr = memaddr;
574
  prev_insn_vma = curr_insn_vma;
575
576
  if (op->name == 0)
577
    fprintf (stream, ".short 0x%04x", inst);
578
  else
579
    {
580
      fprintf (stream, "%s", op->name);
581
      
582
      switch (op->inst_type)
583
	{
584
  case INST_TYPE_RD_R1_R2:
585
     fprintf(stream, "\t%s, %s, %s", get_field_rd(inst), get_field_r1(inst), get_field_r2(inst));
586
     break;
587
        case INST_TYPE_RD_R1_IMM:
588
	  fprintf(stream, "\t%s, %s, %s", get_field_rd(inst), get_field_r1(inst), get_field_imm(inst));
589
	  if (info->print_address_func && get_int_field_r1(inst) == 0 && info->symbol_at_address_func) {
590
	    if (immfound)
591
	      immval |= (get_int_field_imm(inst) & 0x0000ffff);
592
	    else {
593
	      immval = get_int_field_imm(inst);
594
	      if (immval & 0x8000)
595
		immval |= 0xFFFF0000;
596
	    }
597
	    if (immval > 0 && info->symbol_at_address_func(immval, info)) {
598
	      fprintf (stream, "\t// ");
599
	      info->print_address_func (immval, info);
600
	    }
601
	  }
602
	  break;
603
	case INST_TYPE_RD_R1_IMM5:
604
	  fprintf(stream, "\t%s, %s, %s", get_field_rd(inst), get_field_r1(inst), get_field_imm5(inst));
605
	  break;
606
	case INST_TYPE_RD_IMM12:
607
	  fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_imm12(inst));
608
	  break;
609
	case INST_TYPE_R1_IMM12:
610
	  fprintf(stream, "\t%s, %s", get_field_r1(inst), get_field_imm12(inst));
611
	  break;
612
	case INST_TYPE_RD_SPECIAL:
613
	  fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_special(inst, op));
614
	  break;
615
	case INST_TYPE_SPECIAL_R1:
616
	  fprintf(stream, "\t%s, %s", get_field_special(inst, op), get_field_r1(inst));
617
	  break;
618
	case INST_TYPE_RD_R1:
619
	  fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_r1(inst));
620
	  break;
621
	case INST_TYPE_R1_R2:
622
	  fprintf(stream, "\t%s, %s", get_field_r1(inst), get_field_r2(inst));
623
	  break;
624
	case INST_TYPE_R1_IMM:
625
	  fprintf(stream, "\t%s, %s", get_field_r1(inst), get_field_imm(inst));
626
	  /* The non-pc relative instructions are returns, which shouldn't 
627
	     have a label printed */
628
	  if (info->print_address_func && op->inst_offset_type == INST_PC_OFFSET && info->symbol_at_address_func) {
629
	    if (immfound)
630
	      immval |= (get_int_field_imm(inst) & 0x0000ffff);
631
	    else {
632
	      immval = get_int_field_imm(inst);
633
	      if (immval & 0x8000)
634
		immval |= 0xFFFF0000;
635
	    }
636
	    immval += memaddr;
637
	    if (immval > 0 && info->symbol_at_address_func(immval, info)) {
638
	      fprintf (stream, "\t// ");
639
	      info->print_address_func (immval, info);
640
	    } else {
641
	      fprintf (stream, "\t\t// ");
642
	      fprintf (stream, "%x", immval);
643
	    }
644
	  }
645
	  break;
646
        case INST_TYPE_RD_IMM:
647
	  fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_imm(inst));
648
	  if (info->print_address_func && info->symbol_at_address_func) {
649
	    if (immfound)
650
	      immval |= (get_int_field_imm(inst) & 0x0000ffff);
651
	    else {
652
	      immval = get_int_field_imm(inst);
653
	      if (immval & 0x8000)
654
		immval |= 0xFFFF0000;
655
	    }
656
	    if (op->inst_offset_type == INST_PC_OFFSET)
657
	      immval += (int) memaddr;
658
	    if (info->symbol_at_address_func(immval, info)) {
659
	      fprintf (stream, "\t// ");
660
	      info->print_address_func (immval, info);
661
	    } 
662
	  }
663
	  break;
664
        case INST_TYPE_IMM:
665
	  fprintf(stream, "\t%s", get_field_imm(inst));
666
	  if (info->print_address_func && info->symbol_at_address_func && op->instr != imm) {
667
	    if (immfound)
668
	      immval |= (get_int_field_imm(inst) & 0x0000ffff);
669
	    else {
670
	      immval = get_int_field_imm(inst);
671
	      if (immval & 0x8000)
672
		immval |= 0xFFFF0000;
673
	    }
674
	    if (op->inst_offset_type == INST_PC_OFFSET)
675
	      immval += (int) memaddr;
676
	    if (immval > 0 && info->symbol_at_address_func(immval, info)) {
677
	      fprintf (stream, "\t// ");
678
	      info->print_address_func (immval, info);
679
	    } else if (op->inst_offset_type == INST_PC_OFFSET) {
680
	      fprintf (stream, "\t\t// ");
681
	      fprintf (stream, "%x", immval);
682
	    }
683
	  }
684
	  break;
685
        case INST_TYPE_RD_R2:
686
	  fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_r2(inst));
687
	  break;
688
  case INST_TYPE_R2:
689
     fprintf(stream, "\t%s", get_field_r2(inst));
690
     break;
691
  case INST_TYPE_R1:
692
     fprintf(stream, "\t%s", get_field_r1(inst));
693
     break;
694
  case INST_TYPE_RD_R1_SPECIAL:
695
     fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_r2(inst));
696
     break;
697
  case INST_TYPE_RD_IMM14:
698
     fprintf(stream, "\t%s, %s", get_field_rd(inst), get_field_imm14(inst));
699
     break;
700
     /* For tuqula instruction */
701
  case INST_TYPE_RD:
702
     fprintf(stream, "\t%s", get_field_rd(inst));
703
     break;
704
     
705
  default:
706
	  /* if the disassembler lags the instruction set */
707
	  fprintf (stream, "\tundecoded operands, inst is 0x%04x", inst);
708
	  break;
709
	}
710
    }
711
  
712
  /* Say how many bytes we consumed? */
713
  return 4;
714
}
715
716
#if 0
717
static enum microblaze_instr
718
get_insn_microblaze (long inst, boolean *isunsignedimm,
719
                     enum microblaze_instr_type *insn_type,
720
                     short *delay_slots ) 
721
{
722
  struct op_code_struct * op;
723
  *isunsignedimm = false;
724
725
  /* Just a linear search of the table.  */
726
  for (op = opcodes; op->name != 0; op ++)
727
    if (op->bit_sequence == (inst & op->opcode_mask))
728
      break;
729
730
  if (op->name == 0)
731
    return invalid_inst;
732
  else {
733
    *isunsignedimm = (op->inst_type == INST_TYPE_RD_R1_UNSIGNED_IMM);
734
    *insn_type = op->instr_type;
735
    *delay_slots = op->delay_slots;
736
    return op->instr;
737
  }
738
}
739
#endif
740
741
#if 0
742
static short
743
get_delay_slots_microblaze ( long inst )
744
{
745
  boolean isunsignedimm;
746
  enum microblaze_instr_type insn_type;
747
  enum microblaze_instr op;
748
  short delay_slots;
749
750
  op = get_insn_microblaze( inst, &isunsignedimm, &insn_type, &delay_slots);
751
  if (op == invalid_inst)
752
    return 0;
753
  else 
754
    return delay_slots;
755
}
756
#endif
757
758
#if 0
759
static enum microblaze_instr
760
microblaze_decode_insn (long insn, int *rd, int *ra, int *rb, int *imm)
761
{
762
  enum microblaze_instr op;
763
  boolean t1;
764
  enum microblaze_instr_type t2;
765
  short t3;
766
767
  op = get_insn_microblaze(insn, &t1, &t2, &t3);
768
  *rd = (insn & RD_MASK) >> RD_LOW;
769
  *ra = (insn & RA_MASK) >> RA_LOW;
770
  *rb = (insn & RB_MASK) >> RB_LOW;
771
  t3 = (insn & IMM_MASK) >> IMM_LOW;
772
  *imm = (int) t3;
773
  return (op);
774
}
775
#endif
776
777
#if 0
778
static unsigned long
779
microblaze_get_target_address (long inst, boolean immfound, int immval,
780
                               long pcval, long r1val, long r2val,
781
                               boolean *targetvalid,
782
                               boolean *unconditionalbranch)
783
{
784
  struct op_code_struct * op;
785
  long targetaddr = 0;
786
787
  *unconditionalbranch = false;
788
  /* Just a linear search of the table.  */
789
  for (op = opcodes; op->name != 0; op ++)
790
    if (op->bit_sequence == (inst & op->opcode_mask))
791
      break;
792
793
  if (op->name == 0) {
794
    *targetvalid = false;
795
  } else if (op->instr_type == branch_inst) {
796
    switch (op->inst_type) {
797
    case INST_TYPE_R2:
798
      *unconditionalbranch = true;
799
      /* fallthru */
800
    case INST_TYPE_RD_R2:
801
    case INST_TYPE_R1_R2:
802
      targetaddr = r2val;
803
      *targetvalid = true;
804
      if (op->inst_offset_type == INST_PC_OFFSET)
805
	targetaddr += pcval;
806
      break;
807
    case INST_TYPE_IMM:
808
      *unconditionalbranch = true;
809
      /* fallthru */
810
    case INST_TYPE_RD_IMM:
811
    case INST_TYPE_R1_IMM:
812
      if (immfound) {
813
	targetaddr = (immval << 16) & 0xffff0000;
814
	targetaddr |= (get_int_field_imm(inst) & 0x0000ffff);
815
      } else {
816
	targetaddr = get_int_field_imm(inst);
817
	if (targetaddr & 0x8000)
818
	  targetaddr |= 0xFFFF0000;
819
      }
820
      if (op->inst_offset_type == INST_PC_OFFSET)
821
	targetaddr += pcval;
822
      *targetvalid = true;
823
      break;
824
    default:
825
      *targetvalid = false;
826
      break;
827
    }
828
  } else if (op->instr_type == return_inst) {
829
      if (immfound) {
830
	targetaddr = (immval << 16) & 0xffff0000;
831
	targetaddr |= (get_int_field_imm(inst) & 0x0000ffff);
832
      } else {
833
	targetaddr = get_int_field_imm(inst);
834
	if (targetaddr & 0x8000)
835
	  targetaddr |= 0xFFFF0000;
836
      }
837
      targetaddr += r1val;
838
      *targetvalid = true;
839
  } else {
840
    *targetvalid = false;
841
  }
842
  return targetaddr;
843
}
844
#endif