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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [sw/] [utils/] [or32-idecode/] [or32-dis.c] - Blame information for rev 6

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

Line No. Rev Author Line
1 6 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
                  int32_t int32_addr = (int32_t) addr; // Must use explicitly sized bariable here
302
                  //printf("int32_addr: %d ", int32_addr);
303
                  if (int32_addr >= 0)
304
                    printf("(+0x%x)", int32_addr);
305
                  else
306
                    {
307
                      int32_addr = (~int32_addr) + 1;
308
                      printf("(-0x%x)", int32_addr);
309
                    }
310
                  /* Calulate the correct address.  */
311
                  //addr = memaddr + EXTEND28 (addr);
312
 
313
                  //(*info->print_address_func)
314
                  //  (addr, info);
315
                  break;
316
 
317
                default:
318
                  if (strchr (opcode->encoding, *s))
319
                    //or32_print_immediate (*s, opcode->encoding, insn, info);
320
                    or32_print_immediate (*s, opcode->encoding, insn);
321
                  else
322
                    //(*info->fprintf_func) (info->stream, "%c", *s);
323
                    printf("%c", *s);
324
                }
325
            }
326
 
327
          return 4;
328
        }
329
    }
330
 
331
  /* This used to be %8x for binutils.  */
332
  //  (*info->fprintf_func)
333
  //  (info->stream, ".word 0x%08lx", insn);
334
  printf(".word 0x%08lx", insn);
335
  return 4;
336
}
337
 
338
/* Disassemble a big-endian or32 instruction.  */
339
/*
340
int
341
print_insn_big_or32 (bfd_vma memaddr, struct disassemble_info *info)
342
{
343
  info->private_data = find_bytes_big;
344
 
345
  return print_insn (memaddr, info);
346
}
347
*/
348
/* Disassemble a little-endian or32 instruction.  */
349
 /*
350
int
351
print_insn_little_or32 (bfd_vma memaddr, struct disassemble_info *info)
352
{
353
  info->private_data = find_bytes_little;
354
  return print_insn (memaddr, info);
355
}
356
 */
357
#define PRINT_ORIG_INSN_OPTION "-print-orig-insn"
358
 
359
static void print_or32_dis_usage(char *argv[])
360
{
361
  printf(" OpenRISC instruction decoder\n");
362
  printf("\n");
363
  printf(" Decodes an instruction passed on the command line, otherwise reads from stdin.\n");
364
  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);
365
  printf("\n");
366
  printf(" Usage:\n");
367
  printf("\n");
368
  printf(" Decode a single instruction from the command line:\n");
369
  printf(" \t%s 0x1500000\n", argv[0]);
370
  printf("\n");
371
  printf(" Decode a list of instructions from stdin:\n");
372
  printf(" \t%s < list_of_insns\n", argv[0]);
373
  printf("\n");
374
  printf(" Decode a list of instructions from stdin, and print out the original instruction as well:\n");
375
  printf(" \t%s -print-orig-insn < list_of_insns\n", argv[0]);
376
  printf("\n");
377
  printf(" Note: The values don't require the leading \"0x\"\n");
378
  printf("\n");
379
  return;
380
}
381
 
382
// Simple program to do disassembly like or32-objdump but on individual instructions passed to it
383
  // Pass the instruction in hex
384
int main (int argc, char *argv[])
385
{
386
  unsigned long insn;
387
 
388
 
389
  int print_orig_inst_option = 0; // Don't print the instruction we're passed, by default, just the decoded version
390
  // extract possible options we were passed
391
  int i;
392
  for(i=1;i<argc;i++)
393
    {
394
      // First check if it's an option we've been passed
395
      if (strncmp(argv[i],"-", 1) == 0 )
396
        {
397
          //printf("option detected at argv[%d]\n", i);
398
          if (strcmp(argv[i],PRINT_ORIG_INSN_OPTION) == 0 )
399
            {
400
              print_orig_inst_option = 1;
401
              break;
402
            }
403
          if (strncmp(argv[i],"-h",2) == 0 )
404
            {
405
              print_or32_dis_usage(argv);
406
              return 0;
407
            }
408
 
409
        }
410
    }
411
 
412
  int use_stdin = 0;
413
 
414
  if ((argc == 3 && print_orig_inst_option) || (argc == 2 && !print_orig_inst_option))
415
    use_stdin = 0;
416
  else
417
    use_stdin = 1;
418
 
419
  if (!use_stdin) // Just read the instruction passed to us on the command line and exit
420
    {
421
      int index = 1;
422
      if (argc > 2 )
423
        {
424
          if (i == 1) index++; // If the option was the first thing passed, the instruction is in argv[2]
425
        }
426
 
427
      insn = strtoul(argv[index], NULL, 16);
428
      if (print_orig_inst_option)
429
        printf(" %.8lx\t", insn);
430
      print_insn (insn);
431
      printf("\n");
432
 
433
    }
434
  else
435
    {
436
      char inp[10]; // Buffer is long enough to have an 8 char hex value plus its leading "0x", but that is not essential
437
      while(1) // Loop, reading from stdin
438
        {
439
          char c;
440
          c = getchar();
441
          //printf("%c",c);
442
          if (c == '\n') // End of a line - now determine the instruction we've been given
443
            {
444
              insn = strtoul(inp, NULL, 16);
445
 
446
              if (print_orig_inst_option)
447
                printf(" %.8lx\t", insn);
448
 
449
              print_insn (insn);
450
              printf("\n");
451
 
452
              // clear our little buffer
453
              for(i=0;i<10;i++)inp[i]=0;
454
            }
455
          else if (c == EOF)
456
            {
457
              break;
458
            }
459
          else
460
            {
461
              for(i=0;i<9-1;i++)inp[i]=inp[i+1];
462
              inp[7]=c;
463
            }
464
 
465
        }
466
    }
467
  return 0;
468
}

powered by: WebSVN 2.1.0

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