source: branches/libc-0.6/src/binutils/opcodes/tic30-dis.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 19.5 KB
Line 
1/* Disassembly routines for TMS320C30 architecture
2 Copyright 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
3 Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au)
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
18 02111-1307, USA. */
19
20#include <errno.h>
21#include <math.h>
22#include "sysdep.h"
23#include "dis-asm.h"
24#include "opcode/tic30.h"
25
26#define NORMAL_INSN 1
27#define PARALLEL_INSN 2
28
29/* Gets the type of instruction based on the top 2 or 3 bits of the
30 instruction word. */
31#define GET_TYPE(insn) (insn & 0x80000000 ? insn & 0xC0000000 : insn & 0xE0000000)
32
33/* Instruction types. */
34#define TWO_OPERAND_1 0x00000000
35#define TWO_OPERAND_2 0x40000000
36#define THREE_OPERAND 0x20000000
37#define PAR_STORE 0xC0000000
38#define MUL_ADDS 0x80000000
39#define BRANCHES 0x60000000
40
41/* Specific instruction id bits. */
42#define NORMAL_IDEN 0x1F800000
43#define PAR_STORE_IDEN 0x3E000000
44#define MUL_ADD_IDEN 0x2C000000
45#define BR_IMM_IDEN 0x1F000000
46#define BR_COND_IDEN 0x1C3F0000
47
48/* Addressing modes. */
49#define AM_REGISTER 0x00000000
50#define AM_DIRECT 0x00200000
51#define AM_INDIRECT 0x00400000
52#define AM_IMM 0x00600000
53
54#define P_FIELD 0x03000000
55
56#define REG_AR0 0x08
57#define LDP_INSN 0x08700000
58
59/* TMS320C30 program counter for current instruction. */
60static unsigned int _pc;
61
62struct instruction
63{
64 int type;
65 template *tm;
66 partemplate *ptm;
67};
68
69int get_tic30_instruction PARAMS ((unsigned long, struct instruction *));
70int print_two_operand
71 PARAMS ((disassemble_info *, unsigned long, struct instruction *));
72int print_three_operand
73 PARAMS ((disassemble_info *, unsigned long, struct instruction *));
74int print_par_insn
75 PARAMS ((disassemble_info *, unsigned long, struct instruction *));
76int print_branch
77 PARAMS ((disassemble_info *, unsigned long, struct instruction *));
78int get_indirect_operand PARAMS ((unsigned short, int, char *));
79int get_register_operand PARAMS ((unsigned char, char *));
80int cnvt_tmsfloat_ieee PARAMS ((unsigned long, int, float *));
81
82int
83print_insn_tic30 (pc, info)
84 bfd_vma pc;
85 disassemble_info *info;
86{
87 unsigned long insn_word;
88 struct instruction insn = { 0, NULL, NULL };
89 bfd_vma bufaddr = pc - info->buffer_vma;
90 /* Obtain the current instruction word from the buffer. */
91 insn_word = (*(info->buffer + bufaddr) << 24) | (*(info->buffer + bufaddr + 1) << 16) |
92 (*(info->buffer + bufaddr + 2) << 8) | *(info->buffer + bufaddr + 3);
93 _pc = pc / 4;
94 /* Get the instruction refered to by the current instruction word
95 and print it out based on its type. */
96 if (!get_tic30_instruction (insn_word, &insn))
97 return -1;
98 switch (GET_TYPE (insn_word))
99 {
100 case TWO_OPERAND_1:
101 case TWO_OPERAND_2:
102 if (!print_two_operand (info, insn_word, &insn))
103 return -1;
104 break;
105 case THREE_OPERAND:
106 if (!print_three_operand (info, insn_word, &insn))
107 return -1;
108 break;
109 case PAR_STORE:
110 case MUL_ADDS:
111 if (!print_par_insn (info, insn_word, &insn))
112 return -1;
113 break;
114 case BRANCHES:
115 if (!print_branch (info, insn_word, &insn))
116 return -1;
117 break;
118 }
119 return 4;
120}
121
122int
123get_tic30_instruction (insn_word, insn)
124 unsigned long insn_word;
125 struct instruction *insn;
126{
127 switch (GET_TYPE (insn_word))
128 {
129 case TWO_OPERAND_1:
130 case TWO_OPERAND_2:
131 case THREE_OPERAND:
132 insn->type = NORMAL_INSN;
133 {
134 template *current_optab = (template *) tic30_optab;
135 for (; current_optab < tic30_optab_end; current_optab++)
136 {
137 if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
138 {
139 if (current_optab->operands == 0)
140 {
141 if (current_optab->base_opcode == insn_word)
142 {
143 insn->tm = current_optab;
144 break;
145 }
146 }
147 else if ((current_optab->base_opcode & NORMAL_IDEN) == (insn_word & NORMAL_IDEN))
148 {
149 insn->tm = current_optab;
150 break;
151 }
152 }
153 }
154 }
155 break;
156 case PAR_STORE:
157 insn->type = PARALLEL_INSN;
158 {
159 partemplate *current_optab = (partemplate *) tic30_paroptab;
160 for (; current_optab < tic30_paroptab_end; current_optab++)
161 {
162 if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
163 {
164 if ((current_optab->base_opcode & PAR_STORE_IDEN) == (insn_word & PAR_STORE_IDEN))
165 {
166 insn->ptm = current_optab;
167 break;
168 }
169 }
170 }
171 }
172 break;
173 case MUL_ADDS:
174 insn->type = PARALLEL_INSN;
175 {
176 partemplate *current_optab = (partemplate *) tic30_paroptab;
177 for (; current_optab < tic30_paroptab_end; current_optab++)
178 {
179 if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
180 {
181 if ((current_optab->base_opcode & MUL_ADD_IDEN) == (insn_word & MUL_ADD_IDEN))
182 {
183 insn->ptm = current_optab;
184 break;
185 }
186 }
187 }
188 }
189 break;
190 case BRANCHES:
191 insn->type = NORMAL_INSN;
192 {
193 template *current_optab = (template *) tic30_optab;
194 for (; current_optab < tic30_optab_end; current_optab++)
195 {
196 if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
197 {
198 if (current_optab->operand_types[0] & Imm24)
199 {
200 if ((current_optab->base_opcode & BR_IMM_IDEN) == (insn_word & BR_IMM_IDEN))
201 {
202 insn->tm = current_optab;
203 break;
204 }
205 }
206 else if (current_optab->operands > 0)
207 {
208 if ((current_optab->base_opcode & BR_COND_IDEN) == (insn_word & BR_COND_IDEN))
209 {
210 insn->tm = current_optab;
211 break;
212 }
213 }
214 else
215 {
216 if ((current_optab->base_opcode & (BR_COND_IDEN | 0x00800000)) == (insn_word & (BR_COND_IDEN | 0x00800000)))
217 {
218 insn->tm = current_optab;
219 break;
220 }
221 }
222 }
223 }
224 }
225 break;
226 default:
227 return 0;
228 }
229 return 1;
230}
231
232int
233print_two_operand (info, insn_word, insn)
234 disassemble_info *info;
235 unsigned long insn_word;
236 struct instruction *insn;
237{
238 char name[12];
239 char operand[2][13] =
240 {
241 {0},
242 {0}};
243 float f_number;
244
245 if (insn->tm == NULL)
246 return 0;
247 strcpy (name, insn->tm->name);
248 if (insn->tm->opcode_modifier == AddressMode)
249 {
250 int src_op, dest_op;
251 /* Determine whether instruction is a store or a normal instruction. */
252 if ((insn->tm->operand_types[1] & (Direct | Indirect)) == (Direct | Indirect))
253 {
254 src_op = 1;
255 dest_op = 0;
256 }
257 else
258 {
259 src_op = 0;
260 dest_op = 1;
261 }
262 /* Get the destination register. */
263 if (insn->tm->operands == 2)
264 get_register_operand ((insn_word & 0x001F0000) >> 16, operand[dest_op]);
265 /* Get the source operand based on addressing mode. */
266 switch (insn_word & AddressMode)
267 {
268 case AM_REGISTER:
269 /* Check for the NOP instruction before getting the operand. */
270 if ((insn->tm->operand_types[0] & NotReq) == 0)
271 get_register_operand ((insn_word & 0x0000001F), operand[src_op]);
272 break;
273 case AM_DIRECT:
274 sprintf (operand[src_op], "@0x%lX", (insn_word & 0x0000FFFF));
275 break;
276 case AM_INDIRECT:
277 get_indirect_operand ((insn_word & 0x0000FFFF), 2, operand[src_op]);
278 break;
279 case AM_IMM:
280 /* Get the value of the immediate operand based on variable type. */
281 switch (insn->tm->imm_arg_type)
282 {
283 case Imm_Float:
284 cnvt_tmsfloat_ieee ((insn_word & 0x0000FFFF), 2, &f_number);
285 sprintf (operand[src_op], "%2.2f", f_number);
286 break;
287 case Imm_SInt:
288 sprintf (operand[src_op], "%d", (short) (insn_word & 0x0000FFFF));
289 break;
290 case Imm_UInt:
291 sprintf (operand[src_op], "%lu", (insn_word & 0x0000FFFF));
292 break;
293 default:
294 return 0;
295 }
296 /* Handle special case for LDP instruction. */
297 if ((insn_word & 0xFFFFFF00) == LDP_INSN)
298 {
299 strcpy (name, "ldp");
300 sprintf (operand[0], "0x%06lX", (insn_word & 0x000000FF) << 16);
301 operand[1][0] = '\0';
302 }
303 }
304 }
305 /* Handle case for stack and rotate instructions. */
306 else if (insn->tm->operands == 1)
307 {
308 if (insn->tm->opcode_modifier == StackOp)
309 {
310 get_register_operand ((insn_word & 0x001F0000) >> 16, operand[0]);
311 }
312 }
313 /* Output instruction to stream. */
314 info->fprintf_func (info->stream, " %s %s%c%s", name,
315 operand[0][0] ? operand[0] : "",
316 operand[1][0] ? ',' : ' ',
317 operand[1][0] ? operand[1] : "");
318 return 1;
319}
320
321int
322print_three_operand (info, insn_word, insn)
323 disassemble_info *info;
324 unsigned long insn_word;
325 struct instruction *insn;
326{
327 char operand[3][13] =
328 {
329 {0},
330 {0},
331 {0}};
332
333 if (insn->tm == NULL)
334 return 0;
335 switch (insn_word & AddressMode)
336 {
337 case AM_REGISTER:
338 get_register_operand ((insn_word & 0x000000FF), operand[0]);
339 get_register_operand ((insn_word & 0x0000FF00) >> 8, operand[1]);
340 break;
341 case AM_DIRECT:
342 get_register_operand ((insn_word & 0x000000FF), operand[0]);
343 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1]);
344 break;
345 case AM_INDIRECT:
346 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0]);
347 get_register_operand ((insn_word & 0x0000FF00) >> 8, operand[1]);
348 break;
349 case AM_IMM:
350 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0]);
351 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1]);
352 break;
353 default:
354 return 0;
355 }
356 if (insn->tm->operands == 3)
357 get_register_operand ((insn_word & 0x001F0000) >> 16, operand[2]);
358 info->fprintf_func (info->stream, " %s %s,%s%c%s", insn->tm->name,
359 operand[0], operand[1],
360 operand[2][0] ? ',' : ' ',
361 operand[2][0] ? operand[2] : "");
362 return 1;
363}
364
365int
366print_par_insn (info, insn_word, insn)
367 disassemble_info *info;
368 unsigned long insn_word;
369 struct instruction *insn;
370{
371 size_t i, len;
372 char *name1, *name2;
373 char operand[2][3][13] =
374 {
375 {
376 {0},
377 {0},
378 {0}},
379 {
380 {0},
381 {0},
382 {0}}};
383
384 if (insn->ptm == NULL)
385 return 0;
386 /* Parse out the names of each of the parallel instructions from the
387 q_insn1_insn2 format. */
388 name1 = (char *) strdup (insn->ptm->name + 2);
389 name2 = "";
390 len = strlen (name1);
391 for (i = 0; i < len; i++)
392 {
393 if (name1[i] == '_')
394 {
395 name2 = &name1[i + 1];
396 name1[i] = '\0';
397 break;
398 }
399 }
400 /* Get the operands of the instruction based on the operand order. */
401 switch (insn->ptm->oporder)
402 {
403 case OO_4op1:
404 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
405 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
406 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
407 get_register_operand ((insn_word >> 22) & 0x07, operand[0][1]);
408 break;
409 case OO_4op2:
410 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
411 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][0]);
412 get_register_operand ((insn_word >> 19) & 0x07, operand[1][1]);
413 get_register_operand ((insn_word >> 22) & 0x07, operand[0][1]);
414 break;
415 case OO_4op3:
416 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
417 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
418 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
419 get_register_operand ((insn_word >> 22) & 0x07, operand[0][0]);
420 break;
421 case OO_5op1:
422 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
423 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
424 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
425 get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
426 get_register_operand ((insn_word >> 22) & 0x07, operand[0][2]);
427 break;
428 case OO_5op2:
429 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
430 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
431 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
432 get_register_operand ((insn_word >> 19) & 0x07, operand[0][0]);
433 get_register_operand ((insn_word >> 22) & 0x07, operand[0][2]);
434 break;
435 case OO_PField:
436 if (insn_word & 0x00800000)
437 get_register_operand (0x01, operand[0][2]);
438 else
439 get_register_operand (0x00, operand[0][2]);
440 if (insn_word & 0x00400000)
441 get_register_operand (0x03, operand[1][2]);
442 else
443 get_register_operand (0x02, operand[1][2]);
444 switch (insn_word & P_FIELD)
445 {
446 case 0x00000000:
447 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
448 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
449 get_register_operand ((insn_word >> 16) & 0x07, operand[1][1]);
450 get_register_operand ((insn_word >> 19) & 0x07, operand[1][0]);
451 break;
452 case 0x01000000:
453 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][0]);
454 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
455 get_register_operand ((insn_word >> 16) & 0x07, operand[1][1]);
456 get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
457 break;
458 case 0x02000000:
459 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][1]);
460 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][0]);
461 get_register_operand ((insn_word >> 16) & 0x07, operand[0][1]);
462 get_register_operand ((insn_word >> 19) & 0x07, operand[0][0]);
463 break;
464 case 0x03000000:
465 get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][1]);
466 get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
467 get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
468 get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
469 break;
470 }
471 break;
472 default:
473 return 0;
474 }
475 info->fprintf_func (info->stream, " %s %s,%s%c%s", name1,
476 operand[0][0], operand[0][1],
477 operand[0][2][0] ? ',' : ' ',
478 operand[0][2][0] ? operand[0][2] : "");
479 info->fprintf_func (info->stream, "\n\t\t\t|| %s %s,%s%c%s", name2,
480 operand[1][0], operand[1][1],
481 operand[1][2][0] ? ',' : ' ',
482 operand[1][2][0] ? operand[1][2] : "");
483 free (name1);
484 return 1;
485}
486
487int
488print_branch (info, insn_word, insn)
489 disassemble_info *info;
490 unsigned long insn_word;
491 struct instruction *insn;
492{
493 char operand[2][13] =
494 {
495 {0},
496 {0}};
497 unsigned long address;
498 int print_label = 0;
499
500 if (insn->tm == NULL)
501 return 0;
502 /* Get the operands for 24-bit immediate jumps. */
503 if (insn->tm->operand_types[0] & Imm24)
504 {
505 address = insn_word & 0x00FFFFFF;
506 sprintf (operand[0], "0x%lX", address);
507 print_label = 1;
508 }
509 /* Get the operand for the trap instruction. */
510 else if (insn->tm->operand_types[0] & IVector)
511 {
512 address = insn_word & 0x0000001F;
513 sprintf (operand[0], "0x%lX", address);
514 }
515 else
516 {
517 address = insn_word & 0x0000FFFF;
518 /* Get the operands for the DB instructions. */
519 if (insn->tm->operands == 2)
520 {
521 get_register_operand (((insn_word & 0x01C00000) >> 22) + REG_AR0, operand[0]);
522 if (insn_word & PCRel)
523 {
524 sprintf (operand[1], "%d", (short) address);
525 print_label = 1;
526 }
527 else
528 get_register_operand (insn_word & 0x0000001F, operand[1]);
529 }
530 /* Get the operands for the standard branches. */
531 else if (insn->tm->operands == 1)
532 {
533 if (insn_word & PCRel)
534 {
535 address = (short) address;
536 sprintf (operand[0], "%ld", address);
537 print_label = 1;
538 }
539 else
540 get_register_operand (insn_word & 0x0000001F, operand[0]);
541 }
542 }
543 info->fprintf_func (info->stream, " %s %s%c%s", insn->tm->name,
544 operand[0][0] ? operand[0] : "",
545 operand[1][0] ? ',' : ' ',
546 operand[1][0] ? operand[1] : "");
547 /* Print destination of branch in relation to current symbol. */
548 if (print_label && info->symbols)
549 {
550 asymbol *sym = *info->symbols;
551
552 if ((insn->tm->opcode_modifier == PCRel) && (insn_word & PCRel))
553 {
554 address = (_pc + 1 + (short) address) - ((sym->section->vma + sym->value) / 4);
555 /* Check for delayed instruction, if so adjust destination. */
556 if (insn_word & 0x00200000)
557 address += 2;
558 }
559 else
560 {
561 address -= ((sym->section->vma + sym->value) / 4);
562 }
563 if (address == 0)
564 info->fprintf_func (info->stream, " <%s>", sym->name);
565 else
566 info->fprintf_func (info->stream, " <%s %c %d>", sym->name,
567 ((short) address < 0) ? '-' : '+',
568 abs (address));
569 }
570 return 1;
571}
572
573int
574get_indirect_operand (fragment, size, buffer)
575 unsigned short fragment;
576 int size;
577 char *buffer;
578{
579 unsigned char mod;
580 unsigned arnum;
581 unsigned char disp;
582
583 if (buffer == NULL)
584 return 0;
585 /* Determine which bits identify the sections of the indirect
586 operand based on the size in bytes. */
587 switch (size)
588 {
589 case 1:
590 mod = (fragment & 0x00F8) >> 3;
591 arnum = (fragment & 0x0007);
592 disp = 0;
593 break;
594 case 2:
595 mod = (fragment & 0xF800) >> 11;
596 arnum = (fragment & 0x0700) >> 8;
597 disp = (fragment & 0x00FF);
598 break;
599 default:
600 return 0;
601 }
602 {
603 const ind_addr_type *current_ind = tic30_indaddr_tab;
604 for (; current_ind < tic30_indaddrtab_end; current_ind++)
605 {
606 if (current_ind->modfield == mod)
607 {
608 if (current_ind->displacement == IMPLIED_DISP && size == 2)
609 {
610 continue;
611 }
612 else
613 {
614 size_t i, len;
615 int bufcnt;
616
617 len = strlen (current_ind->syntax);
618 for (i = 0, bufcnt = 0; i < len; i++, bufcnt++)
619 {
620 buffer[bufcnt] = current_ind->syntax[i];
621 if (buffer[bufcnt - 1] == 'a' && buffer[bufcnt] == 'r')
622 buffer[++bufcnt] = arnum + '0';
623 if (buffer[bufcnt] == '('
624 && current_ind->displacement == DISP_REQUIRED)
625 {
626 sprintf (&buffer[bufcnt + 1], "%u", disp);
627 bufcnt += strlen (&buffer[bufcnt + 1]);
628 }
629 }
630 buffer[bufcnt + 1] = '\0';
631 break;
632 }
633 }
634 }
635 }
636 return 1;
637}
638
639int
640get_register_operand (fragment, buffer)
641 unsigned char fragment;
642 char *buffer;
643{
644 const reg *current_reg = tic30_regtab;
645
646 if (buffer == NULL)
647 return 0;
648 for (; current_reg < tic30_regtab_end; current_reg++)
649 {
650 if ((fragment & 0x1F) == current_reg->opcode)
651 {
652 strcpy (buffer, current_reg->name);
653 return 1;
654 }
655 }
656 return 0;
657}
658
659int
660cnvt_tmsfloat_ieee (tmsfloat, size, ieeefloat)
661 unsigned long tmsfloat;
662 int size;
663 float *ieeefloat;
664{
665 unsigned long exp, sign, mant;
666 union {
667 unsigned long l;
668 float f;
669 } val;
670
671 if (size == 2)
672 {
673 if ((tmsfloat & 0x0000F000) == 0x00008000)
674 tmsfloat = 0x80000000;
675 else
676 {
677 tmsfloat <<= 16;
678 tmsfloat = (long) tmsfloat >> 4;
679 }
680 }
681 exp = tmsfloat & 0xFF000000;
682 if (exp == 0x80000000)
683 {
684 *ieeefloat = 0.0;
685 return 1;
686 }
687 exp += 0x7F000000;
688 sign = (tmsfloat & 0x00800000) << 8;
689 mant = tmsfloat & 0x007FFFFF;
690 if (exp == 0xFF000000)
691 {
692 if (mant == 0)
693 *ieeefloat = ERANGE;
694 if (sign == 0)
695 *ieeefloat = 1.0 / 0.0;
696 else
697 *ieeefloat = -1.0 / 0.0;
698 return 1;
699 }
700 exp >>= 1;
701 if (sign)
702 {
703 mant = (~mant) & 0x007FFFFF;
704 mant += 1;
705 exp += mant & 0x00800000;
706 exp &= 0x7F800000;
707 mant &= 0x007FFFFF;
708 }
709 if (tmsfloat == 0x80000000)
710 sign = mant = exp = 0;
711 tmsfloat = sign | exp | mant;
712 val.l = tmsfloat;
713 *ieeefloat = val.f;
714 return 1;
715}
Note: See TracBrowser for help on using the repository browser.