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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [ax-general.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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