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