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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-stable/] [gdb-7.2/] [gdb/] [ax-general.c] - Blame information for rev 835

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

Line No. Rev Author Line
1 330 jeremybenn
/* Functions for manipulating expressions designed to be executed on the agent
2
   Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009, 2010
3
   Free Software Foundation, Inc.
4
 
5
   This file is part of GDB.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
 
20
/* Despite what the above comment says about this file being part of
21
   GDB, we would like to keep these functions free of GDB
22
   dependencies, since we want to be able to use them in contexts
23
   outside of GDB (test suites, the stub, etc.)  */
24
 
25
#include "defs.h"
26
#include "ax.h"
27
 
28
#include "value.h"
29
#include "gdb_string.h"
30
 
31
static void grow_expr (struct agent_expr *x, int n);
32
 
33
static void append_const (struct agent_expr *x, LONGEST val, int n);
34
 
35
static LONGEST read_const (struct agent_expr *x, int o, int n);
36
 
37
static void generic_ext (struct agent_expr *x, enum agent_op op, int n);
38
 
39
/* Functions for building expressions.  */
40
 
41
/* Allocate a new, empty agent expression.  */
42
struct agent_expr *
43
new_agent_expr (struct gdbarch *gdbarch, CORE_ADDR scope)
44
{
45
  struct agent_expr *x = xmalloc (sizeof (*x));
46
 
47
  x->len = 0;
48
  x->size = 1;                  /* Change this to a larger value once
49
                                   reallocation code is tested.  */
50
  x->buf = xmalloc (x->size);
51
 
52
  x->gdbarch = gdbarch;
53
  x->scope = scope;
54
 
55
  /* Bit vector for registers used.  */
56
  x->reg_mask_len = 1;
57
  x->reg_mask = xmalloc (x->reg_mask_len * sizeof (x->reg_mask[0]));
58
  memset (x->reg_mask, 0, x->reg_mask_len * sizeof (x->reg_mask[0]));
59
 
60
  return x;
61
}
62
 
63
/* Free a agent expression.  */
64
void
65
free_agent_expr (struct agent_expr *x)
66
{
67
  xfree (x->buf);
68
  xfree (x->reg_mask);
69
  xfree (x);
70
}
71
 
72
static void
73
do_free_agent_expr_cleanup (void *x)
74
{
75
  free_agent_expr (x);
76
}
77
 
78
struct cleanup *
79
make_cleanup_free_agent_expr (struct agent_expr *x)
80
{
81
  return make_cleanup (do_free_agent_expr_cleanup, x);
82
}
83
 
84
 
85
/* Make sure that X has room for at least N more bytes.  This doesn't
86
   affect the length, just the allocated size.  */
87
static void
88
grow_expr (struct agent_expr *x, int n)
89
{
90
  if (x->len + n > x->size)
91
    {
92
      x->size *= 2;
93
      if (x->size < x->len + n)
94
        x->size = x->len + n + 10;
95
      x->buf = xrealloc (x->buf, x->size);
96
    }
97
}
98
 
99
 
100
/* Append the low N bytes of VAL as an N-byte integer to the
101
   expression X, in big-endian order.  */
102
static void
103
append_const (struct agent_expr *x, LONGEST val, int n)
104
{
105
  int i;
106
 
107
  grow_expr (x, n);
108
  for (i = n - 1; i >= 0; i--)
109
    {
110
      x->buf[x->len + i] = val & 0xff;
111
      val >>= 8;
112
    }
113
  x->len += n;
114
}
115
 
116
 
117
/* Extract an N-byte big-endian unsigned integer from expression X at
118
   offset O.  */
119
static LONGEST
120
read_const (struct agent_expr *x, int o, int n)
121
{
122
  int i;
123
  LONGEST accum = 0;
124
 
125
  /* Make sure we're not reading off the end of the expression.  */
126
  if (o + n > x->len)
127
    error (_("GDB bug: ax-general.c (read_const): incomplete constant"));
128
 
129
  for (i = 0; i < n; i++)
130
    accum = (accum << 8) | x->buf[o + i];
131
 
132
  return accum;
133
}
134
 
135
 
136
/* Append a simple operator OP to EXPR.  */
137
void
138
ax_simple (struct agent_expr *x, enum agent_op op)
139
{
140
  grow_expr (x, 1);
141
  x->buf[x->len++] = op;
142
}
143
 
144
 
145
/* Append a sign-extension or zero-extension instruction to EXPR, to
146
   extend an N-bit value.  */
147
static void
148
generic_ext (struct agent_expr *x, enum agent_op op, int n)
149
{
150
  /* N must fit in a byte.  */
151
  if (n < 0 || n > 255)
152
    error (_("GDB bug: ax-general.c (generic_ext): bit count out of range"));
153
  /* That had better be enough range.  */
154
  if (sizeof (LONGEST) * 8 > 255)
155
    error (_("GDB bug: ax-general.c (generic_ext): opcode has inadequate range"));
156
 
157
  grow_expr (x, 2);
158
  x->buf[x->len++] = op;
159
  x->buf[x->len++] = n;
160
}
161
 
162
 
163
/* Append a sign-extension instruction to EXPR, to extend an N-bit value.  */
164
void
165
ax_ext (struct agent_expr *x, int n)
166
{
167
  generic_ext (x, aop_ext, n);
168
}
169
 
170
 
171
/* Append a zero-extension instruction to EXPR, to extend an N-bit value.  */
172
void
173
ax_zero_ext (struct agent_expr *x, int n)
174
{
175
  generic_ext (x, aop_zero_ext, n);
176
}
177
 
178
 
179
/* Append a trace_quick instruction to EXPR, to record N bytes.  */
180
void
181
ax_trace_quick (struct agent_expr *x, int n)
182
{
183
  /* N must fit in a byte.  */
184
  if (n < 0 || n > 255)
185
    error (_("GDB bug: ax-general.c (ax_trace_quick): size out of range for trace_quick"));
186
 
187
  grow_expr (x, 2);
188
  x->buf[x->len++] = aop_trace_quick;
189
  x->buf[x->len++] = n;
190
}
191
 
192
 
193
/* Append a goto op to EXPR.  OP is the actual op (must be aop_goto or
194
   aop_if_goto).  We assume we don't know the target offset yet,
195
   because it's probably a forward branch, so we leave space in EXPR
196
   for the target, and return the offset in EXPR of that space, so we
197
   can backpatch it once we do know the target offset.  Use ax_label
198
   to do the backpatching.  */
199
int
200
ax_goto (struct agent_expr *x, enum agent_op op)
201
{
202
  grow_expr (x, 3);
203
  x->buf[x->len + 0] = op;
204
  x->buf[x->len + 1] = 0xff;
205
  x->buf[x->len + 2] = 0xff;
206
  x->len += 3;
207
  return x->len - 2;
208
}
209
 
210
/* Suppose a given call to ax_goto returns some value PATCH.  When you
211
   know the offset TARGET that goto should jump to, call
212
   ax_label (EXPR, PATCH, TARGET)
213
   to patch TARGET into the ax_goto instruction.  */
214
void
215
ax_label (struct agent_expr *x, int patch, int target)
216
{
217
  /* Make sure the value is in range.  Don't accept 0xffff as an
218
     offset; that's our magic sentinel value for unpatched branches.  */
219
  if (target < 0 || target >= 0xffff)
220
    error (_("GDB bug: ax-general.c (ax_label): label target out of range"));
221
 
222
  x->buf[patch] = (target >> 8) & 0xff;
223
  x->buf[patch + 1] = target & 0xff;
224
}
225
 
226
 
227
/* Assemble code to push a constant on the stack.  */
228
void
229
ax_const_l (struct agent_expr *x, LONGEST l)
230
{
231
  static enum agent_op ops[]
232
  =
233
  {aop_const8, aop_const16, aop_const32, aop_const64};
234
  int size;
235
  int op;
236
 
237
  /* How big is the number?  'op' keeps track of which opcode to use.
238
     Notice that we don't really care whether the original number was
239
     signed or unsigned; we always reproduce the value exactly, and
240
     use the shortest representation.  */
241
  for (op = 0, size = 8; size < 64; size *= 2, op++)
242
    {
243
      LONGEST lim = ((LONGEST) 1) << (size - 1);
244
 
245
      if (-lim <= l && l <= lim - 1)
246
        break;
247
    }
248
 
249
  /* Emit the right opcode... */
250
  ax_simple (x, ops[op]);
251
 
252
  /* Emit the low SIZE bytes as an unsigned number.  We know that
253
     sign-extending this will yield l.  */
254
  append_const (x, l, size / 8);
255
 
256
  /* Now, if it was negative, and not full-sized, sign-extend it.  */
257
  if (l < 0 && size < 64)
258
    ax_ext (x, size);
259
}
260
 
261
 
262
void
263
ax_const_d (struct agent_expr *x, LONGEST d)
264
{
265
  /* FIXME: floating-point support not present yet.  */
266
  error (_("GDB bug: ax-general.c (ax_const_d): floating point not supported yet"));
267
}
268
 
269
 
270
/* Assemble code to push the value of register number REG on the
271
   stack.  */
272
void
273
ax_reg (struct agent_expr *x, int reg)
274
{
275
  /* Make sure the register number is in range.  */
276
  if (reg < 0 || reg > 0xffff)
277
    error (_("GDB bug: ax-general.c (ax_reg): register number out of range"));
278
  grow_expr (x, 3);
279
  x->buf[x->len] = aop_reg;
280
  x->buf[x->len + 1] = (reg >> 8) & 0xff;
281
  x->buf[x->len + 2] = (reg) & 0xff;
282
  x->len += 3;
283
}
284
 
285
/* Assemble code to operate on a trace state variable.  */
286
 
287
void
288
ax_tsv (struct agent_expr *x, enum agent_op op, int num)
289
{
290
  /* Make sure the tsv number is in range.  */
291
  if (num < 0 || num > 0xffff)
292
    internal_error (__FILE__, __LINE__, _("ax-general.c (ax_tsv): variable number is %d, out of range"), num);
293
 
294
  grow_expr (x, 3);
295
  x->buf[x->len] = op;
296
  x->buf[x->len + 1] = (num >> 8) & 0xff;
297
  x->buf[x->len + 2] = (num) & 0xff;
298
  x->len += 3;
299
}
300
 
301
 
302
 
303
/* Functions for disassembling agent expressions, and otherwise
304
   debugging the expression compiler.  */
305
 
306
struct aop_map aop_map[] =
307
{
308
  {0, 0, 0, 0, 0},
309
  {"float", 0, 0, 0, 0},    /* 0x01 */
310
  {"add", 0, 0, 2, 1},            /* 0x02 */
311
  {"sub", 0, 0, 2, 1},            /* 0x03 */
312
  {"mul", 0, 0, 2, 1},            /* 0x04 */
313
  {"div_signed", 0, 0, 2, 1},     /* 0x05 */
314
  {"div_unsigned", 0, 0, 2, 1},   /* 0x06 */
315
  {"rem_signed", 0, 0, 2, 1},     /* 0x07 */
316
  {"rem_unsigned", 0, 0, 2, 1},   /* 0x08 */
317
  {"lsh", 0, 0, 2, 1},            /* 0x09 */
318
  {"rsh_signed", 0, 0, 2, 1},     /* 0x0a */
319
  {"rsh_unsigned", 0, 0, 2, 1},   /* 0x0b */
320
  {"trace", 0, 0, 2, 0},   /* 0x0c */
321
  {"trace_quick", 1, 0, 1, 1},   /* 0x0d */
322
  {"log_not", 0, 0, 1, 1},        /* 0x0e */
323
  {"bit_and", 0, 0, 2, 1},        /* 0x0f */
324
  {"bit_or", 0, 0, 2, 1}, /* 0x10 */
325
  {"bit_xor", 0, 0, 2, 1},        /* 0x11 */
326
  {"bit_not", 0, 0, 1, 1},        /* 0x12 */
327
  {"equal", 0, 0, 2, 1},  /* 0x13 */
328
  {"less_signed", 0, 0, 2, 1},    /* 0x14 */
329
  {"less_unsigned", 0, 0, 2, 1},  /* 0x15 */
330
  {"ext", 1, 0, 1, 1},           /* 0x16 */
331
  {"ref8", 0, 8, 1, 1},          /* 0x17 */
332
  {"ref16", 0, 16, 1, 1},        /* 0x18 */
333
  {"ref32", 0, 32, 1, 1},        /* 0x19 */
334
  {"ref64", 0, 64, 1, 1},        /* 0x1a */
335
  {"ref_float", 0, 0, 1, 1},      /* 0x1b */
336
  {"ref_double", 0, 0, 1, 1},     /* 0x1c */
337
  {"ref_long_double", 0, 0, 1, 1},        /* 0x1d */
338
  {"l_to_d", 0, 0, 1, 1}, /* 0x1e */
339
  {"d_to_l", 0, 0, 1, 1}, /* 0x1f */
340
  {"if_goto", 2, 0, 1, 0},        /* 0x20 */
341
  {"goto", 2, 0, 0, 0},            /* 0x21 */
342
  {"const8", 1, 8, 0, 1},        /* 0x22 */
343
  {"const16", 2, 16, 0, 1},      /* 0x23 */
344
  {"const32", 4, 32, 0, 1},      /* 0x24 */
345
  {"const64", 8, 64, 0, 1},      /* 0x25 */
346
  {"reg", 2, 0, 0, 1},            /* 0x26 */
347
  {"end", 0, 0, 0, 0},              /* 0x27 */
348
  {"dup", 0, 0, 1, 2},            /* 0x28 */
349
  {"pop", 0, 0, 1, 0},             /* 0x29 */
350
  {"zero_ext", 1, 0, 1, 1},      /* 0x2a */
351
  {"swap", 0, 0, 2, 2},           /* 0x2b */
352
  {"getv", 2, 0, 0, 1},           /* 0x2c */
353
  {"setv", 2, 0, 0, 1},           /* 0x2d */
354
  {"tracev", 2, 0, 0, 1}, /* 0x2e */
355
  {0, 0, 0, 0, 0},           /* 0x2f */
356
  {"trace16", 2, 0, 1, 1},       /* 0x30 */
357
};
358
 
359
 
360
/* Disassemble the expression EXPR, writing to F.  */
361
void
362
ax_print (struct ui_file *f, struct agent_expr *x)
363
{
364
  int i;
365
  int is_float = 0;
366
 
367
  fprintf_filtered (f, _("Scope: %s\n"), paddress (x->gdbarch, x->scope));
368
  fprintf_filtered (f, _("Reg mask:"));
369
  for (i = 0; i < x->reg_mask_len; ++i)
370
    fprintf_filtered (f, _(" %02x"), x->reg_mask[i]);
371
  fprintf_filtered (f, _("\n"));
372
 
373
  /* Check the size of the name array against the number of entries in
374
     the enum, to catch additions that people didn't sync.  */
375
  if ((sizeof (aop_map) / sizeof (aop_map[0]))
376
      != aop_last)
377
    error (_("GDB bug: ax-general.c (ax_print): opcode map out of sync"));
378
 
379
  for (i = 0; i < x->len;)
380
    {
381
      enum agent_op op = x->buf[i];
382
 
383
      if (op >= (sizeof (aop_map) / sizeof (aop_map[0]))
384
          || !aop_map[op].name)
385
        {
386
          fprintf_filtered (f, _("%3d  <bad opcode %02x>\n"), i, op);
387
          i++;
388
          continue;
389
        }
390
      if (i + 1 + aop_map[op].op_size > x->len)
391
        {
392
          fprintf_filtered (f, _("%3d  <incomplete opcode %s>\n"),
393
                            i, aop_map[op].name);
394
          break;
395
        }
396
 
397
      fprintf_filtered (f, "%3d  %s", i, aop_map[op].name);
398
      if (aop_map[op].op_size > 0)
399
        {
400
          fputs_filtered (" ", f);
401
 
402
          print_longest (f, 'd', 0,
403
                         read_const (x, i + 1, aop_map[op].op_size));
404
        }
405
      fprintf_filtered (f, "\n");
406
      i += 1 + aop_map[op].op_size;
407
 
408
      is_float = (op == aop_float);
409
    }
410
}
411
 
412
/* Add register REG to the register mask for expression AX.  */
413
void
414
ax_reg_mask (struct agent_expr *ax, int reg)
415
{
416
  int byte = reg / 8;
417
 
418
  /* Grow the bit mask if necessary.  */
419
  if (byte >= ax->reg_mask_len)
420
    {
421
      /* It's not appropriate to double here.  This isn't a
422
         string buffer.  */
423
      int new_len = byte + 1;
424
      unsigned char *new_reg_mask = xrealloc (ax->reg_mask,
425
                                              new_len * sizeof (ax->reg_mask[0]));
426
      memset (new_reg_mask + ax->reg_mask_len, 0,
427
              (new_len - ax->reg_mask_len) * sizeof (ax->reg_mask[0]));
428
      ax->reg_mask_len = new_len;
429
      ax->reg_mask = new_reg_mask;
430
    }
431
 
432
  ax->reg_mask[byte] |= 1 << (reg % 8);
433
}
434
 
435
/* Given an agent expression AX, fill in requirements and other descriptive
436
   bits.  */
437
void
438
ax_reqs (struct agent_expr *ax)
439
{
440
  int i;
441
  int height;
442
 
443
  /* Jump target table.  targets[i] is non-zero iff we have found a
444
     jump to offset i.  */
445
  char *targets = (char *) alloca (ax->len * sizeof (targets[0]));
446
 
447
  /* Instruction boundary table.  boundary[i] is non-zero iff our scan
448
     has reached an instruction starting at offset i.  */
449
  char *boundary = (char *) alloca (ax->len * sizeof (boundary[0]));
450
 
451
  /* Stack height record.  If either targets[i] or boundary[i] is
452
     non-zero, heights[i] is the height the stack should have before
453
     executing the bytecode at that point.  */
454
  int *heights = (int *) alloca (ax->len * sizeof (heights[0]));
455
 
456
  /* Pointer to a description of the present op.  */
457
  struct aop_map *op;
458
 
459
  memset (targets, 0, ax->len * sizeof (targets[0]));
460
  memset (boundary, 0, ax->len * sizeof (boundary[0]));
461
 
462
  ax->max_height = ax->min_height = height = 0;
463
  ax->flaw = agent_flaw_none;
464
  ax->max_data_size = 0;
465
 
466
  for (i = 0; i < ax->len; i += 1 + op->op_size)
467
    {
468
      if (ax->buf[i] > (sizeof (aop_map) / sizeof (aop_map[0])))
469
        {
470
          ax->flaw = agent_flaw_bad_instruction;
471
          return;
472
        }
473
 
474
      op = &aop_map[ax->buf[i]];
475
 
476
      if (!op->name)
477
        {
478
          ax->flaw = agent_flaw_bad_instruction;
479
          return;
480
        }
481
 
482
      if (i + 1 + op->op_size > ax->len)
483
        {
484
          ax->flaw = agent_flaw_incomplete_instruction;
485
          return;
486
        }
487
 
488
      /* If this instruction is a forward jump target, does the
489
         current stack height match the stack height at the jump
490
         source?  */
491
      if (targets[i] && (heights[i] != height))
492
        {
493
          ax->flaw = agent_flaw_height_mismatch;
494
          return;
495
        }
496
 
497
      boundary[i] = 1;
498
      heights[i] = height;
499
 
500
      height -= op->consumed;
501
      if (height < ax->min_height)
502
        ax->min_height = height;
503
      height += op->produced;
504
      if (height > ax->max_height)
505
        ax->max_height = height;
506
 
507
      if (op->data_size > ax->max_data_size)
508
        ax->max_data_size = op->data_size;
509
 
510
      /* For jump instructions, check that the target is a valid
511
         offset.  If it is, record the fact that that location is a
512
         jump target, and record the height we expect there.  */
513
      if (aop_goto == op - aop_map
514
          || aop_if_goto == op - aop_map)
515
        {
516
          int target = read_const (ax, i + 1, 2);
517
          if (target < 0 || target >= ax->len)
518
            {
519
              ax->flaw = agent_flaw_bad_jump;
520
              return;
521
            }
522
 
523
          /* Do we have any information about what the stack height
524
             should be at the target?  */
525
          if (targets[target] || boundary[target])
526
            {
527
              if (heights[target] != height)
528
                {
529
                  ax->flaw = agent_flaw_height_mismatch;
530
                  return;
531
                }
532
            }
533
 
534
          /* Record the target, along with the stack height we expect.  */
535
          targets[target] = 1;
536
          heights[target] = height;
537
        }
538
 
539
      /* For unconditional jumps with a successor, check that the
540
         successor is a target, and pick up its stack height.  */
541
      if (aop_goto == op - aop_map
542
          && i + 3 < ax->len)
543
        {
544
          if (!targets[i + 3])
545
            {
546
              ax->flaw = agent_flaw_hole;
547
              return;
548
            }
549
 
550
          height = heights[i + 3];
551
        }
552
 
553
      /* For reg instructions, record the register in the bit mask.  */
554
      if (aop_reg == op - aop_map)
555
        {
556
          int reg = read_const (ax, i + 1, 2);
557
 
558
          ax_reg_mask (ax, reg);
559
        }
560
    }
561
 
562
  /* Check that all the targets are on boundaries.  */
563
  for (i = 0; i < ax->len; i++)
564
    if (targets[i] && !boundary[i])
565
      {
566
        ax->flaw = agent_flaw_bad_jump;
567
        return;
568
      }
569
 
570
  ax->final_height = height;
571
}

powered by: WebSVN 2.1.0

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