2011-01-05 Michael Snyder <msnyder@vmware.com>
[deliverable/binutils-gdb.git] / gdb / ax-general.c
CommitLineData
c906108c 1/* Functions for manipulating expressions designed to be executed on the agent
7b6bb8da 2 Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009, 2010, 2011
0fb0cc75 3 Free Software Foundation, Inc.
c906108c 4
c5aa993b 5 This file is part of GDB.
c906108c 6
c5aa993b
JM
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
c5aa993b 10 (at your option) any later version.
c906108c 11
c5aa993b
JM
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
c906108c 16
c5aa993b 17 You should have received a copy of the GNU General Public License
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c 19
c906108c
SS
20/* Despite what the above comment says about this file being part of
21 GDB, we would like to keep these functions free of GDB
22 dependencies, since we want to be able to use them in contexts
23 outside of GDB (test suites, the stub, etc.) */
24
25#include "defs.h"
26#include "ax.h"
27
7a292a7a 28#include "value.h"
b66d6d2e 29#include "gdb_string.h"
7a292a7a 30
175ff332
HZ
31#include "user-regs.h"
32
a14ed312 33static void grow_expr (struct agent_expr *x, int n);
392a587b 34
a14ed312 35static void append_const (struct agent_expr *x, LONGEST val, int n);
392a587b 36
a14ed312 37static LONGEST read_const (struct agent_expr *x, int o, int n);
392a587b 38
a14ed312 39static void generic_ext (struct agent_expr *x, enum agent_op op, int n);
c906108c
SS
40\f
41/* Functions for building expressions. */
42
43/* Allocate a new, empty agent expression. */
44struct agent_expr *
35c9c7ba 45new_agent_expr (struct gdbarch *gdbarch, CORE_ADDR scope)
c906108c
SS
46{
47 struct agent_expr *x = xmalloc (sizeof (*x));
35c9c7ba 48
c5aa993b 49 x->len = 0;
c906108c
SS
50 x->size = 1; /* Change this to a larger value once
51 reallocation code is tested. */
c5aa993b 52 x->buf = xmalloc (x->size);
35c9c7ba
SS
53
54 x->gdbarch = gdbarch;
c906108c
SS
55 x->scope = scope;
56
35c9c7ba
SS
57 /* Bit vector for registers used. */
58 x->reg_mask_len = 1;
59 x->reg_mask = xmalloc (x->reg_mask_len * sizeof (x->reg_mask[0]));
60 memset (x->reg_mask, 0, x->reg_mask_len * sizeof (x->reg_mask[0]));
61
c906108c
SS
62 return x;
63}
64
65/* Free a agent expression. */
66void
fba45db2 67free_agent_expr (struct agent_expr *x)
c906108c 68{
b8c9b27d 69 xfree (x->buf);
35c9c7ba 70 xfree (x->reg_mask);
b8c9b27d 71 xfree (x);
c906108c
SS
72}
73
f23d52e0
AC
74static void
75do_free_agent_expr_cleanup (void *x)
76{
77 free_agent_expr (x);
78}
79
80struct cleanup *
81make_cleanup_free_agent_expr (struct agent_expr *x)
82{
83 return make_cleanup (do_free_agent_expr_cleanup, x);
84}
85
c906108c
SS
86
87/* Make sure that X has room for at least N more bytes. This doesn't
88 affect the length, just the allocated size. */
89static void
fba45db2 90grow_expr (struct agent_expr *x, int n)
c906108c
SS
91{
92 if (x->len + n > x->size)
93 {
94 x->size *= 2;
95 if (x->size < x->len + n)
96 x->size = x->len + n + 10;
97 x->buf = xrealloc (x->buf, x->size);
98 }
99}
100
101
102/* Append the low N bytes of VAL as an N-byte integer to the
103 expression X, in big-endian order. */
104static void
fba45db2 105append_const (struct agent_expr *x, LONGEST val, int n)
c906108c
SS
106{
107 int i;
108
109 grow_expr (x, n);
110 for (i = n - 1; i >= 0; i--)
111 {
112 x->buf[x->len + i] = val & 0xff;
113 val >>= 8;
114 }
115 x->len += n;
116}
117
118
119/* Extract an N-byte big-endian unsigned integer from expression X at
120 offset O. */
121static LONGEST
fba45db2 122read_const (struct agent_expr *x, int o, int n)
c906108c
SS
123{
124 int i;
125 LONGEST accum = 0;
126
127 /* Make sure we're not reading off the end of the expression. */
128 if (o + n > x->len)
3d263c1d 129 error (_("GDB bug: ax-general.c (read_const): incomplete constant"));
c906108c
SS
130
131 for (i = 0; i < n; i++)
132 accum = (accum << 8) | x->buf[o + i];
c5aa993b 133
c906108c
SS
134 return accum;
135}
136
137
138/* Append a simple operator OP to EXPR. */
139void
fba45db2 140ax_simple (struct agent_expr *x, enum agent_op op)
c906108c
SS
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. */
149static void
fba45db2 150generic_ext (struct agent_expr *x, enum agent_op op, int n)
c906108c
SS
151{
152 /* N must fit in a byte. */
153 if (n < 0 || n > 255)
3d263c1d 154 error (_("GDB bug: ax-general.c (generic_ext): bit count out of range"));
c906108c
SS
155 /* That had better be enough range. */
156 if (sizeof (LONGEST) * 8 > 255)
3e43a32a
MS
157 error (_("GDB bug: ax-general.c (generic_ext): "
158 "opcode has inadequate range"));
c906108c
SS
159
160 grow_expr (x, 2);
161 x->buf[x->len++] = op;
162 x->buf[x->len++] = n;
163}
164
165
166/* Append a sign-extension instruction to EXPR, to extend an N-bit value. */
167void
fba45db2 168ax_ext (struct agent_expr *x, int n)
c906108c
SS
169{
170 generic_ext (x, aop_ext, n);
171}
172
173
174/* Append a zero-extension instruction to EXPR, to extend an N-bit value. */
175void
fba45db2 176ax_zero_ext (struct agent_expr *x, int n)
c906108c
SS
177{
178 generic_ext (x, aop_zero_ext, n);
179}
180
181
182/* Append a trace_quick instruction to EXPR, to record N bytes. */
183void
fba45db2 184ax_trace_quick (struct agent_expr *x, int n)
c906108c
SS
185{
186 /* N must fit in a byte. */
187 if (n < 0 || n > 255)
3e43a32a
MS
188 error (_("GDB bug: ax-general.c (ax_trace_quick): "
189 "size out of range for trace_quick"));
c906108c
SS
190
191 grow_expr (x, 2);
192 x->buf[x->len++] = aop_trace_quick;
193 x->buf[x->len++] = n;
194}
195
196
197/* Append a goto op to EXPR. OP is the actual op (must be aop_goto or
198 aop_if_goto). We assume we don't know the target offset yet,
199 because it's probably a forward branch, so we leave space in EXPR
200 for the target, and return the offset in EXPR of that space, so we
201 can backpatch it once we do know the target offset. Use ax_label
202 to do the backpatching. */
c5aa993b 203int
fba45db2 204ax_goto (struct agent_expr *x, enum agent_op op)
c906108c
SS
205{
206 grow_expr (x, 3);
207 x->buf[x->len + 0] = op;
208 x->buf[x->len + 1] = 0xff;
209 x->buf[x->len + 2] = 0xff;
210 x->len += 3;
211 return x->len - 2;
212}
213
214/* Suppose a given call to ax_goto returns some value PATCH. When you
215 know the offset TARGET that goto should jump to, call
c5aa993b 216 ax_label (EXPR, PATCH, TARGET)
c906108c
SS
217 to patch TARGET into the ax_goto instruction. */
218void
fba45db2 219ax_label (struct agent_expr *x, int patch, int target)
c906108c
SS
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)
3d263c1d 224 error (_("GDB bug: ax-general.c (ax_label): label target out of range"));
c5aa993b 225
c906108c
SS
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. */
232void
fba45db2 233ax_const_l (struct agent_expr *x, LONGEST l)
c906108c
SS
234{
235 static enum agent_op ops[]
c5aa993b
JM
236 =
237 {aop_const8, aop_const16, aop_const32, aop_const64};
c906108c
SS
238 int size;
239 int op;
240
241 /* How big is the number? 'op' keeps track of which opcode to use.
242 Notice that we don't really care whether the original number was
243 signed or unsigned; we always reproduce the value exactly, and
244 use the shortest representation. */
245 for (op = 0, size = 8; size < 64; size *= 2, op++)
44a81774 246 {
cf3e25ca 247 LONGEST lim = ((LONGEST) 1) << (size - 1);
44a81774
JB
248
249 if (-lim <= l && l <= lim - 1)
250 break;
251 }
c906108c 252
0e2de366 253 /* Emit the right opcode... */
c906108c
SS
254 ax_simple (x, ops[op]);
255
256 /* Emit the low SIZE bytes as an unsigned number. We know that
257 sign-extending this will yield l. */
258 append_const (x, l, size / 8);
259
260 /* Now, if it was negative, and not full-sized, sign-extend it. */
261 if (l < 0 && size < 64)
262 ax_ext (x, size);
263}
264
265
266void
fba45db2 267ax_const_d (struct agent_expr *x, LONGEST d)
c906108c
SS
268{
269 /* FIXME: floating-point support not present yet. */
3e43a32a
MS
270 error (_("GDB bug: ax-general.c (ax_const_d): "
271 "floating point not supported yet"));
c906108c
SS
272}
273
274
275/* Assemble code to push the value of register number REG on the
276 stack. */
c5aa993b 277void
fba45db2 278ax_reg (struct agent_expr *x, int reg)
c906108c 279{
175ff332
HZ
280 if (reg >= gdbarch_num_regs (x->gdbarch))
281 {
282 /* This is a pseudo-register. */
283 if (!gdbarch_ax_pseudo_register_push_stack_p (x->gdbarch))
284 error (_("'%s' is a pseudo-register; "
285 "GDB cannot yet trace its contents."),
286 user_reg_map_regnum_to_name (x->gdbarch, reg));
287 if (gdbarch_ax_pseudo_register_push_stack (x->gdbarch, x, reg))
288 error (_("Trace '%s' failed."),
289 user_reg_map_regnum_to_name (x->gdbarch, reg));
290 }
291 else
292 {
293 /* Make sure the register number is in range. */
294 if (reg < 0 || reg > 0xffff)
3e43a32a
MS
295 error (_("GDB bug: ax-general.c (ax_reg): "
296 "register number out of range"));
175ff332
HZ
297 grow_expr (x, 3);
298 x->buf[x->len] = aop_reg;
299 x->buf[x->len + 1] = (reg >> 8) & 0xff;
300 x->buf[x->len + 2] = (reg) & 0xff;
301 x->len += 3;
302 }
c906108c 303}
f61e138d
SS
304
305/* Assemble code to operate on a trace state variable. */
306
307void
308ax_tsv (struct agent_expr *x, enum agent_op op, int num)
309{
310 /* Make sure the tsv number is in range. */
311 if (num < 0 || num > 0xffff)
3e43a32a
MS
312 internal_error (__FILE__, __LINE__,
313 _("ax-general.c (ax_tsv): variable "
314 "number is %d, out of range"), num);
f61e138d
SS
315
316 grow_expr (x, 3);
317 x->buf[x->len] = op;
318 x->buf[x->len + 1] = (num >> 8) & 0xff;
319 x->buf[x->len + 2] = (num) & 0xff;
320 x->len += 3;
321}
c5aa993b 322\f
c906108c
SS
323
324
c906108c
SS
325/* Functions for disassembling agent expressions, and otherwise
326 debugging the expression compiler. */
327
c5aa993b
JM
328struct aop_map aop_map[] =
329{
330 {0, 0, 0, 0, 0},
331 {"float", 0, 0, 0, 0}, /* 0x01 */
332 {"add", 0, 0, 2, 1}, /* 0x02 */
333 {"sub", 0, 0, 2, 1}, /* 0x03 */
334 {"mul", 0, 0, 2, 1}, /* 0x04 */
335 {"div_signed", 0, 0, 2, 1}, /* 0x05 */
336 {"div_unsigned", 0, 0, 2, 1}, /* 0x06 */
337 {"rem_signed", 0, 0, 2, 1}, /* 0x07 */
338 {"rem_unsigned", 0, 0, 2, 1}, /* 0x08 */
339 {"lsh", 0, 0, 2, 1}, /* 0x09 */
340 {"rsh_signed", 0, 0, 2, 1}, /* 0x0a */
341 {"rsh_unsigned", 0, 0, 2, 1}, /* 0x0b */
342 {"trace", 0, 0, 2, 0}, /* 0x0c */
343 {"trace_quick", 1, 0, 1, 1}, /* 0x0d */
344 {"log_not", 0, 0, 1, 1}, /* 0x0e */
345 {"bit_and", 0, 0, 2, 1}, /* 0x0f */
346 {"bit_or", 0, 0, 2, 1}, /* 0x10 */
347 {"bit_xor", 0, 0, 2, 1}, /* 0x11 */
348 {"bit_not", 0, 0, 1, 1}, /* 0x12 */
349 {"equal", 0, 0, 2, 1}, /* 0x13 */
350 {"less_signed", 0, 0, 2, 1}, /* 0x14 */
351 {"less_unsigned", 0, 0, 2, 1}, /* 0x15 */
352 {"ext", 1, 0, 1, 1}, /* 0x16 */
353 {"ref8", 0, 8, 1, 1}, /* 0x17 */
354 {"ref16", 0, 16, 1, 1}, /* 0x18 */
355 {"ref32", 0, 32, 1, 1}, /* 0x19 */
356 {"ref64", 0, 64, 1, 1}, /* 0x1a */
357 {"ref_float", 0, 0, 1, 1}, /* 0x1b */
358 {"ref_double", 0, 0, 1, 1}, /* 0x1c */
359 {"ref_long_double", 0, 0, 1, 1}, /* 0x1d */
360 {"l_to_d", 0, 0, 1, 1}, /* 0x1e */
361 {"d_to_l", 0, 0, 1, 1}, /* 0x1f */
362 {"if_goto", 2, 0, 1, 0}, /* 0x20 */
363 {"goto", 2, 0, 0, 0}, /* 0x21 */
364 {"const8", 1, 8, 0, 1}, /* 0x22 */
365 {"const16", 2, 16, 0, 1}, /* 0x23 */
366 {"const32", 4, 32, 0, 1}, /* 0x24 */
367 {"const64", 8, 64, 0, 1}, /* 0x25 */
368 {"reg", 2, 0, 0, 1}, /* 0x26 */
369 {"end", 0, 0, 0, 0}, /* 0x27 */
370 {"dup", 0, 0, 1, 2}, /* 0x28 */
371 {"pop", 0, 0, 1, 0}, /* 0x29 */
372 {"zero_ext", 1, 0, 1, 1}, /* 0x2a */
373 {"swap", 0, 0, 2, 2}, /* 0x2b */
f61e138d
SS
374 {"getv", 2, 0, 0, 1}, /* 0x2c */
375 {"setv", 2, 0, 0, 1}, /* 0x2d */
376 {"tracev", 2, 0, 0, 1}, /* 0x2e */
c5aa993b
JM
377 {0, 0, 0, 0, 0}, /* 0x2f */
378 {"trace16", 2, 0, 1, 1}, /* 0x30 */
c906108c
SS
379};
380
381
382/* Disassemble the expression EXPR, writing to F. */
383void
fba45db2 384ax_print (struct ui_file *f, struct agent_expr *x)
c906108c
SS
385{
386 int i;
387 int is_float = 0;
388
35c9c7ba
SS
389 fprintf_filtered (f, _("Scope: %s\n"), paddress (x->gdbarch, x->scope));
390 fprintf_filtered (f, _("Reg mask:"));
391 for (i = 0; i < x->reg_mask_len; ++i)
392 fprintf_filtered (f, _(" %02x"), x->reg_mask[i]);
393 fprintf_filtered (f, _("\n"));
394
c906108c
SS
395 /* Check the size of the name array against the number of entries in
396 the enum, to catch additions that people didn't sync. */
397 if ((sizeof (aop_map) / sizeof (aop_map[0]))
398 != aop_last)
3d263c1d 399 error (_("GDB bug: ax-general.c (ax_print): opcode map out of sync"));
c5aa993b
JM
400
401 for (i = 0; i < x->len;)
c906108c
SS
402 {
403 enum agent_op op = x->buf[i];
404
405 if (op >= (sizeof (aop_map) / sizeof (aop_map[0]))
c5aa993b 406 || !aop_map[op].name)
c906108c 407 {
3d263c1d 408 fprintf_filtered (f, _("%3d <bad opcode %02x>\n"), i, op);
c906108c
SS
409 i++;
410 continue;
411 }
412 if (i + 1 + aop_map[op].op_size > x->len)
413 {
3d263c1d 414 fprintf_filtered (f, _("%3d <incomplete opcode %s>\n"),
c906108c
SS
415 i, aop_map[op].name);
416 break;
417 }
418
419 fprintf_filtered (f, "%3d %s", i, aop_map[op].name);
420 if (aop_map[op].op_size > 0)
421 {
422 fputs_filtered (" ", f);
c5aa993b 423
c906108c
SS
424 print_longest (f, 'd', 0,
425 read_const (x, i + 1, aop_map[op].op_size));
426 }
427 fprintf_filtered (f, "\n");
428 i += 1 + aop_map[op].op_size;
429
430 is_float = (op == aop_float);
431 }
432}
433
35c9c7ba
SS
434/* Add register REG to the register mask for expression AX. */
435void
436ax_reg_mask (struct agent_expr *ax, int reg)
437{
175ff332 438 if (reg >= gdbarch_num_regs (ax->gdbarch))
35c9c7ba 439 {
175ff332
HZ
440 /* This is a pseudo-register. */
441 if (!gdbarch_ax_pseudo_register_collect_p (ax->gdbarch))
442 error (_("'%s' is a pseudo-register; "
443 "GDB cannot yet trace its contents."),
444 user_reg_map_regnum_to_name (ax->gdbarch, reg));
445 if (gdbarch_ax_pseudo_register_collect (ax->gdbarch, ax, reg))
446 error (_("Trace '%s' failed."),
447 user_reg_map_regnum_to_name (ax->gdbarch, reg));
448 }
449 else
450 {
451 int byte = reg / 8;
452
453 /* Grow the bit mask if necessary. */
454 if (byte >= ax->reg_mask_len)
455 {
456 /* It's not appropriate to double here. This isn't a
457 string buffer. */
458 int new_len = byte + 1;
459 unsigned char *new_reg_mask = xrealloc (ax->reg_mask,
460 new_len
461 * sizeof (ax->reg_mask[0]));
462 memset (new_reg_mask + ax->reg_mask_len, 0,
463 (new_len - ax->reg_mask_len) * sizeof (ax->reg_mask[0]));
464 ax->reg_mask_len = new_len;
465 ax->reg_mask = new_reg_mask;
466 }
467
468 ax->reg_mask[byte] |= 1 << (reg % 8);
35c9c7ba 469 }
35c9c7ba
SS
470}
471
472/* Given an agent expression AX, fill in requirements and other descriptive
473 bits. */
c906108c 474void
35c9c7ba 475ax_reqs (struct agent_expr *ax)
c906108c
SS
476{
477 int i;
478 int height;
479
3d269a59
JB
480 /* Jump target table. targets[i] is non-zero iff we have found a
481 jump to offset i. */
c906108c
SS
482 char *targets = (char *) alloca (ax->len * sizeof (targets[0]));
483
3d269a59
JB
484 /* Instruction boundary table. boundary[i] is non-zero iff our scan
485 has reached an instruction starting at offset i. */
c906108c
SS
486 char *boundary = (char *) alloca (ax->len * sizeof (boundary[0]));
487
3d269a59 488 /* Stack height record. If either targets[i] or boundary[i] is
c906108c
SS
489 non-zero, heights[i] is the height the stack should have before
490 executing the bytecode at that point. */
491 int *heights = (int *) alloca (ax->len * sizeof (heights[0]));
492
493 /* Pointer to a description of the present op. */
494 struct aop_map *op;
495
c906108c
SS
496 memset (targets, 0, ax->len * sizeof (targets[0]));
497 memset (boundary, 0, ax->len * sizeof (boundary[0]));
498
35c9c7ba
SS
499 ax->max_height = ax->min_height = height = 0;
500 ax->flaw = agent_flaw_none;
501 ax->max_data_size = 0;
c906108c
SS
502
503 for (i = 0; i < ax->len; i += 1 + op->op_size)
504 {
505 if (ax->buf[i] > (sizeof (aop_map) / sizeof (aop_map[0])))
506 {
35c9c7ba 507 ax->flaw = agent_flaw_bad_instruction;
c906108c
SS
508 return;
509 }
510
511 op = &aop_map[ax->buf[i]];
512
c5aa993b 513 if (!op->name)
c906108c 514 {
35c9c7ba 515 ax->flaw = agent_flaw_bad_instruction;
c906108c
SS
516 return;
517 }
c5aa993b 518
c906108c
SS
519 if (i + 1 + op->op_size > ax->len)
520 {
35c9c7ba 521 ax->flaw = agent_flaw_incomplete_instruction;
c906108c
SS
522 return;
523 }
524
3d269a59
JB
525 /* If this instruction is a forward jump target, does the
526 current stack height match the stack height at the jump
527 source? */
c906108c
SS
528 if (targets[i] && (heights[i] != height))
529 {
35c9c7ba 530 ax->flaw = agent_flaw_height_mismatch;
c906108c
SS
531 return;
532 }
533
534 boundary[i] = 1;
535 heights[i] = height;
536
537 height -= op->consumed;
35c9c7ba
SS
538 if (height < ax->min_height)
539 ax->min_height = height;
c906108c 540 height += op->produced;
35c9c7ba
SS
541 if (height > ax->max_height)
542 ax->max_height = height;
c906108c 543
35c9c7ba
SS
544 if (op->data_size > ax->max_data_size)
545 ax->max_data_size = op->data_size;
c906108c
SS
546
547 /* For jump instructions, check that the target is a valid
c5aa993b
JM
548 offset. If it is, record the fact that that location is a
549 jump target, and record the height we expect there. */
c906108c
SS
550 if (aop_goto == op - aop_map
551 || aop_if_goto == op - aop_map)
552 {
553 int target = read_const (ax, i + 1, 2);
554 if (target < 0 || target >= ax->len)
555 {
35c9c7ba 556 ax->flaw = agent_flaw_bad_jump;
c906108c
SS
557 return;
558 }
3d269a59
JB
559
560 /* Do we have any information about what the stack height
561 should be at the target? */
562 if (targets[target] || boundary[target])
c906108c 563 {
3d269a59 564 if (heights[target] != height)
c906108c 565 {
35c9c7ba 566 ax->flaw = agent_flaw_height_mismatch;
c906108c
SS
567 return;
568 }
569 }
3d269a59
JB
570
571 /* Record the target, along with the stack height we expect. */
572 targets[target] = 1;
573 heights[target] = height;
c906108c 574 }
c5aa993b 575
c906108c
SS
576 /* For unconditional jumps with a successor, check that the
577 successor is a target, and pick up its stack height. */
578 if (aop_goto == op - aop_map
579 && i + 3 < ax->len)
580 {
c5aa993b 581 if (!targets[i + 3])
c906108c 582 {
35c9c7ba 583 ax->flaw = agent_flaw_hole;
c906108c
SS
584 return;
585 }
586
587 height = heights[i + 3];
588 }
589
590 /* For reg instructions, record the register in the bit mask. */
591 if (aop_reg == op - aop_map)
592 {
593 int reg = read_const (ax, i + 1, 2);
c906108c 594
35c9c7ba 595 ax_reg_mask (ax, reg);
c906108c
SS
596 }
597 }
598
599 /* Check that all the targets are on boundaries. */
600 for (i = 0; i < ax->len; i++)
601 if (targets[i] && !boundary[i])
602 {
35c9c7ba 603 ax->flaw = agent_flaw_bad_jump;
c906108c
SS
604 return;
605 }
606
35c9c7ba 607 ax->final_height = height;
c906108c 608}
This page took 0.688239 seconds and 4 git commands to generate.