00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <errno.h>
00021 #include <math.h>
00022 #include "sysdep.h"
00023 #include "dis-asm.h"
00024 #include "opcode/tic30.h"
00025
00026 #define NORMAL_INSN 1
00027 #define PARALLEL_INSN 2
00028
00029
00030
00031 #define GET_TYPE(insn) (insn & 0x80000000 ? insn & 0xC0000000 : insn & 0xE0000000)
00032
00033
00034 #define TWO_OPERAND_1 0x00000000
00035 #define TWO_OPERAND_2 0x40000000
00036 #define THREE_OPERAND 0x20000000
00037 #define PAR_STORE 0xC0000000
00038 #define MUL_ADDS 0x80000000
00039 #define BRANCHES 0x60000000
00040
00041
00042 #define NORMAL_IDEN 0x1F800000
00043 #define PAR_STORE_IDEN 0x3E000000
00044 #define MUL_ADD_IDEN 0x2C000000
00045 #define BR_IMM_IDEN 0x1F000000
00046 #define BR_COND_IDEN 0x1C3F0000
00047
00048
00049 #define AM_REGISTER 0x00000000
00050 #define AM_DIRECT 0x00200000
00051 #define AM_INDIRECT 0x00400000
00052 #define AM_IMM 0x00600000
00053
00054 #define P_FIELD 0x03000000
00055
00056 #define REG_AR0 0x08
00057 #define LDP_INSN 0x08700000
00058
00059
00060 static unsigned int _pc;
00061
00062 struct instruction
00063 {
00064 int type;
00065 template *tm;
00066 partemplate *ptm;
00067 };
00068
00069 int get_tic30_instruction PARAMS ((unsigned long, struct instruction *));
00070 int print_two_operand
00071 PARAMS ((disassemble_info *, unsigned long, struct instruction *));
00072 int print_three_operand
00073 PARAMS ((disassemble_info *, unsigned long, struct instruction *));
00074 int print_par_insn
00075 PARAMS ((disassemble_info *, unsigned long, struct instruction *));
00076 int print_branch
00077 PARAMS ((disassemble_info *, unsigned long, struct instruction *));
00078 int get_indirect_operand PARAMS ((unsigned short, int, char *));
00079 int get_register_operand PARAMS ((unsigned char, char *));
00080 int cnvt_tmsfloat_ieee PARAMS ((unsigned long, int, float *));
00081
00082 int
00083 print_insn_tic30 (pc, info)
00084 bfd_vma pc;
00085 disassemble_info *info;
00086 {
00087 unsigned long insn_word;
00088 struct instruction insn = { 0, NULL, NULL };
00089 bfd_vma bufaddr = pc - info->buffer_vma;
00090
00091 insn_word = (*(info->buffer + bufaddr) << 24) | (*(info->buffer + bufaddr + 1) << 16) |
00092 (*(info->buffer + bufaddr + 2) << 8) | *(info->buffer + bufaddr + 3);
00093 _pc = pc / 4;
00094
00095
00096 if (!get_tic30_instruction (insn_word, &insn))
00097 return -1;
00098 switch (GET_TYPE (insn_word))
00099 {
00100 case TWO_OPERAND_1:
00101 case TWO_OPERAND_2:
00102 if (!print_two_operand (info, insn_word, &insn))
00103 return -1;
00104 break;
00105 case THREE_OPERAND:
00106 if (!print_three_operand (info, insn_word, &insn))
00107 return -1;
00108 break;
00109 case PAR_STORE:
00110 case MUL_ADDS:
00111 if (!print_par_insn (info, insn_word, &insn))
00112 return -1;
00113 break;
00114 case BRANCHES:
00115 if (!print_branch (info, insn_word, &insn))
00116 return -1;
00117 break;
00118 }
00119 return 4;
00120 }
00121
00122 int
00123 get_tic30_instruction (insn_word, insn)
00124 unsigned long insn_word;
00125 struct instruction *insn;
00126 {
00127 switch (GET_TYPE (insn_word))
00128 {
00129 case TWO_OPERAND_1:
00130 case TWO_OPERAND_2:
00131 case THREE_OPERAND:
00132 insn->type = NORMAL_INSN;
00133 {
00134 template *current_optab = (template *) tic30_optab;
00135 for (; current_optab < tic30_optab_end; current_optab++)
00136 {
00137 if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
00138 {
00139 if (current_optab->operands == 0)
00140 {
00141 if (current_optab->base_opcode == insn_word)
00142 {
00143 insn->tm = current_optab;
00144 break;
00145 }
00146 }
00147 else if ((current_optab->base_opcode & NORMAL_IDEN) == (insn_word & NORMAL_IDEN))
00148 {
00149 insn->tm = current_optab;
00150 break;
00151 }
00152 }
00153 }
00154 }
00155 break;
00156 case PAR_STORE:
00157 insn->type = PARALLEL_INSN;
00158 {
00159 partemplate *current_optab = (partemplate *) tic30_paroptab;
00160 for (; current_optab < tic30_paroptab_end; current_optab++)
00161 {
00162 if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
00163 {
00164 if ((current_optab->base_opcode & PAR_STORE_IDEN) == (insn_word & PAR_STORE_IDEN))
00165 {
00166 insn->ptm = current_optab;
00167 break;
00168 }
00169 }
00170 }
00171 }
00172 break;
00173 case MUL_ADDS:
00174 insn->type = PARALLEL_INSN;
00175 {
00176 partemplate *current_optab = (partemplate *) tic30_paroptab;
00177 for (; current_optab < tic30_paroptab_end; current_optab++)
00178 {
00179 if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
00180 {
00181 if ((current_optab->base_opcode & MUL_ADD_IDEN) == (insn_word & MUL_ADD_IDEN))
00182 {
00183 insn->ptm = current_optab;
00184 break;
00185 }
00186 }
00187 }
00188 }
00189 break;
00190 case BRANCHES:
00191 insn->type = NORMAL_INSN;
00192 {
00193 template *current_optab = (template *) tic30_optab;
00194 for (; current_optab < tic30_optab_end; current_optab++)
00195 {
00196 if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
00197 {
00198 if (current_optab->operand_types[0] & Imm24)
00199 {
00200 if ((current_optab->base_opcode & BR_IMM_IDEN) == (insn_word & BR_IMM_IDEN))
00201 {
00202 insn->tm = current_optab;
00203 break;
00204 }
00205 }
00206 else if (current_optab->operands > 0)
00207 {
00208 if ((current_optab->base_opcode & BR_COND_IDEN) == (insn_word & BR_COND_IDEN))
00209 {
00210 insn->tm = current_optab;
00211 break;
00212 }
00213 }
00214 else
00215 {
00216 if ((current_optab->base_opcode & (BR_COND_IDEN | 0x00800000)) == (insn_word & (BR_COND_IDEN | 0x00800000)))
00217 {
00218 insn->tm = current_optab;
00219 break;
00220 }
00221 }
00222 }
00223 }
00224 }
00225 break;
00226 default:
00227 return 0;
00228 }
00229 return 1;
00230 }
00231
00232 int
00233 print_two_operand (info, insn_word, insn)
00234 disassemble_info *info;
00235 unsigned long insn_word;
00236 struct instruction *insn;
00237 {
00238 char name[12];
00239 char operand[2][13] =
00240 {
00241 {0},
00242 {0}};
00243 float f_number;
00244
00245 if (insn->tm == NULL)
00246 return 0;
00247 strcpy (name, insn->tm->name);
00248 if (insn->tm->opcode_modifier == AddressMode)
00249 {
00250 int src_op, dest_op;
00251
00252 if ((insn->tm->operand_types[1] & (Direct | Indirect)) == (Direct | Indirect))
00253 {
00254 src_op = 1;
00255 dest_op = 0;
00256 }
00257 else
00258 {
00259 src_op = 0;
00260 dest_op = 1;
00261 }
00262
00263 if (insn->tm->operands == 2)
00264 get_register_operand ((insn_word & 0x001F0000) >> 16, operand[dest_op]);
00265
00266 switch (insn_word & AddressMode)
00267 {
00268 case AM_REGISTER:
00269
00270 if ((insn->tm->operand_types[0] & NotReq) == 0)
00271 get_register_operand ((insn_word & 0x0000001F), operand[src_op]);
00272 break;
00273 case AM_DIRECT:
00274 sprintf (operand[src_op], "@0x%lX", (insn_word & 0x0000FFFF));
00275 break;
00276 case AM_INDIRECT:
00277 get_indirect_operand ((insn_word & 0x0000FFFF), 2, operand[src_op]);
00278 break;
00279 case AM_IMM:
00280
00281 switch (insn->tm->imm_arg_type)
00282 {
00283 case Imm_Float:
00284 cnvt_tmsfloat_ieee ((insn_word & 0x0000FFFF), 2, &f_number);
00285 sprintf (operand[src_op], "%2.2f", f_number);
00286 break;
00287 case Imm_SInt:
00288 sprintf (operand[src_op], "%d", (short) (insn_word & 0x0000FFFF));
00289 break;
00290 case Imm_UInt:
00291 sprintf (operand[src_op], "%lu", (insn_word & 0x0000FFFF));
00292 break;
00293 default:
00294 return 0;
00295 }
00296
00297 if ((insn_word & 0xFFFFFF00) == LDP_INSN)
00298 {
00299 strcpy (name, "ldp");
00300 sprintf (operand[0], "0x%06lX", (insn_word & 0x000000FF) << 16);
00301 operand[1][0] = '\0';
00302 }
00303 }
00304 }
00305
00306 else if (insn->tm->operands == 1)
00307 {
00308 if (insn->tm->opcode_modifier == StackOp)
00309 {
00310 get_register_operand ((insn_word & 0x001F0000) >> 16, operand[0]);
00311 }
00312 }
00313
00314 info->fprintf_func (info->stream, " %s %s%c%s", name,
00315 operand[0][0] ? operand[0] : "",
00316 operand[1][0] ? ',' : ' ',
00317 operand[1][0] ? operand[1] : "");
00318 return 1;
00319 }
00320
00321 int
00322 print_three_operand (info, insn_word, insn)
00323 disassemble_info *info;
00324 unsigned long insn_word;
00325 struct instruction *insn;
00326 {
00327 char operand[3][13] =
00328 {
00329 {0},
00330 {0},
00331 {0}};
00332
00333 if (insn->tm == NULL)
00334 return 0;
00335 switch (insn_word & AddressMode)
00336 {
00337 case AM_REGISTER:
00338 get_register_operand ((insn_word & 0x000000FF), operand[0]);
00339 get_register_operand ((insn_word & 0x0000FF00) >> 8, operand[1]);
00340 break;
00341 case AM_DIRECT:
00342 get_register_operand ((insn_word & 0x000000FF), operand[0]);
00343 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1]);
00344 break;
00345 case AM_INDIRECT:
00346 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0]);
00347 get_register_operand ((insn_word & 0x0000FF00) >> 8, operand[1]);
00348 break;
00349 case AM_IMM:
00350 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0]);
00351 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1]);
00352 break;
00353 default:
00354 return 0;
00355 }
00356 if (insn->tm->operands == 3)
00357 get_register_operand ((insn_word & 0x001F0000) >> 16, operand[2]);
00358 info->fprintf_func (info->stream, " %s %s,%s%c%s", insn->tm->name,
00359 operand[0], operand[1],
00360 operand[2][0] ? ',' : ' ',
00361 operand[2][0] ? operand[2] : "");
00362 return 1;
00363 }
00364
00365 int
00366 print_par_insn (info, insn_word, insn)
00367 disassemble_info *info;
00368 unsigned long insn_word;
00369 struct instruction *insn;
00370 {
00371 size_t i, len;
00372 char *name1, *name2;
00373 char operand[2][3][13] =
00374 {
00375 {
00376 {0},
00377 {0},
00378 {0}},
00379 {
00380 {0},
00381 {0},
00382 {0}}};
00383
00384 if (insn->ptm == NULL)
00385 return 0;
00386
00387
00388 name1 = (char *) strdup (insn->ptm->name + 2);
00389 name2 = "";
00390 len = strlen (name1);
00391 for (i = 0; i < len; i++)
00392 {
00393 if (name1[i] == '_')
00394 {
00395 name2 = &name1[i + 1];
00396 name1[i] = '\0';
00397 break;
00398 }
00399 }
00400
00401 switch (insn->ptm->oporder)
00402 {
00403 case OO_4op1:
00404 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
00405 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
00406 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
00407 get_register_operand ((insn_word >> 22) & 0x07, operand[0][1]);
00408 break;
00409 case OO_4op2:
00410 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
00411 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][0]);
00412 get_register_operand ((insn_word >> 19) & 0x07, operand[1][1]);
00413 get_register_operand ((insn_word >> 22) & 0x07, operand[0][1]);
00414 break;
00415 case OO_4op3:
00416 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
00417 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
00418 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
00419 get_register_operand ((insn_word >> 22) & 0x07, operand[0][0]);
00420 break;
00421 case OO_5op1:
00422 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
00423 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
00424 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
00425 get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
00426 get_register_operand ((insn_word >> 22) & 0x07, operand[0][2]);
00427 break;
00428 case OO_5op2:
00429 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
00430 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
00431 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
00432 get_register_operand ((insn_word >> 19) & 0x07, operand[0][0]);
00433 get_register_operand ((insn_word >> 22) & 0x07, operand[0][2]);
00434 break;
00435 case OO_PField:
00436 if (insn_word & 0x00800000)
00437 get_register_operand (0x01, operand[0][2]);
00438 else
00439 get_register_operand (0x00, operand[0][2]);
00440 if (insn_word & 0x00400000)
00441 get_register_operand (0x03, operand[1][2]);
00442 else
00443 get_register_operand (0x02, operand[1][2]);
00444 switch (insn_word & P_FIELD)
00445 {
00446 case 0x00000000:
00447 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
00448 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
00449 get_register_operand ((insn_word >> 16) & 0x07, operand[1][1]);
00450 get_register_operand ((insn_word >> 19) & 0x07, operand[1][0]);
00451 break;
00452 case 0x01000000:
00453 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][0]);
00454 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
00455 get_register_operand ((insn_word >> 16) & 0x07, operand[1][1]);
00456 get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
00457 break;
00458 case 0x02000000:
00459 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][1]);
00460 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][0]);
00461 get_register_operand ((insn_word >> 16) & 0x07, operand[0][1]);
00462 get_register_operand ((insn_word >> 19) & 0x07, operand[0][0]);
00463 break;
00464 case 0x03000000:
00465 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][1]);
00466 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
00467 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
00468 get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
00469 break;
00470 }
00471 break;
00472 default:
00473 return 0;
00474 }
00475 info->fprintf_func (info->stream, " %s %s,%s%c%s", name1,
00476 operand[0][0], operand[0][1],
00477 operand[0][2][0] ? ',' : ' ',
00478 operand[0][2][0] ? operand[0][2] : "");
00479 info->fprintf_func (info->stream, "\n\t\t\t|| %s %s,%s%c%s", name2,
00480 operand[1][0], operand[1][1],
00481 operand[1][2][0] ? ',' : ' ',
00482 operand[1][2][0] ? operand[1][2] : "");
00483 free (name1);
00484 return 1;
00485 }
00486
00487 int
00488 print_branch (info, insn_word, insn)
00489 disassemble_info *info;
00490 unsigned long insn_word;
00491 struct instruction *insn;
00492 {
00493 char operand[2][13] =
00494 {
00495 {0},
00496 {0}};
00497 unsigned long address;
00498 int print_label = 0;
00499
00500 if (insn->tm == NULL)
00501 return 0;
00502
00503 if (insn->tm->operand_types[0] & Imm24)
00504 {
00505 address = insn_word & 0x00FFFFFF;
00506 sprintf (operand[0], "0x%lX", address);
00507 print_label = 1;
00508 }
00509
00510 else if (insn->tm->operand_types[0] & IVector)
00511 {
00512 address = insn_word & 0x0000001F;
00513 sprintf (operand[0], "0x%lX", address);
00514 }
00515 else
00516 {
00517 address = insn_word & 0x0000FFFF;
00518
00519 if (insn->tm->operands == 2)
00520 {
00521 get_register_operand (((insn_word & 0x01C00000) >> 22) + REG_AR0, operand[0]);
00522 if (insn_word & PCRel)
00523 {
00524 sprintf (operand[1], "%d", (short) address);
00525 print_label = 1;
00526 }
00527 else
00528 get_register_operand (insn_word & 0x0000001F, operand[1]);
00529 }
00530
00531 else if (insn->tm->operands == 1)
00532 {
00533 if (insn_word & PCRel)
00534 {
00535 address = (short) address;
00536 sprintf (operand[0], "%ld", address);
00537 print_label = 1;
00538 }
00539 else
00540 get_register_operand (insn_word & 0x0000001F, operand[0]);
00541 }
00542 }
00543 info->fprintf_func (info->stream, " %s %s%c%s", insn->tm->name,
00544 operand[0][0] ? operand[0] : "",
00545 operand[1][0] ? ',' : ' ',
00546 operand[1][0] ? operand[1] : "");
00547
00548 if (print_label && info->symbols)
00549 {
00550 asymbol *sym = *info->symbols;
00551
00552 if ((insn->tm->opcode_modifier == PCRel) && (insn_word & PCRel))
00553 {
00554 address = (_pc + 1 + (short) address) - ((sym->section->vma + sym->value) / 4);
00555
00556 if (insn_word & 0x00200000)
00557 address += 2;
00558 }
00559 else
00560 {
00561 address -= ((sym->section->vma + sym->value) / 4);
00562 }
00563 if (address == 0)
00564 info->fprintf_func (info->stream, " <%s>", sym->name);
00565 else
00566 info->fprintf_func (info->stream, " <%s %c %d>", sym->name,
00567 ((short) address < 0) ? '-' : '+',
00568 abs (address));
00569 }
00570 return 1;
00571 }
00572
00573 int
00574 get_indirect_operand (fragment, size, buffer)
00575 unsigned short fragment;
00576 int size;
00577 char *buffer;
00578 {
00579 unsigned char mod;
00580 unsigned arnum;
00581 unsigned char disp;
00582
00583 if (buffer == NULL)
00584 return 0;
00585
00586
00587 switch (size)
00588 {
00589 case 1:
00590 mod = (fragment & 0x00F8) >> 3;
00591 arnum = (fragment & 0x0007);
00592 disp = 0;
00593 break;
00594 case 2:
00595 mod = (fragment & 0xF800) >> 11;
00596 arnum = (fragment & 0x0700) >> 8;
00597 disp = (fragment & 0x00FF);
00598 break;
00599 default:
00600 return 0;
00601 }
00602 {
00603 const ind_addr_type *current_ind = tic30_indaddr_tab;
00604 for (; current_ind < tic30_indaddrtab_end; current_ind++)
00605 {
00606 if (current_ind->modfield == mod)
00607 {
00608 if (current_ind->displacement == IMPLIED_DISP && size == 2)
00609 {
00610 continue;
00611 }
00612 else
00613 {
00614 size_t i, len;
00615 int bufcnt;
00616
00617 len = strlen (current_ind->syntax);
00618 for (i = 0, bufcnt = 0; i < len; i++, bufcnt++)
00619 {
00620 buffer[bufcnt] = current_ind->syntax[i];
00621 if (buffer[bufcnt - 1] == 'a' && buffer[bufcnt] == 'r')
00622 buffer[++bufcnt] = arnum + '0';
00623 if (buffer[bufcnt] == '('
00624 && current_ind->displacement == DISP_REQUIRED)
00625 {
00626 sprintf (&buffer[bufcnt + 1], "%u", disp);
00627 bufcnt += strlen (&buffer[bufcnt + 1]);
00628 }
00629 }
00630 buffer[bufcnt + 1] = '\0';
00631 break;
00632 }
00633 }
00634 }
00635 }
00636 return 1;
00637 }
00638
00639 int
00640 get_register_operand (fragment, buffer)
00641 unsigned char fragment;
00642 char *buffer;
00643 {
00644 const reg *current_reg = tic30_regtab;
00645
00646 if (buffer == NULL)
00647 return 0;
00648 for (; current_reg < tic30_regtab_end; current_reg++)
00649 {
00650 if ((fragment & 0x1F) == current_reg->opcode)
00651 {
00652 strcpy (buffer, current_reg->name);
00653 return 1;
00654 }
00655 }
00656 return 0;
00657 }
00658
00659 int
00660 cnvt_tmsfloat_ieee (tmsfloat, size, ieeefloat)
00661 unsigned long tmsfloat;
00662 int size;
00663 float *ieeefloat;
00664 {
00665 unsigned long exp, sign, mant;
00666 union {
00667 unsigned long l;
00668 float f;
00669 } val;
00670
00671 if (size == 2)
00672 {
00673 if ((tmsfloat & 0x0000F000) == 0x00008000)
00674 tmsfloat = 0x80000000;
00675 else
00676 {
00677 tmsfloat <<= 16;
00678 tmsfloat = (long) tmsfloat >> 4;
00679 }
00680 }
00681 exp = tmsfloat & 0xFF000000;
00682 if (exp == 0x80000000)
00683 {
00684 *ieeefloat = 0.0;
00685 return 1;
00686 }
00687 exp += 0x7F000000;
00688 sign = (tmsfloat & 0x00800000) << 8;
00689 mant = tmsfloat & 0x007FFFFF;
00690 if (exp == 0xFF000000)
00691 {
00692 if (mant == 0)
00693 *ieeefloat = ERANGE;
00694 if (sign == 0)
00695 *ieeefloat = 1.0 / 0.0;
00696 else
00697 *ieeefloat = -1.0 / 0.0;
00698 return 1;
00699 }
00700 exp >>= 1;
00701 if (sign)
00702 {
00703 mant = (~mant) & 0x007FFFFF;
00704 mant += 1;
00705 exp += mant & 0x00800000;
00706 exp &= 0x7F800000;
00707 mant &= 0x007FFFFF;
00708 }
00709 if (tmsfloat == 0x80000000)
00710 sign = mant = exp = 0;
00711 tmsfloat = sign | exp | mant;
00712 val.l = tmsfloat;
00713 *ieeefloat = val.f;
00714 return 1;
00715 }