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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.3/] [gdb/] [ax-general.c] - Blame information for rev 1777

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

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

powered by: WebSVN 2.1.0

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