OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [sw/] [utils/] [or32-idecode/] [or32-dis.c] - Blame information for rev 27

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 julius
/* Instruction printing code for the OpenRISC 1000
2
   Copyright (C) 2002, 2005, 2007 Free Software Foundation, Inc.
3
   Contributed by Damjan Lampret <lampret@opencores.org>.
4
   Modified from a29k port.
5
 
6
   This file is part of the GNU opcodes library.
7
 
8
   This library is free software; you can redistribute it and/or modify
9
   it under the terms of the GNU General Public License as published by
10
   the Free Software Foundation; either version 3, or (at your option)
11
   any later version.
12
 
13
   It is distributed in the hope that it will be useful, but WITHOUT
14
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15
   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16
   License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with this program; if not, write to the Free Software
20
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21
   MA 02110-1301, USA.  */
22
 
23
#define DEBUG 0
24
 
25
#include "dis-asm.h"
26
#include "or32.h"
27
//#include "safe-ctype.h"
28
#include <ctype.h>
29
#include <string.h>
30
#include <stdlib.h>
31
#include <stdio.h>
32
#define EXTEND28(x) ((x) & (unsigned long) 0x08000000 ? ((x) | (unsigned long) 0xf0000000) : ((x)))
33
 
34
/* Now find the four bytes of INSN_CH and put them in *INSN.  */
35
 
36
static void
37
find_bytes_big (unsigned char *insn_ch, unsigned long *insn)
38
{
39
  *insn =
40
    ((unsigned long) insn_ch[0] << 24) +
41
    ((unsigned long) insn_ch[1] << 16) +
42
    ((unsigned long) insn_ch[2] << 8) +
43
    ((unsigned long) insn_ch[3]);
44
#if DEBUG
45
  printf ("find_bytes_big3: %x\n", *insn);
46
#endif
47
}
48
 
49
static void
50
find_bytes_little (unsigned char *insn_ch, unsigned long *insn)
51
{
52
  *insn =
53
    ((unsigned long) insn_ch[3] << 24) +
54
    ((unsigned long) insn_ch[2] << 16) +
55
    ((unsigned long) insn_ch[1] << 8) +
56
    ((unsigned long) insn_ch[0]);
57
}
58
 
59
typedef void (*find_byte_func_type) (unsigned char *, unsigned long *);
60
 
61
static unsigned long
62
or32_extract (char param_ch, char *enc_initial, unsigned long insn)
63
{
64
  char *enc;
65
  unsigned long ret = 0;
66
  int opc_pos = 0;
67
  int param_pos = 0;
68
 
69
  for (enc = enc_initial; *enc != '\0'; enc++)
70
    if (*enc == param_ch)
71
      {
72
        if (enc - 2 >= enc_initial && (*(enc - 2) == '0') && (*(enc - 1) == 'x'))
73
          continue;
74
        else
75
          param_pos++;
76
      }
77
 
78
#if DEBUG
79
  printf ("or32_extract: %c %x ", param_ch, param_pos);
80
#endif
81
  opc_pos = 32;
82
 
83
  for (enc = enc_initial; *enc != '\0'; )
84
    if ((*enc == '0') && (*(enc + 1) == 'x'))
85
      {
86
        opc_pos -= 4;
87
 
88
        if ((param_ch == '0') || (param_ch == '1'))
89
          {
90
            unsigned long tmp = strtoul (enc, NULL, 16);
91
#if DEBUG
92
            printf (" enc=%s, tmp=%x ", enc, tmp);
93
#endif
94
            if (param_ch == '0')
95
              tmp = 15 - tmp;
96
            ret |= tmp << opc_pos;
97
          }
98
        enc += 3;
99
      }
100
    else if ((*enc == '0') || (*enc == '1'))
101
      {
102
        opc_pos--;
103
        if (param_ch == *enc)
104
          ret |= 1 << opc_pos;
105
        enc++;
106
      }
107
    else if (*enc == param_ch)
108
      {
109
        opc_pos--;
110
        param_pos--;
111
#if DEBUG
112
        printf ("\n  ret=%x opc_pos=%x, param_pos=%x\n", ret, opc_pos, param_pos);
113
#endif
114
        ret += ((insn >> opc_pos) & 0x1) << param_pos;
115
 
116
        if (!param_pos
117
            && letter_signed (param_ch)
118
            && ret >> (letter_range (param_ch) - 1))
119
          {
120
#if DEBUG
121
            printf ("\n  ret=%x opc_pos=%x, param_pos=%x\n",
122
                    ret, opc_pos, param_pos);
123
#endif
124
            ret |= 0xffffffff << letter_range(param_ch);
125
#if DEBUG
126
            printf ("\n  after conversion to signed: ret=%x\n", ret);
127
#endif
128
          }
129
        enc++;
130
      }
131
  //else if (ISALPHA (*enc))
132
  else if (isalpha(*enc))
133
      {
134
        opc_pos--;
135
        enc++;
136
      }
137
    else if (*enc == '-')
138
      {
139
        opc_pos--;
140
        enc++;
141
      }
142
    else
143
      enc++;
144
 
145
#if DEBUG
146
  printf ("ret=%x\n", ret);
147
#endif
148
  return ret;
149
}
150
 
