ee550c6d06e4111308407ee5b2eef2ff7bb675ce
[deliverable/binutils-gdb.git] / gdb / i387-tdep.c
1 /* Intel 387 floating point stuff.
2
3 Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1998, 1999, 2000,
4 2001, 2002, 2003 Free Software Foundation, Inc.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
22
23 #include "defs.h"
24 #include "frame.h"
25 #include "inferior.h"
26 #include "language.h"
27 #include "value.h"
28 #include "gdbcore.h"
29 #include "floatformat.h"
30 #include "regcache.h"
31 #include "gdb_assert.h"
32 #include "gdb_string.h"
33 #include "doublest.h"
34
35 #include "i386-tdep.h"
36 #include "i387-tdep.h"
37
38 /* Implement the `info float' layout based on the register definitions
39 in `tm-i386.h'. */
40
41 /* Print the floating point number specified by RAW. */
42 static void
43 print_i387_value (char *raw, struct ui_file *file)
44 {
45 DOUBLEST value;
46
47 /* Using extract_typed_floating here might affect the representation
48 of certain numbers such as NaNs, even if GDB is running natively.
49 This is fine since our caller already detects such special
50 numbers and we print the hexadecimal representation anyway. */
51 value = extract_typed_floating (raw, builtin_type_i387_ext);
52
53 /* We try to print 19 digits. The last digit may or may not contain
54 garbage, but we'd better print one too many. We need enough room
55 to print the value, 1 position for the sign, 1 for the decimal
56 point, 19 for the digits and 6 for the exponent adds up to 27. */
57 #ifdef PRINTF_HAS_LONG_DOUBLE
58 fprintf_filtered (file, " %-+27.19Lg", (long double) value);
59 #else
60 fprintf_filtered (file, " %-+27.19g", (double) value);
61 #endif
62 }
63
64 /* Print the classification for the register contents RAW. */
65 static void
66 print_i387_ext (unsigned char *raw, struct ui_file *file)
67 {
68 int sign;
69 int integer;
70 unsigned int exponent;
71 unsigned long fraction[2];
72
73 sign = raw[9] & 0x80;
74 integer = raw[7] & 0x80;
75 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
76 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
77 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
78 | (raw[5] << 8) | raw[4]);
79
80 if (exponent == 0x7fff && integer)
81 {
82 if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
83 /* Infinity. */
84 fprintf_filtered (file, " %cInf", (sign ? '-' : '+'));
85 else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
86 /* Real Indefinite (QNaN). */
87 fputs_unfiltered (" Real Indefinite (QNaN)", file);
88 else if (fraction[1] & 0x40000000)
89 /* QNaN. */
90 fputs_filtered (" QNaN", file);
91 else
92 /* SNaN. */
93 fputs_filtered (" SNaN", file);
94 }
95 else if (exponent < 0x7fff && exponent > 0x0000 && integer)
96 /* Normal. */
97 print_i387_value (raw, file);
98 else if (exponent == 0x0000)
99 {
100 /* Denormal or zero. */
101 print_i387_value (raw, file);
102
103 if (integer)
104 /* Pseudo-denormal. */
105 fputs_filtered (" Pseudo-denormal", file);
106 else if (fraction[0] || fraction[1])
107 /* Denormal. */
108 fputs_filtered (" Denormal", file);
109 }
110 else
111 /* Unsupported. */
112 fputs_filtered (" Unsupported", file);
113 }
114
115 /* Print the status word STATUS. */
116 static void
117 print_i387_status_word (unsigned int status, struct ui_file *file)
118 {
119 fprintf_filtered (file, "Status Word: %s",
120 local_hex_string_custom (status, "04"));
121 fputs_filtered (" ", file);
122 fprintf_filtered (file, " %s", (status & 0x0001) ? "IE" : " ");
123 fprintf_filtered (file, " %s", (status & 0x0002) ? "DE" : " ");
124 fprintf_filtered (file, " %s", (status & 0x0004) ? "ZE" : " ");
125 fprintf_filtered (file, " %s", (status & 0x0008) ? "OE" : " ");
126 fprintf_filtered (file, " %s", (status & 0x0010) ? "UE" : " ");
127 fprintf_filtered (file, " %s", (status & 0x0020) ? "PE" : " ");
128 fputs_filtered (" ", file);
129 fprintf_filtered (file, " %s", (status & 0x0080) ? "ES" : " ");
130 fputs_filtered (" ", file);
131 fprintf_filtered (file, " %s", (status & 0x0040) ? "SF" : " ");
132 fputs_filtered (" ", file);
133 fprintf_filtered (file, " %s", (status & 0x0100) ? "C0" : " ");
134 fprintf_filtered (file, " %s", (status & 0x0200) ? "C1" : " ");
135 fprintf_filtered (file, " %s", (status & 0x0400) ? "C2" : " ");
136 fprintf_filtered (file, " %s", (status & 0x4000) ? "C3" : " ");
137
138 fputs_filtered ("\n", file);
139
140 fprintf_filtered (file,
141 " TOP: %d\n", ((status >> 11) & 7));
142 }
143
144 /* Print the control word CONTROL. */
145 static void
146 print_i387_control_word (unsigned int control, struct ui_file *file)
147 {
148 fprintf_filtered (file, "Control Word: %s",
149 local_hex_string_custom (control, "04"));
150 fputs_filtered (" ", file);
151 fprintf_filtered (file, " %s", (control & 0x0001) ? "IM" : " ");
152 fprintf_filtered (file, " %s", (control & 0x0002) ? "DM" : " ");
153 fprintf_filtered (file, " %s", (control & 0x0004) ? "ZM" : " ");
154 fprintf_filtered (file, " %s", (control & 0x0008) ? "OM" : " ");
155 fprintf_filtered (file, " %s", (control & 0x0010) ? "UM" : " ");
156 fprintf_filtered (file, " %s", (control & 0x0020) ? "PM" : " ");
157
158 fputs_filtered ("\n", file);
159
160 fputs_filtered (" PC: ", file);
161 switch ((control >> 8) & 3)
162 {
163 case 0:
164 fputs_filtered ("Single Precision (24-bits)\n", file);
165 break;
166 case 1:
167 fputs_filtered ("Reserved\n", file);
168 break;
169 case 2:
170 fputs_filtered ("Double Precision (53-bits)\n", file);
171 break;
172 case 3:
173 fputs_filtered ("Extended Precision (64-bits)\n", file);
174 break;
175 }
176
177 fputs_filtered (" RC: ", file);
178 switch ((control >> 10) & 3)
179 {
180 case 0:
181 fputs_filtered ("Round to nearest\n", file);
182 break;
183 case 1:
184 fputs_filtered ("Round down\n", file);
185 break;
186 case 2:
187 fputs_filtered ("Round up\n", file);
188 break;
189 case 3:
190 fputs_filtered ("Round toward zero\n", file);
191 break;
192 }
193 }
194
195 /* Print out the i387 floating point state. Note that we ignore FRAME
196 in the code below. That's OK since floating-point registers are
197 never saved on the stack. */
198
199 void
200 i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
201 struct frame_info *frame, const char *args)
202 {
203 char buf[4];
204 ULONGEST fctrl;
205 ULONGEST fstat;
206 ULONGEST ftag;
207 ULONGEST fiseg;
208 ULONGEST fioff;
209 ULONGEST foseg;
210 ULONGEST fooff;
211 ULONGEST fop;
212 int fpreg;
213 int top;
214
215 frame_register_read (frame, FCTRL_REGNUM, buf);
216 fctrl = extract_unsigned_integer (buf, 4);
217 frame_register_read (frame, FSTAT_REGNUM, buf);
218 fstat = extract_unsigned_integer (buf, 4);
219 frame_register_read (frame, FTAG_REGNUM, buf);
220 ftag = extract_unsigned_integer (buf, 4);
221 frame_register_read (frame, FISEG_REGNUM, buf);
222 fiseg = extract_unsigned_integer (buf, 4);
223 frame_register_read (frame, FIOFF_REGNUM, buf);
224 fioff = extract_unsigned_integer (buf, 4);
225 frame_register_read (frame, FOSEG_REGNUM, buf);
226 foseg = extract_unsigned_integer (buf, 4);
227 frame_register_read (frame, FOOFF_REGNUM, buf);
228 fooff = extract_unsigned_integer (buf, 4);
229 frame_register_read (frame, FOP_REGNUM, buf);
230 fop = extract_unsigned_integer (buf, 4);
231
232 top = ((fstat >> 11) & 7);
233
234 for (fpreg = 7; fpreg >= 0; fpreg--)
235 {
236 unsigned char raw[FPU_REG_RAW_SIZE];
237 int tag = (ftag >> (fpreg * 2)) & 3;
238 int i;
239
240 fprintf_filtered (file, "%sR%d: ", fpreg == top ? "=>" : " ", fpreg);
241
242 switch (tag)
243 {
244 case 0:
245 fputs_filtered ("Valid ", file);
246 break;
247 case 1:
248 fputs_filtered ("Zero ", file);
249 break;
250 case 2:
251 fputs_filtered ("Special ", file);
252 break;
253 case 3:
254 fputs_filtered ("Empty ", file);
255 break;
256 }
257
258 frame_register_read (frame, (fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
259
260 fputs_filtered ("0x", file);
261 for (i = 9; i >= 0; i--)
262 fprintf_filtered (file, "%02x", raw[i]);
263
264 if (tag != 3)
265 print_i387_ext (raw, file);
266
267 fputs_filtered ("\n", file);
268 }
269
270 fputs_filtered ("\n", file);
271
272 print_i387_status_word (fstat, file);
273 print_i387_control_word (fctrl, file);
274 fprintf_filtered (file, "Tag Word: %s\n",
275 local_hex_string_custom (ftag, "04"));
276 fprintf_filtered (file, "Instruction Pointer: %s:",
277 local_hex_string_custom (fiseg, "02"));
278 fprintf_filtered (file, "%s\n", local_hex_string_custom (fioff, "08"));
279 fprintf_filtered (file, "Operand Pointer: %s:",
280 local_hex_string_custom (foseg, "02"));
281 fprintf_filtered (file, "%s\n", local_hex_string_custom (fooff, "08"));
282 fprintf_filtered (file, "Opcode: %s\n",
283 local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
284 }
285 \f
286
287 /* Read a value of type TYPE from register REGNUM in frame FRAME, and
288 return its contents in TO. */
289
290 void
291 i387_register_to_value (struct frame_info *frame, int regnum,
292 struct type *type, void *to)
293 {
294 char from[I386_MAX_REGISTER_SIZE];
295
296 gdb_assert (i386_fp_regnum_p (regnum));
297
298 /* We only support floating-point values. */
299 if (TYPE_CODE (type) != TYPE_CODE_FLT)
300 {
301 warning ("Cannot convert floating-point register value "
302 "to non-floating-point type.");
303 return;
304 }
305
306 /* Convert to TYPE. This should be a no-op if TYPE is equivalent to
307 the extended floating-point format used by the FPU. */
308 frame_read_register (frame, regnum, from);
309 convert_typed_floating (from, builtin_type_i387_ext, to, type);
310 }
311
312 /* Write the contents FROM of a value of type TYPE into register
313 REGNUM in frame FRAME. */
314
315 void
316 i387_value_to_register (struct frame_info *frame, int regnum,
317 struct type *type, const void *from)
318 {
319 char to[I386_MAX_REGISTER_SIZE];
320
321 gdb_assert (i386_fp_regnum_p (regnum));
322
323 /* We only support floating-point values. */
324 if (TYPE_CODE (type) != TYPE_CODE_FLT)
325 {
326 warning ("Cannot convert non-floating-point type "
327 "to floating-point register value.");
328 return;
329 }
330
331 /* Convert from TYPE. This should be a no-op if TYPE is equivalent
332 to the extended floating-point format used by the FPU. */
333 convert_typed_floating (from, type, to, builtin_type_i387_ext);
334 put_frame_register (frame, regnum, to);
335 }
336 \f
337
338 /* FIXME: kettenis/2000-05-21: Right now more than a few i386 targets
339 define their own routines to manage the floating-point registers in
340 GDB's register array. Most (if not all) of these targets use the
341 format used by the "fsave" instruction in their communication with
342 the OS. They should all be converted to use the routines below. */
343
344 /* At fsave_offset[REGNUM] you'll find the offset to the location in
345 the data structure used by the "fsave" instruction where GDB
346 register REGNUM is stored. */
347
348 static int fsave_offset[] =
349 {
350 28 + 0 * FPU_REG_RAW_SIZE, /* FP0_REGNUM through ... */
351 28 + 1 * FPU_REG_RAW_SIZE,
352 28 + 2 * FPU_REG_RAW_SIZE,
353 28 + 3 * FPU_REG_RAW_SIZE,
354 28 + 4 * FPU_REG_RAW_SIZE,
355 28 + 5 * FPU_REG_RAW_SIZE,
356 28 + 6 * FPU_REG_RAW_SIZE,
357 28 + 7 * FPU_REG_RAW_SIZE, /* ... FP7_REGNUM. */
358 0, /* FCTRL_REGNUM (16 bits). */
359 4, /* FSTAT_REGNUM (16 bits). */
360 8, /* FTAG_REGNUM (16 bits). */
361 16, /* FISEG_REGNUM (16 bits). */
362 12, /* FIOFF_REGNUM. */
363 24, /* FOSEG_REGNUM. */
364 20, /* FOOFF_REGNUM. */
365 18 /* FOP_REGNUM (bottom 11 bits). */
366 };
367
368 #define FSAVE_ADDR(fsave, regnum) (fsave + fsave_offset[regnum - FP0_REGNUM])
369 \f
370
371 /* Fill register REGNUM in GDB's register array with the appropriate
372 value from *FSAVE. This function masks off any of the reserved
373 bits in *FSAVE. */
374
375 void
376 i387_supply_register (int regnum, char *fsave)
377 {
378 if (fsave == NULL)
379 {
380 supply_register (regnum, NULL);
381 return;
382 }
383
384 /* Most of the FPU control registers occupy only 16 bits in
385 the fsave area. Give those a special treatment. */
386 if (regnum >= FPC_REGNUM
387 && regnum != FIOFF_REGNUM && regnum != FOOFF_REGNUM)
388 {
389 unsigned char val[4];
390
391 memcpy (val, FSAVE_ADDR (fsave, regnum), 2);
392 val[2] = val[3] = 0;
393 if (regnum == FOP_REGNUM)
394 val[1] &= ((1 << 3) - 1);
395 supply_register (regnum, val);
396 }
397 else
398 supply_register (regnum, FSAVE_ADDR (fsave, regnum));
399 }
400
401 /* Fill GDB's register array with the floating-point register values
402 in *FSAVE. This function masks off any of the reserved
403 bits in *FSAVE. */
404
405 void
406 i387_supply_fsave (char *fsave)
407 {
408 int i;
409
410 for (i = FP0_REGNUM; i < XMM0_REGNUM; i++)
411 i387_supply_register (i, fsave);
412 }
413
414 /* Fill register REGNUM (if it is a floating-point register) in *FSAVE
415 with the value in GDB's register array. If REGNUM is -1, do this
416 for all registers. This function doesn't touch any of the reserved
417 bits in *FSAVE. */
418
419 void
420 i387_fill_fsave (char *fsave, int regnum)
421 {
422 int i;
423
424 for (i = FP0_REGNUM; i < XMM0_REGNUM; i++)
425 if (regnum == -1 || regnum == i)
426 {
427 /* Most of the FPU control registers occupy only 16 bits in
428 the fsave area. Give those a special treatment. */
429 if (i >= FPC_REGNUM
430 && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
431 {
432 unsigned char buf[4];
433
434 regcache_collect (i, buf);
435
436 if (i == FOP_REGNUM)
437 {
438 /* The opcode occupies only 11 bits. Make sure we
439 don't touch the other bits. */
440 buf[1] &= ((1 << 3) - 1);
441 buf[1] |= ((FSAVE_ADDR (fsave, i))[1] & ~((1 << 3) - 1));
442 }
443 memcpy (FSAVE_ADDR (fsave, i), buf, 2);
444 }
445 else
446 regcache_collect (i, FSAVE_ADDR (fsave, i));
447 }
448 }
449 \f
450
451 /* At fxsave_offset[REGNUM] you'll find the offset to the location in
452 the data structure used by the "fxsave" instruction where GDB
453 register REGNUM is stored. */
454
455 static int fxsave_offset[] =
456 {
457 32, /* FP0_REGNUM through ... */
458 48,
459 64,
460 80,
461 96,
462 112,
463 128,
464 144, /* ... FP7_REGNUM (80 bits each). */
465 0, /* FCTRL_REGNUM (16 bits). */
466 2, /* FSTAT_REGNUM (16 bits). */
467 4, /* FTAG_REGNUM (16 bits). */
468 12, /* FISEG_REGNUM (16 bits). */
469 8, /* FIOFF_REGNUM. */
470 20, /* FOSEG_REGNUM (16 bits). */
471 16, /* FOOFF_REGNUM. */
472 6, /* FOP_REGNUM (bottom 11 bits). */
473 160 + 0 * 16, /* XMM0_REGNUM through ... */
474 160 + 1 * 16,
475 160 + 2 * 16,
476 160 + 3 * 16,
477 160 + 4 * 16,
478 160 + 5 * 16,
479 160 + 6 * 16,
480 160 + 7 * 16,
481 160 + 8 * 16,
482 160 + 9 * 16,
483 160 + 10 * 16,
484 160 + 11 * 16,
485 160 + 12 * 16,
486 160 + 13 * 16,
487 160 + 14 * 16,
488 160 + 15 * 16, /* ... XMM15_REGNUM (128 bits each). */
489 24 /* MXCSR_REGNUM. */
490 };
491
492 /* FIXME: kettenis/20030430: We made an unfortunate choice in putting
493 %mxcsr after the SSE registers %xmm0-%xmm7 instead of before, since
494 it makes supporting the registers %xmm8-%xmm15 on x86-64 a bit
495 involved. Hack around it by explicitly overriding the offset for
496 %mxcsr here. */
497
498 #define FXSAVE_ADDR(fxsave, regnum) \
499 ((regnum == MXCSR_REGNUM) ? (fxsave + 24) : \
500 (fxsave + fxsave_offset[regnum - FP0_REGNUM]))
501
502 static int i387_tag (unsigned char *raw);
503 \f
504
505 /* Fill GDB's register array with the floating-point and SSE register
506 values in *FXSAVE. This function masks off any of the reserved
507 bits in *FXSAVE. */
508
509 void
510 i387_supply_fxsave (char *fxsave)
511 {
512 int i, last_regnum = MXCSR_REGNUM;
513
514 if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
515 last_regnum = FOP_REGNUM;
516
517 for (i = FP0_REGNUM; i <= last_regnum; i++)
518 {
519 if (fxsave == NULL)
520 {
521 supply_register (i, NULL);
522 continue;
523 }
524
525 /* Most of the FPU control registers occupy only 16 bits in
526 the fxsave area. Give those a special treatment. */
527 if (i >= FPC_REGNUM && i < XMM0_REGNUM
528 && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
529 {
530 unsigned char val[4];
531
532 memcpy (val, FXSAVE_ADDR (fxsave, i), 2);
533 val[2] = val[3] = 0;
534 if (i == FOP_REGNUM)
535 val[1] &= ((1 << 3) - 1);
536 else if (i== FTAG_REGNUM)
537 {
538 /* The fxsave area contains a simplified version of the
539 tag word. We have to look at the actual 80-bit FP
540 data to recreate the traditional i387 tag word. */
541
542 unsigned long ftag = 0;
543 int fpreg;
544 int top;
545
546 top = (((FXSAVE_ADDR (fxsave, FSTAT_REGNUM))[1] >> 3) & 0x7);
547
548 for (fpreg = 7; fpreg >= 0; fpreg--)
549 {
550 int tag;
551
552 if (val[0] & (1 << fpreg))
553 {
554 int regnum = (fpreg + 8 - top) % 8 + FP0_REGNUM;
555 tag = i387_tag (FXSAVE_ADDR (fxsave, regnum));
556 }
557 else
558 tag = 3; /* Empty */
559
560 ftag |= tag << (2 * fpreg);
561 }
562 val[0] = ftag & 0xff;
563 val[1] = (ftag >> 8) & 0xff;
564 }
565 supply_register (i, val);
566 }
567 else
568 supply_register (i, FXSAVE_ADDR (fxsave, i));
569 }
570 }
571
572 /* Fill register REGNUM (if it is a floating-point or SSE register) in
573 *FXSAVE with the value in GDB's register array. If REGNUM is -1, do
574 this for all registers. This function doesn't touch any of the
575 reserved bits in *FXSAVE. */
576
577 void
578 i387_fill_fxsave (char *fxsave, int regnum)
579 {
580 int i, last_regnum = MXCSR_REGNUM;
581
582 if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
583 last_regnum = FOP_REGNUM;
584
585 for (i = FP0_REGNUM; i <= last_regnum; i++)
586 if (regnum == -1 || regnum == i)
587 {
588 /* Most of the FPU control registers occupy only 16 bits in
589 the fxsave area. Give those a special treatment. */
590 if (i >= FPC_REGNUM && i < XMM0_REGNUM
591 && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
592 {
593 unsigned char buf[4];
594
595 regcache_collect (i, buf);
596
597 if (i == FOP_REGNUM)
598 {
599 /* The opcode occupies only 11 bits. Make sure we
600 don't touch the other bits. */
601 buf[1] &= ((1 << 3) - 1);
602 buf[1] |= ((FXSAVE_ADDR (fxsave, i))[1] & ~((1 << 3) - 1));
603 }
604 else if (i == FTAG_REGNUM)
605 {
606 /* Converting back is much easier. */
607
608 unsigned short ftag;
609 int fpreg;
610
611 ftag = (buf[1] << 8) | buf[0];
612 buf[0] = 0;
613 buf[1] = 0;
614
615 for (fpreg = 7; fpreg >= 0; fpreg--)
616 {
617 int tag = (ftag >> (fpreg * 2)) & 3;
618
619 if (tag != 3)
620 buf[0] |= (1 << fpreg);
621 }
622 }
623 memcpy (FXSAVE_ADDR (fxsave, i), buf, 2);
624 }
625 else
626 regcache_collect (i, FXSAVE_ADDR (fxsave, i));
627 }
628 }
629
630 /* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
631 *RAW. */
632
633 static int
634 i387_tag (unsigned char *raw)
635 {
636 int integer;
637 unsigned int exponent;
638 unsigned long fraction[2];
639
640 integer = raw[7] & 0x80;
641 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
642 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
643 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
644 | (raw[5] << 8) | raw[4]);
645
646 if (exponent == 0x7fff)
647 {
648 /* Special. */
649 return (2);
650 }
651 else if (exponent == 0x0000)
652 {
653 if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
654 {
655 /* Zero. */
656 return (1);
657 }
658 else
659 {
660 /* Special. */
661 return (2);
662 }
663 }
664 else
665 {
666 if (integer)
667 {
668 /* Valid. */
669 return (0);
670 }
671 else
672 {
673 /* Special. */
674 return (2);
675 }
676 }
677 }
This page took 0.047797 seconds and 4 git commands to generate.