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