00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "sysdep.h"
00036 #include <stdio.h>
00037 #include "ansidecl.h"
00038 #include "dis-asm.h"
00039 #include "bfd.h"
00040 #include "symcat.h"
00041 #include "libiberty.h"
00042 #include "m32r-desc.h"
00043 #include "m32r-opc.h"
00044 #include "opintl.h"
00045
00046
00047 #define UNKNOWN_INSN_MSG _("*unknown*")
00048
00049 static void print_normal
00050 (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
00051 static void print_address
00052 (CGEN_CPU_DESC, void *, bfd_vma, unsigned int, bfd_vma, int) ATTRIBUTE_UNUSED;
00053 static void print_keyword
00054 (CGEN_CPU_DESC, void *, CGEN_KEYWORD *, long, unsigned int) ATTRIBUTE_UNUSED;
00055 static void print_insn_normal
00056 (CGEN_CPU_DESC, void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int);
00057 static int print_insn
00058 (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, unsigned);
00059 static int default_print_insn
00060 (CGEN_CPU_DESC, bfd_vma, disassemble_info *) ATTRIBUTE_UNUSED;
00061 static int read_insn
00062 (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, int, CGEN_EXTRACT_INFO *,
00063 unsigned long *);
00064
00065
00066
00067
00068 static void print_hash PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int));
00069 static int my_print_insn PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *));
00070
00071
00072
00073 #define CGEN_PRINT_NORMAL(cd, info, value, attrs, pc, length) \
00074 do \
00075 { \
00076 if (CGEN_BOOL_ATTR ((attrs), CGEN_OPERAND_HASH_PREFIX)) \
00077 (*info->fprintf_func) (info->stream, "#"); \
00078 } \
00079 while (0)
00080
00081
00082
00083 static void
00084 print_hash (cd, dis_info, value, attrs, pc, length)
00085 CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
00086 PTR dis_info;
00087 long value ATTRIBUTE_UNUSED;
00088 unsigned int attrs ATTRIBUTE_UNUSED;
00089 bfd_vma pc ATTRIBUTE_UNUSED;
00090 int length ATTRIBUTE_UNUSED;
00091 {
00092 disassemble_info *info = (disassemble_info *) dis_info;
00093 (*info->fprintf_func) (info->stream, "#");
00094 }
00095
00096 #undef CGEN_PRINT_INSN
00097 #define CGEN_PRINT_INSN my_print_insn
00098
00099 static int
00100 my_print_insn (cd, pc, info)
00101 CGEN_CPU_DESC cd;
00102 bfd_vma pc;
00103 disassemble_info *info;
00104 {
00105 bfd_byte buffer[CGEN_MAX_INSN_SIZE];
00106 bfd_byte *buf = buffer;
00107 int status;
00108 int buflen = (pc & 3) == 0 ? 4 : 2;
00109 int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
00110 bfd_byte *x;
00111
00112
00113
00114 status = (*info->read_memory_func) (pc - ((!big_p && (pc & 3) != 0) ? 2 : 0),
00115 buf, buflen, info);
00116 if (status != 0)
00117 {
00118 (*info->memory_error_func) (status, pc, info);
00119 return -1;
00120 }
00121
00122
00123 x = (big_p ? &buf[0] : &buf[3]);
00124 if ((pc & 3) == 0 && (*x & 0x80) != 0)
00125 return print_insn (cd, pc, info, buf, buflen);
00126
00127
00128 if ((pc & 3) == 0)
00129 {
00130 buf += (big_p ? 0 : 2);
00131 if (print_insn (cd, pc, info, buf, 2) == 0)
00132 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
00133 buf += (big_p ? 2 : -2);
00134 }
00135
00136 x = (big_p ? &buf[0] : &buf[1]);
00137 if (*x & 0x80)
00138 {
00139
00140 (*info->fprintf_func) (info->stream, " || ");
00141 *x &= 0x7f;
00142 }
00143 else
00144 (*info->fprintf_func) (info->stream, " -> ");
00145
00146
00147
00148
00149 if (print_insn (cd, pc & ~ (bfd_vma) 3, info, buf, 2) == 0)
00150 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
00151
00152 return (pc & 3) ? 2 : 4;
00153 }
00154
00155
00156
00157 void m32r_cgen_print_operand
00158 PARAMS ((CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *,
00159 void const *, bfd_vma, int));
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 void
00177 m32r_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length)
00178 CGEN_CPU_DESC cd;
00179 int opindex;
00180 PTR xinfo;
00181 CGEN_FIELDS *fields;
00182 void const *attrs ATTRIBUTE_UNUSED;
00183 bfd_vma pc;
00184 int length;
00185 {
00186 disassemble_info *info = (disassemble_info *) xinfo;
00187
00188 switch (opindex)
00189 {
00190 case M32R_OPERAND_ACC :
00191 print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_acc, 0);
00192 break;
00193 case M32R_OPERAND_ACCD :
00194 print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_accd, 0);
00195 break;
00196 case M32R_OPERAND_ACCS :
00197 print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_accs, 0);
00198 break;
00199 case M32R_OPERAND_DCR :
00200 print_keyword (cd, info, & m32r_cgen_opval_cr_names, fields->f_r1, 0);
00201 break;
00202 case M32R_OPERAND_DISP16 :
00203 print_address (cd, info, fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
00204 break;
00205 case M32R_OPERAND_DISP24 :
00206 print_address (cd, info, fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
00207 break;
00208 case M32R_OPERAND_DISP8 :
00209 print_address (cd, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
00210 break;
00211 case M32R_OPERAND_DR :
00212 print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r1, 0);
00213 break;
00214 case M32R_OPERAND_HASH :
00215 print_hash (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
00216 break;
00217 case M32R_OPERAND_HI16 :
00218 print_normal (cd, info, fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT), pc, length);
00219 break;
00220 case M32R_OPERAND_IMM1 :
00221 print_normal (cd, info, fields->f_imm1, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00222 break;
00223 case M32R_OPERAND_SCR :
00224 print_keyword (cd, info, & m32r_cgen_opval_cr_names, fields->f_r2, 0);
00225 break;
00226 case M32R_OPERAND_SIMM16 :
00227 print_normal (cd, info, fields->f_simm16, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00228 break;
00229 case M32R_OPERAND_SIMM8 :
00230 print_normal (cd, info, fields->f_simm8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00231 break;
00232 case M32R_OPERAND_SLO16 :
00233 print_normal (cd, info, fields->f_simm16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
00234 break;
00235 case M32R_OPERAND_SR :
00236 print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r2, 0);
00237 break;
00238 case M32R_OPERAND_SRC1 :
00239 print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r1, 0);
00240 break;
00241 case M32R_OPERAND_SRC2 :
00242 print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r2, 0);
00243 break;
00244 case M32R_OPERAND_UIMM16 :
00245 print_normal (cd, info, fields->f_uimm16, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00246 break;
00247 case M32R_OPERAND_UIMM24 :
00248 print_address (cd, info, fields->f_uimm24, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
00249 break;
00250 case M32R_OPERAND_UIMM3 :
00251 print_normal (cd, info, fields->f_uimm3, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00252 break;
00253 case M32R_OPERAND_UIMM4 :
00254 print_normal (cd, info, fields->f_uimm4, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00255 break;
00256 case M32R_OPERAND_UIMM5 :
00257 print_normal (cd, info, fields->f_uimm5, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00258 break;
00259 case M32R_OPERAND_UIMM8 :
00260 print_normal (cd, info, fields->f_uimm8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
00261 break;
00262 case M32R_OPERAND_ULO16 :
00263 print_normal (cd, info, fields->f_uimm16, 0, pc, length);
00264 break;
00265
00266 default :
00267
00268 fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
00269 opindex);
00270 abort ();
00271 }
00272 }
00273
00274 cgen_print_fn * const m32r_cgen_print_handlers[] =
00275 {
00276 print_insn_normal,
00277 };
00278
00279
00280 void
00281 m32r_cgen_init_dis (cd)
00282 CGEN_CPU_DESC cd;
00283 {
00284 m32r_cgen_init_opcode_table (cd);
00285 m32r_cgen_init_ibld_table (cd);
00286 cd->print_handlers = & m32r_cgen_print_handlers[0];
00287 cd->print_operand = m32r_cgen_print_operand;
00288 }
00289
00290
00291
00292
00293 static void
00294 print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00295 void *dis_info,
00296 long value,
00297 unsigned int attrs,
00298 bfd_vma pc ATTRIBUTE_UNUSED,
00299 int length ATTRIBUTE_UNUSED)
00300 {
00301 disassemble_info *info = (disassemble_info *) dis_info;
00302
00303 #ifdef CGEN_PRINT_NORMAL
00304 CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
00305 #endif
00306
00307
00308 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
00309 ;
00310 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
00311 (*info->fprintf_func) (info->stream, "%ld", value);
00312 else
00313 (*info->fprintf_func) (info->stream, "0x%lx", value);
00314 }
00315
00316
00317
00318 static void
00319 print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00320 void *dis_info,
00321 bfd_vma value,
00322 unsigned int attrs,
00323 bfd_vma pc ATTRIBUTE_UNUSED,
00324 int length ATTRIBUTE_UNUSED)
00325 {
00326 disassemble_info *info = (disassemble_info *) dis_info;
00327
00328 #ifdef CGEN_PRINT_ADDRESS
00329 CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
00330 #endif
00331
00332
00333 if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
00334 ;
00335 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
00336 (*info->print_address_func) (value, info);
00337 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
00338 (*info->print_address_func) (value, info);
00339 else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
00340 (*info->fprintf_func) (info->stream, "%ld", (long) value);
00341 else
00342 (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
00343 }
00344
00345
00346
00347 static void
00348 print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00349 void *dis_info,
00350 CGEN_KEYWORD *keyword_table,
00351 long value,
00352 unsigned int attrs ATTRIBUTE_UNUSED)
00353 {
00354 disassemble_info *info = (disassemble_info *) dis_info;
00355 const CGEN_KEYWORD_ENTRY *ke;
00356
00357 ke = cgen_keyword_lookup_value (keyword_table, value);
00358 if (ke != NULL)
00359 (*info->fprintf_func) (info->stream, "%s", ke->name);
00360 else
00361 (*info->fprintf_func) (info->stream, "???");
00362 }
00363
00364
00365
00366
00367
00368
00369 static void
00370 print_insn_normal (CGEN_CPU_DESC cd,
00371 void *dis_info,
00372 const CGEN_INSN *insn,
00373 CGEN_FIELDS *fields,
00374 bfd_vma pc,
00375 int length)
00376 {
00377 const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
00378 disassemble_info *info = (disassemble_info *) dis_info;
00379 const CGEN_SYNTAX_CHAR_TYPE *syn;
00380
00381 CGEN_INIT_PRINT (cd);
00382
00383 for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
00384 {
00385 if (CGEN_SYNTAX_MNEMONIC_P (*syn))
00386 {
00387 (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
00388 continue;
00389 }
00390 if (CGEN_SYNTAX_CHAR_P (*syn))
00391 {
00392 (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
00393 continue;
00394 }
00395
00396
00397 m32r_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
00398 fields, CGEN_INSN_ATTRS (insn), pc, length);
00399 }
00400 }
00401
00402
00403
00404
00405
00406 static int
00407 read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
00408 bfd_vma pc,
00409 disassemble_info *info,
00410 bfd_byte *buf,
00411 int buflen,
00412 CGEN_EXTRACT_INFO *ex_info,
00413 unsigned long *insn_value)
00414 {
00415 int status = (*info->read_memory_func) (pc, buf, buflen, info);
00416 if (status != 0)
00417 {
00418 (*info->memory_error_func) (status, pc, info);
00419 return -1;
00420 }
00421
00422 ex_info->dis_info = info;
00423 ex_info->valid = (1 << buflen) - 1;
00424 ex_info->insn_bytes = buf;
00425
00426 *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
00427 return 0;
00428 }
00429
00430
00431
00432
00433
00434
00435
00436 static int
00437 print_insn (CGEN_CPU_DESC cd,
00438 bfd_vma pc,
00439 disassemble_info *info,
00440 bfd_byte *buf,
00441 unsigned int buflen)
00442 {
00443 CGEN_INSN_INT insn_value;
00444 const CGEN_INSN_LIST *insn_list;
00445 CGEN_EXTRACT_INFO ex_info;
00446 int basesize;
00447
00448
00449 basesize = cd->base_insn_bitsize < buflen * 8 ?
00450 cd->base_insn_bitsize : buflen * 8;
00451 insn_value = cgen_get_insn_value (cd, buf, basesize);
00452
00453
00454
00455
00456
00457 ex_info.valid = (1 << buflen) - 1;
00458 ex_info.dis_info = info;
00459 ex_info.insn_bytes = buf;
00460
00461
00462
00463
00464 insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
00465 while (insn_list != NULL)
00466 {
00467 const CGEN_INSN *insn = insn_list->insn;
00468 CGEN_FIELDS fields;
00469 int length;
00470 unsigned long insn_value_cropped;
00471
00472 #ifdef CGEN_VALIDATE_INSN_SUPPORTED
00473
00474
00475 if (! m32r_cgen_insn_supported (cd, insn))
00476 {
00477 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
00478 continue;
00479 }
00480 #endif
00481
00482
00483
00484
00485
00486
00487
00488 if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
00489 (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
00490 insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
00491 info->endian == BFD_ENDIAN_BIG);
00492 else
00493 insn_value_cropped = insn_value;
00494
00495 if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
00496 == CGEN_INSN_BASE_VALUE (insn))
00497 {
00498
00499
00500
00501
00502
00503
00504 if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
00505 (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
00506 {
00507 unsigned long full_insn_value;
00508 int rc = read_insn (cd, pc, info, buf,
00509 CGEN_INSN_BITSIZE (insn) / 8,
00510 & ex_info, & full_insn_value);
00511 if (rc != 0)
00512 return rc;
00513 length = CGEN_EXTRACT_FN (cd, insn)
00514 (cd, insn, &ex_info, full_insn_value, &fields, pc);
00515 }
00516 else
00517 length = CGEN_EXTRACT_FN (cd, insn)
00518 (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
00519
00520
00521 if (length < 0)
00522 return length;
00523 if (length > 0)
00524 {
00525 CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
00526
00527 return length / 8;
00528 }
00529 }
00530
00531 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
00532 }
00533
00534 return 0;
00535 }
00536
00537
00538
00539
00540
00541 #ifndef CGEN_PRINT_INSN
00542 #define CGEN_PRINT_INSN default_print_insn
00543 #endif
00544
00545 static int
00546 default_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
00547 {
00548 bfd_byte buf[CGEN_MAX_INSN_SIZE];
00549 int buflen;
00550 int status;
00551
00552
00553 buflen = cd->base_insn_bitsize / 8;
00554 status = (*info->read_memory_func) (pc, buf, buflen, info);
00555
00556
00557 if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
00558 {
00559 buflen = cd->min_insn_bitsize / 8;
00560 status = (*info->read_memory_func) (pc, buf, buflen, info);
00561 }
00562
00563 if (status != 0)
00564 {
00565 (*info->memory_error_func) (status, pc, info);
00566 return -1;
00567 }
00568
00569 return print_insn (cd, pc, info, buf, buflen);
00570 }
00571
00572
00573
00574
00575
00576 typedef struct cpu_desc_list {
00577 struct cpu_desc_list *next;
00578 int isa;
00579 int mach;
00580 int endian;
00581 CGEN_CPU_DESC cd;
00582 } cpu_desc_list;
00583
00584 int
00585 print_insn_m32r (bfd_vma pc, disassemble_info *info)
00586 {
00587 static cpu_desc_list *cd_list = 0;
00588 cpu_desc_list *cl = 0;
00589 static CGEN_CPU_DESC cd = 0;
00590 static int prev_isa;
00591 static int prev_mach;
00592 static int prev_endian;
00593 int length;
00594 int isa,mach;
00595 int endian = (info->endian == BFD_ENDIAN_BIG
00596 ? CGEN_ENDIAN_BIG
00597 : CGEN_ENDIAN_LITTLE);
00598 enum bfd_architecture arch;
00599
00600
00601 #ifndef CGEN_BFD_ARCH
00602 #define CGEN_BFD_ARCH bfd_arch_m32r
00603 #endif
00604 arch = info->arch;
00605 if (arch == bfd_arch_unknown)
00606 arch = CGEN_BFD_ARCH;
00607
00608
00609
00610 #ifdef CGEN_COMPUTE_MACH
00611 mach = CGEN_COMPUTE_MACH (info);
00612 #else
00613 mach = info->mach;
00614 #endif
00615
00616 #ifdef CGEN_COMPUTE_ISA
00617 isa = CGEN_COMPUTE_ISA (info);
00618 #else
00619 isa = info->insn_sets;
00620 #endif
00621
00622
00623 if (cd
00624 && (isa != prev_isa
00625 || mach != prev_mach
00626 || endian != prev_endian))
00627 {
00628 cd = 0;
00629 for (cl = cd_list; cl; cl = cl->next)
00630 {
00631 if (cl->isa == isa &&
00632 cl->mach == mach &&
00633 cl->endian == endian)
00634 {
00635 cd = cl->cd;
00636 break;
00637 }
00638 }
00639 }
00640
00641
00642 if (! cd)
00643 {
00644 const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
00645 const char *mach_name;
00646
00647 if (!arch_type)
00648 abort ();
00649 mach_name = arch_type->printable_name;
00650
00651 prev_isa = isa;
00652 prev_mach = mach;
00653 prev_endian = endian;
00654 cd = m32r_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
00655 CGEN_CPU_OPEN_BFDMACH, mach_name,
00656 CGEN_CPU_OPEN_ENDIAN, prev_endian,
00657 CGEN_CPU_OPEN_END);
00658 if (!cd)
00659 abort ();
00660
00661
00662 cl = xmalloc (sizeof (struct cpu_desc_list));
00663 cl->cd = cd;
00664 cl->isa = isa;
00665 cl->mach = mach;
00666 cl->endian = endian;
00667 cl->next = cd_list;
00668 cd_list = cl;
00669
00670 m32r_cgen_init_dis (cd);
00671 }
00672
00673
00674
00675
00676
00677
00678 length = CGEN_PRINT_INSN (cd, pc, info);
00679 if (length > 0)
00680 return length;
00681 if (length < 0)
00682 return -1;
00683
00684 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
00685 return cd->default_insn_bitsize / 8;
00686 }