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 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 \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
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 \f
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      GDB_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 }