Statistics
| Branch: | Revision:

root / microblaze-dis.c @ 8167ee88

History | View | Annotate | Download (39.8 kB)

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
15
along with this program; if not, see <http://www.gnu.org/licenses/>.  */
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
57
along with this program; if not, see <http://www.gnu.org/licenses/>.  */
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