151
static int
152
or32_opcode_match (unsigned long insn, char *encoding)
153
{
154
  unsigned long ones, zeros;
155
 
156
#if DEBUG
157
  printf ("or32_opcode_match: %.8lx\n", insn);
158
#endif    
159
  ones  = or32_extract ('1', encoding, insn);
160
  zeros = or32_extract ('0', encoding, insn);
161
 
162
  // Added 090430 - jb - fixed problem where upper 4 bytes of a 64-bit long weren't getting setup properly for comparison
163
  // As a result, instructions weren't getting decoded properly
164
  insn &= 0xffffffff;
165
  ones &= 0xffffffff;
166
  zeros &= 0xffffffff;
167
 
168
#if DEBUG
169
  printf ("ones: %x \n", ones);
170
  printf ("zeros: %x \n", zeros);
171
#endif
172
  if ((insn & ones) != ones)
173
    {
174
#if DEBUG
175
      printf ("ret1\n");
176
#endif
177
      return 0;
178
    }
179
 
180
  if ((~insn & zeros) != zeros)
181
    {
182
#if DEBUG
183
      printf ("ret2\n");
184
#endif
185
      return 0;
186
    }
187
 
188
#if DEBUG
189
  printf ("ret3\n");
190
#endif
191
  return 1;
192
}
193
 
194
/* Print register to INFO->STREAM. Used only by print_insn.  */
195
 
196
static void
197
or32_print_register (char param_ch,
198
                     char *encoding,
199
                     unsigned long insn)
200
                     //              struct disassemble_info *info)
201
{
202
  int regnum = or32_extract (param_ch, encoding, insn);
203
 
204
#if DEBUG
205
  printf ("or32_print_register: %c, %s, %x\n", param_ch, encoding, insn);
206
#endif  
207
  if (param_ch == 'A')
208
    //(*info->fprintf_func) (info->stream, "r%d", regnum);
209
    printf("r%d", regnum);
210
  else if (param_ch == 'B')
211
    //(*info->fprintf_func) (info->stream, "r%d", regnum);
212
    printf("r%d", regnum);
213
  else if (param_ch == 'D')
214
    //(*info->fprintf_func) (info->stream, "r%d", regnum);
215
    printf("r%d", regnum);
216
  else if (regnum < 16)
217
    //(*info->fprintf_func) (info->stream, "r%d", regnum);
218
    printf("r%d", regnum);
219
  else if (regnum < 32)
220
    //(*info->fprintf_func) (info->stream, "r%d", regnum-16);
221
    printf("r%d", regnum-16);
222
  else
223
    //(*info->fprintf_func) (info->stream, "X%d", regnum);
224
    printf("X%d", regnum);
225
}
226
 
227
/* Print immediate to INFO->STREAM. Used only by print_insn.  */
228
 
229
static void
230
or32_print_immediate (char param_ch,
231
                      char *encoding,
232
                      unsigned long insn)
233
                      //struct disassemble_info *info)
234
{
235
  int imm = or32_extract(param_ch, encoding, insn);
236
 
237
  if (letter_signed(param_ch))
238
    //(*info->fprintf_func) (info->stream, "0x%x", imm);
239
    printf("0x%x", imm);
240
/*    (*info->fprintf_func) (info->stream, "%d", imm); */
241
  else
242
    //(*info->fprintf_func) (info->stream, "0x%x", imm);
243
    printf("0x%x", imm);
244
}
245
 
246
/* Print one instruction from MEMADDR on INFO->STREAM.
247
   Return the size of the instruction (always 4 on or32).  */
248
 
249
static int
250
//print_insn (bfd_vma memaddr, struct disassemble_info *info)
251
print_insn(unsigned long insn)
252
{
253
  /* The raw instruction.  */
254
  unsigned char insn_ch[4];
255
  /* Address. Will be sign extened 27-bit.  */
256
  unsigned long addr;
257
  /* The four bytes of the instruction.  */
258
  //unsigned long insn;
259
  //find_byte_func_type find_byte_func = (find_byte_func_type) info->private_data;
260
  struct or32_opcode const * opcode;
261
  /*
262
  {
263
    int status =
264
      (*info->read_memory_func) (memaddr, (bfd_byte *) &insn_ch[0], 4, info);
265
 
266
    if (status != 0)
267
      {
268
        (*info->memory_error_func) (status, memaddr, info);
269
        return -1;
270
      }
271
  }
272
  */
273
 
274
  //(*find_byte_func) (&insn_ch[0], &insn);
275
 
276
  for (opcode = &or32_opcodes[0];
277
       opcode < &or32_opcodes[or32_num_opcodes];
278
       ++opcode)
279
    {
280
      if (or32_opcode_match (insn, opcode->encoding))
281
        {
282
          char *s;
283
 
284
          //(*info->fprintf_func) (info->stream, "%s ", opcode->name);
285
          printf("%s ", opcode->name);
286
 
287
          for (s = opcode->args; *s != '\0'; ++s)
288
            {
289
              switch (*s)
290
                {
291
                case '\0':
292
                  return 4;
293
 
294
                case 'r':
295
                  //or32_print_register (*++s, opcode->encoding, insn, info);
296
                  or32_print_register (*++s, opcode->encoding, insn);
297
                  break;
298
 
299
                case 'N':
300
                  addr = or32_extract ('N', opcode->encoding, insn) << 2;
301
 
302
                  /* Calulate the correct address.  */
303
                  //addr = memaddr + EXTEND28 (addr);
304
 
305
                  //(*info->print_address_func)
306
                  //  (addr, info);
307
                  break;
308
 
309
                default:
310
                  if (strchr (opcode->encoding, *s))
311
                    //or32_print_immediate (*s, opcode->encoding, insn, info);
312
                    or32_print_immediate (*s, opcode->encoding, insn);
313
                  else
314
                    //(*info->fprintf_func) (info->stream, "%c", *s);
315
                    printf("%c", *s);
316
                }
317
            }
318
 
319
          return 4;
320
        }
321
    }
322
 
323
  /* This used to be %8x for binutils.  */
324
  //  (*info->fprintf_func)
325
  //  (info->stream, ".word 0x%08lx", insn);
326
  printf(".word 0x%08lx", insn);
327
  return 4;
328
}
329
 
330
/* Disassemble a big-endian or32 instruction.  */
331
/*
332
int
333
print_insn_big_or32 (bfd_vma memaddr, struct disassemble_info *info)
334
{
335
  info->private_data = find_bytes_big;
336
 
337
  return print_insn (memaddr, info);
338
}
339
*/
340
/* Disassemble a little-endian or32 instruction.  */
341
 /*
342
int
343
print_insn_little_or32 (bfd_vma memaddr, struct disassemble_info *info)
344
{
345
  info->private_data = find_bytes_little;
346
  return print_insn (memaddr, info);
347
}
348
 */
349
#define PRINT_ORIG_INSN_OPTION "-print-orig-insn"
350
 
351
static void print_or32_dis_usage(char *argv[])
352
{
353
  printf(" OpenRISC instruction decoder\n");
354
  printf("\n");
355
  printf(" Decodes an instruction passed on the command line, otherwise reads from stdin.\n");
356
  printf(" The option %s prints out the original instruction along with the decoded version\n similar to the objdump disassembler output, except without address information\n", PRINT_ORIG_INSN_OPTION);
357
  printf("\n");
358
  printf(" Usage:\n");
359
  printf("\n");
360
  printf(" Decode a single instruction from the command line:\n");
361
  printf(" \t%s 0x1500000\n", argv[0]);
362
  printf("\n");
363
  printf(" Decode a list of instructions from stdin:\n");
364
  printf(" \t%s < list_of_insns\n", argv[0]);
365
  printf("\n");
366
  printf(" Decode a list of instructions from stdin, and print out the original instruction as well:\n");
367
  printf(" \t%s -print-orig-insn < list_of_insns\n", argv[0]);
368
  printf("\n");
369
  printf(" Note: The values don't require the leading \"0x\"\n");
370
  printf("\n");
371
  return;
372
}
373
 
374
// Simple program to do disassembly like or32-objdump but on individual instructions passed to it
375
  // Pass the instruction in hex
376
int main (int argc, char *argv[])
377
{
378
  unsigned long insn;
379
 
380
 
381
  int print_orig_inst_option = 0; // Don't print the instruction we're passed, by default, just the decoded version
382
  // extract possible options we were passed
383
  int i;
384
  for(i=1;i<argc;i++)
385
    {
386
      // First check if it's an option we've been passed
387
      if (strncmp(argv[i],"-", 1) == 0 )
388
        {
389
          //printf("option detected at argv[%d]\n", i);
390
          if (strcmp(argv[i],PRINT_ORIG_INSN_OPTION) == 0 )
391
            {
392
              print_orig_inst_option = 1;
393
              break;
394
            }
395
          if (strncmp(argv[i],"-h",2) == 0 )
396
            {
397
              print_or32_dis_usage(argv);
398
              return 0;
399
            }
400
 
401
        }
402
    }
403
 
404
  int use_stdin = 0;
405
 
406
  if ((argc == 3 && print_orig_inst_option) || (argc == 2 && !print_orig_inst_option))
407
    use_stdin = 0;
408
  else
409
    use_stdin = 1;
410
 
411
  if (!use_stdin) // Just read the instruction passed to us on the command line and exit
412
    {
413
      int index = 1;
414
      if (argc > 2 )
415
        {
416
          if (i == 1) index++; // If the option was the first thing passed, the instruction is in argv[2]
417
        }
418
 
419
      insn = strtoul(argv[index], NULL, 16);
420
      if (print_orig_inst_option)
421
        printf(" %.8lx\t", insn);
422
      print_insn (insn);
423
      printf("\n");
424
 
425
    }
426
  else
427
    {
428
      char inp[10]; // Buffer is long enough to have an 8 char hex value plus its leading "0x", but that is not essential
429
      while(1) // Loop, reading from stdin
430
        {
431
          char c;
432
          c = getchar();
433
          //printf("%c",c);
434
          if (c == '\n') // End of a line - now determine the instruction we've been given
435
            {
436
              insn = strtoul(inp, NULL, 16);
437
 
438
              if (print_orig_inst_option)
439
                printf(" %.8lx\t", insn);
440
 
441
              print_insn (insn);
442
              printf("\n");
443
 
444
              // clear our little buffer
445
              for(i=0;i<10;i++)inp[i]=0;
446
            }
447
          else if (c == EOF)
448
            {
449
              break;
450
            }
451
          else
452
            {
453
              for(i=0;i<9-1;i++)inp[i]=inp[i+1];
454
              inp[7]=c;
455
            }
456
 
457
        }
458
    }
459
  return 0;
460
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.