📄 utils.c
字号:
/* * Author: Christopher G. Phillips * Copyright (C) 1994 All Rights Reserved * * NOTICE * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby granted * provided that the above copyright notice appear in all copies and * that both the copyright notice and this permission notice appear in * supporting documentation. * * The author makes no representations about the suitability of this * software for any purpose. This software is provided ``as is'' * without express or implied warranty. *//* * Various utility functions including formatting effective addresses, * reading input (correctly!), and printing are here. */#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <ctype.h>#include <math.h>#include <float.h>#include <limits.h>#include "dis.h"/* * Format immediate constant ``value'' into ``s''. */intimmsprintf(char *s, long value){ long absvalue; char *sign; if (pass == FIRSTPASS) return 0; if (value < 0) { absvalue = -value; sign = "-$"; } else { absvalue = value; sign = "$"; } if (absvalue > 9 || value == LONG_MIN) return sprintf(s, "%ld!%s%lx", value, sign, absvalue); else return sprintf(s, "%ld", value);}/* * Sign-extend ``value'' from a ``bits''-bit value to a long. */longsignextend(long value, int bits){ switch (bits) { case 8: value &= 0xff; if (value & 0x80) value |= ~0xffL; break; case 16: value &= 0xffff; if (value & 0x8000) value |= ~0xffffL; break; case 32: value &= 0xffffffff; if (value & 0x80000000) value |= ~0xffffffffL; break; } return value;}char instbuf[512];size_t leninstbuf = 0;/* * Read a word from the input file. Put its numerical value in *wp. */intnextword(m68kword *wp){ unsigned char c[WORDSIZE]; size_t i; if (fread(c, 1, WORDSIZE, infp) == WORDSIZE) { for (*wp = 0, i = 0; i < WORDSIZE; i++) *wp += c[i] << (CHAR_BIT * (WORDSIZE - 1 - i)); pc += WORDSIZE; curoffset += WORDSIZE; for (i = 0; i < WORDSIZE; i++) { sprintf(&instbuf[leninstbuf], "%0*x", WORDSIZE, c[i]); leninstbuf += WORDSIZE; } return 0; } else return -1;}/* * Get a sign-extended value of type ``size'' from the input file. */longgetval(int size, int *failure){ m68kword extra[2]; long value; if (nextword(&extra[0]) == -1) { *failure = -1; return 0; } switch (size) { case BYTE:#if 0 if (extra[0] & 0xff00) { *failure = -1; return 0; } else#endif value = signextend(extra[0], 8); break; case WORD: value = signextend(extra[0], 16); break; case LONGWORD: if (nextword(&extra[1]) == -1) { *failure = -1; return 0; } value = signextend(((long)extra[0] << 16) | extra[1], 32); break; default: *failure = -1; return 0; break; } *failure = 0; return value;}/* * Translate scale bits to a scaling factor. */static intscale(int s){ switch (s) { case 0: return 1; break; case 1: return 2; break; case 2: return 4; break; case 3: return 8; break; } /* NOTREACHED */}/* * Format address register ``reg'' taking ``sp'' into account. */char *Areg(int reg){ static char s[2] = "A0"; if (sp && reg == 7) return "SP"; else { s[1] = reg + '0'; return s; }}/* * Format register ``reg''. */voidAreg2(char *s, char c, int reg){ if (c == 'A') sprintf(s, "%2.2s", Areg(reg)); else sprintf(s, "D%d", reg);}/* * Extended mode for extension words. * * The formatted text goes in ``s''. * Return 0 for success, negative for failure. */static intextended(char *s, const char *reg, int size){ m68kword extra; m68kaddr bd; m68kaddr od; m68kaddr savedpc; int comma; int n = 0; int failure; char reg2[2]; savedpc = pc; if (nextword(&extra) == -1) return -1; if (CPU(chip) < MC68020 || (extra & 0x0100) == 0) { /* Brief format */ long value; /* * Format is as follows: * * Bits Name * 15 Index register type (D/A, 0 if D) * 12-14 Index register number * 11 Index size (W/L, 0 if sign-extended word) * 9-10 Scale (00 = 1, 01 = 2, 10 = 4, 11 = 8) * 8 Must be 0 * 0-7 Displacement */ if (CPU(chip) >= MC68020) n += sprintf(s, "("); value = (long)signextend(extra, 8); if (strcmp(reg, "PC") == 0) value += WORDSIZE; n += immsprintf(s + n, value); n += sprintf(s + n, "%s", (CPU(chip) < MC68020) ? "(" : ","); Areg2(reg2, (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7); n += sprintf(s + n, "%s,%2.2s.%c", reg, reg2, (extra & 0x0800) ? 'L' : 'W'); if (CPU(chip) >= MC68020 && ((extra >> 9) & 3)) n += sprintf(s + n, "*%d", scale((extra >> 9) & 3)); n += sprintf(s + n, ")"); } else { /* Full format */ /* * Format is as follows: * * Bits Name * 15 Index register type (D/A, 0 if D) * 12-14 Index register number * 11 Index size (W/L, 0 if sign-extended word) * 9-10 Scale (00 = 1, 01 = 2, 10 = 4, 11 = 8) * 8 Must be 1 * 7 Base suppress (1 if base register suppressed) * 6 Index suppress (1 if index register suppressed) * 4-5 Base displacement size (00 = reserved, 01 = null, 10 = word, 11 = long) * 3 Must be 0 * 0-2 Index/Indirect selection * I/IS combinations: * * IS I/IS Operation * 0 000 No memory indirection * 0 001 Indirect preindexed with null outer displacement * 0 010 Indirect preindexed with word od * 0 011 Indirect preindexed with long od * 0 101 Indirect postindexed with null od * 0 110 Indirect postindexed with word od * 0 111 Indirect postindexed with long od * 1 000 No memory indirection * 1 001 Memory indirect with null od * 1 010 Memory indirect with word od * 1 011 Memory indirect with long od */ /* * Get base displacement */ switch ((extra >> 4) & 3) { case 0: return -1; break; case 1: bd = 0; break; case 2: bd = getval(WORD, &failure); if (failure) return failure; break; case 3: bd = getval(LONGWORD, &failure); if (failure) return failure; break; } /* * Check if collapses to PC-relative */ if ((extra & 0x01cf) == 0x0140) { if (pass == DCLABELSPASS) { if (bd + savedpc >= initialpc && bd + savedpc <= initialpc + maxoffset) { insts[bd + savedpc - initialpc].flags |= ISLABEL; if (!insts[ppc - initialpc].size && insts[ppc - initialpc].flags & ISFPU) insts[bd + savedpc - initialpc].flags |= ftype2lis(size); } } else if (pass == FIRSTPASS && pcrelative) { required[flags & 3] = bd + savedpc; flags++; } else if (pass == LASTPASS && bd + savedpc >= initialpc && bd + savedpc <= initialpc + maxoffset && insts[bd + savedpc - initialpc].labelnum) sprintf(s, "L%d", insts[bd + savedpc - initialpc].labelnum); else /* if ((pass == FIRSTPASS || pass == LASTPASS) && !pcrelative || pass == DEBUGPASS || pass == LASTPASS && pcrelative && bd + savedpc > initialpc + maxoffset) */ { if (bd) sprintf(s, "(%ld,PC)!$%lx", bd, bd + savedpc); else sprintf(s, "(PC)!$%lx", savedpc); } return 0; } switch (extra & 3) { case 0: /* FALLTHROUGH */ case 1: od = 0; break; case 2: od = getval(WORD, &failure); if (failure) return failure; break; case 3: od = getval(LONGWORD, &failure); if (failure) return failure; break; } n += sprintf(s + n, "("); if (extra & 3) n += sprintf(s + n, "["); if (comma = bd) n += immsprintf(s + n, (long)bd); if ((extra & 0x0080) == 0) { /* * Base suppress is 0. */ if (comma) n += sprintf(s + n, ","); n += sprintf(s + n, "%s", reg); comma = 1; } else if (strcmp(reg, "PC") == 0) { if (comma) n += sprintf(s + n, ","); n += sprintf(s + n, "ZPC"); comma = 1; } if (extra & 4) { n += sprintf(s + n, "]"); comma = 1; } if ((extra & 0x0040) == 0) { /* * Index suppress is 0. */ if ((extra & 7) == 4) return -1; if (comma) n += sprintf(s + n, ","); Areg2(reg2, (extra & 0x8000) ? 'A' : 'D', (extra >> 12) & 7); n += sprintf(s + n, "%2.2s.%c", reg2, (extra & 0x0800) ? 'L' : 'W'); if ((extra >> 9) & 3) n += sprintf(s + n, "*%d", scale((extra >> 9) & 3)); } else if (extra & 4) return -1; if ((extra & 3) && (extra & 4) == 0) { n += sprintf(s + n, "]"); comma = 1; } if (od) { if (comma) n += sprintf(s + n, ","); n += immsprintf(s + n, (long)od); } if (n) { if (s[n - 1] != '(') n += sprintf(s + n, ")"); else { s[n - 1] = '\0'; if (--n == 0) sprintf(s, "0"); } } else sprintf(s, "0"); } return 0;}/* * The next few functions convert hexadecimal nibble values * to a floating-point value (and format it). */#define BIT(p,n) ((p)[(n) / 32] & (1UL << (32 - (n) % 32 - 1)))/* * Is the mantissa zero? */static intzeromantissa(u32bit_t *p, size_t firstbit, size_t lastbit){ size_t bit; for (bit = firstbit; bit <= lastbit; bit++) if (BIT(p, bit)) return 0; return 1;}/* * Convert the input data in *lwp from bits ``firstbit'' to ``lastbit'' * into a mantissa. Note that the *highest* bit is considered bit 0 here. */static doublestod(u32bit_t *lwp, size_t firstbit, size_t lastbit){ double result = 1.0; double value = 0.5; size_t bit; for (bit = firstbit; bit <= lastbit && value; bit++) { if (BIT(lwp, bit)) result += value; value /= 2.0; } return result;}/* * Convert the input data in *longwords into a floating-point value * of floating-point type ``type'' and place a human-readable version in ``s''. * Return -1 if NaN or Denormalized, else 0. */intfpoint(u32bit_t *longwords, int type, char *s){ short exponent; short sign; short zero; short maxexp; short minexp; size_t firstbit; size_t lastbit; int rval = 0; /* return -1 if NaN or Denormalized */ /* These are for PACKED */ short mantissa[17]; short lastnonzero; short firstnonzero; size_t i; sign = (longwords[0] & 0x80000000) != 0; switch (type) { case SINGLE: /* * Format: * * 1 bit sign * 8 bits exponent (biased by 0x7f) * 23 bits mantissa (implicit leading bit * left of implied binary point) */ exponent = ((longwords[0] >> (32 - (8+1))) & 0xff) - 0x7f; firstbit = 31 - 22; lastbit = 31; zero = zeromantissa(longwords, firstbit, lastbit); maxexp = 0x80; minexp = -0x7f; break; case DOUBLE: /* * Format: * * 1 bit sign * 11 bits exponent (biased by 0x3ff) * 52 bits mantissa (implicit leading bit * left of implied binary point) */ exponent = ((longwords[0] >> (32 - (11+1))) & 0x7ff) - 0x3ff; firstbit = 63 - 51;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -