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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-6.8/] [gdb/] [ax-general.c] - Blame information for rev 857

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

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

powered by: WebSVN 2.1.0

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