Category : C Source Code
Archive   : M68KDIS.ZIP
Filename : UTILS.C

 
Output of file : UTILS.C contained in archive : M68KDIS.ZIP
/*
* 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.
*/

#include
#include
#include
#include
#include "dis.h"

int
immsprintf(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)
return sprintf(s, "%ld!%s%lx", value, sign, absvalue);
else
return sprintf(s, "%ld", value);
}

long
signextend(long value, int bits)
{
switch (bits) {
case 8:
value &= 0xFF;
if (value & 0x80)
value |= ~0xFF;
break;
case 16:
value &= 0xFFFF;
if (value & 0x8000)
value |= ~0xFFFF;
break;
case 32:
value &= 0xFFFFFFFF;
if (value & 0x80000000)
value |= ~0xFFFFFFFF;
break;
}

return value;
}

#include

char instbuf[BUFSIZ];
size_t leninstbuf = 0;

int
nextword(word_t *wp)
{
unsigned char c[sizeof(word_t)];
int i;

if (fread(c, 1, sizeof(word_t), infp) == sizeof(word_t)) {
for (*wp = 0, i = 0; i < sizeof(word_t); i++)
*wp += c[i] << (CHAR_BIT * (sizeof(word_t) - 1 - i));
pc += sizeof(word_t);
curoffset += sizeof(word_t);
for (i = 0; i < sizeof(word_t); i++) {
sprintf(&instbuf[leninstbuf], "%0*x", sizeof(word_t),
c[i]);
leninstbuf += sizeof(word_t);
}
return 0;
} else
return -1;
}

long
getval(int size, int *failure)
{
word_t extra[2];
long value;

if (nextword(&extra[0]) == -1) {
*failure = -1;
return 0;
}
switch (size) {
case BYTE:
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;
}

static int
scale(int s)
{
switch (s) {
case 0: return 1; break;
case 1: return 2; break;
case 2: return 4; break;
case 3: return 8; break;
}
}

char *
Areg(int reg)
{
static char s[2] = "A0";

if (sp && reg == 7)
return "SP";
else {
s[1] = reg + '0';
return s;
}
}

void
Areg2(char buf[], char c, int reg)
{
if (c == 'A')
sprintf(buf, "%2.2s", Areg(reg));
else
sprintf(buf, "D%d", reg);
}

static int
extended(char *s, const char *reg)
{
word_t extra;
addr_t bd;
addr_t od;
int comma;
int n = 0;
int failure;
char reg2[2];


if (nextword(&extra) == -1)
return -1;
if (chip < MC68020 || (extra & 0x0100) == 0) {
/* Brief format */
if (chip >= MC68020)
n += sprintf(s, "(");
n += immsprintf(s + n, (long)signextend(extra, 8));
n += sprintf(s + n, "%s", (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 (chip >= MC68020 && ((extra >> 9) & 3))
n += sprintf(s + n, "*%d", scale((extra >> 9) & 3));
n += sprintf(s + n, ")");
} else {
/* Full format */
switch ((extra >> 4) & 3) {
case 0:
/* error */
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;
}
switch (extra & 3) {
case 0:
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 (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));
}
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");

#if 0
/* should reduce to PC-relative addressing sometimes */
if ( && pcrelative) {
required[flags & 3] = longval + savedpc;
flags++;
}
#endif
}

return 0;
}

int
getea(char *s, word_t reg, word_t mode, int size)
{
long longval;
addr_t savedpc;
char creg[3];
int failure;

switch (mode) {
case 0:
/* Data register direct */
sprintf(s, "D%d", reg);
break;
case 1:
/* Address register direct */
sprintf(s, "%2.2s", Areg(reg));
break;
case 2:
/* Address register indirect */
sprintf(s, "(%2.2s)", Areg(reg));
break;
case 3:
/* Address register indirect with postincrement */
sprintf(s, "(%2.2s)+", Areg(reg));
break;
case 4:
/* Address register indirect with predecrement */
sprintf(s, "-(%2.2s)", Areg(reg));
break;
case 5:
/* Address register indirect with displacement */
longval = getval(WORD, &failure);
if (failure)
return failure;
if (chip >= MC68020)
sprintf(s, "(%ld,%2.2s)", longval, Areg(reg));
else
sprintf(s, "%ld(%2.2s)", longval, Areg(reg));
break;
case 6:
/*
* Address register indirect
* with index and displacement
*/
sprintf(creg, "%2.2s", Areg(reg));
return extended(s, creg);
break;
case 7:
switch (reg) {
case 0:
/* Absolute short */
longval = getval(WORD, &failure);
if (failure)
return failure;
sprintf(s, "$%0*lx.W", 2 * sizeof(word_t), longval);
break;
case 1:
/* Absolute long */
longval = getval(LONGWORD, &failure);
if (failure)
return failure;
sprintf(s, "$%0*lx.L", 4 * sizeof(word_t), longval);
break;
case 2:
/* Program counter indirect with displacement */
savedpc = pc;
longval = getval(WORD, &failure);
if (failure)
return failure;

if (pass == DCLABELSPASS) {
if (longval + savedpc >= initialpc
|| longval + savedpc <= initialpc + maxoffset)
insts[longval + savedpc
- initialpc].flags |= ISLABEL;
} else if (pass == FIRSTPASS && pcrelative) {
required[flags & 3] = longval + savedpc;
flags++;
} else if (pass == LASTPASS
&& longval + savedpc >= initialpc
&& longval + savedpc <= initialpc + maxoffset
&& insts[longval + savedpc - initialpc].labelnum)
sprintf(s, "L%d",
insts[longval + savedpc - initialpc].labelnum);
else /* if ((pass == FIRSTPASS || pass == LASTPASS)
&& !pcrelative
|| pass == DEBUGPASS
|| pass == LASTPASS && pcrelative
&& longval + savedpc > initialpc + maxoffset) { */
if (chip >= MC68020)
sprintf(s, "(%ld,PC)!$%lx", longval,
longval + savedpc);
else
sprintf(s, "%ld(PC)!$%lx", longval,
longval + savedpc);
break;
case 3:
/*
* Program counter indirect
* with index and displacement
*/
return extended(s, "PC");
break;
case 4:
/* Immediate */
s[0] = '#';
longval = getval(size, &failure);
if (failure)
return failure;
immsprintf(s + 1, longval);
break;
}
}

return 0;
}

#include

void
instprint(int lflags, const char *name, ...)
{
va_list ap;
int operands = f2ops(lflags);
char *cp;
size_t i;

va_start(ap, name);

if (pass == LASTPASS || pass == DEBUGPASS) {
fprintf(outfp, "%08x", (int)ppc);
if (lower)
for (i = 0; i < leninstbuf; i++)
instbuf[i] = tolower(instbuf[i]);
fprintf(outfp, "\t%-20.*s", (int)leninstbuf, instbuf);
if (pass == LASTPASS && insts[ppc - initialpc].labelnum)
fprintf(outfp, "L%-4d", insts[ppc - initialpc].labelnum);
else
fprintf(outfp, " ");
if (lower) {
char *newname;
size_t len = strlen(name);

if (newname = malloc(len + 1)) {
for (i = 0; i < len; i++)
newname[i] = tolower(name[i]);
newname[len] = '\0';
fprintf(outfp, "\t%s", newname);
free(newname);
} else
fprintf(outfp, "\t%s", name);
} else
fprintf(outfp, "\t%s", name);
if (lower) {
if (lflags & PBYTE)
fprintf(outfp, ".b");
else if (lflags & PWORD)
fprintf(outfp, ".w");
else if (lflags & PLONGWORD)
fprintf(outfp, ".l");
} else {
if (lflags & PBYTE)
fprintf(outfp, ".B");
else if (lflags & PWORD)
fprintf(outfp, ".W");
else if (lflags & PLONGWORD)
fprintf(outfp, ".L");
}

for (i = 1; i <= operands; i++) {
putc(i == 1 ? '\t' : ',', outfp);
if (lflags & sharp2f(i))
putc('#', outfp);
cp = va_arg(ap, char *);
if (lower && (cp[0] != 'L' || !isdigit(cp[1]))) {
char *cp2 = cp - 1;

while (*++cp2)
*cp2 = tolower(*cp2);
}
fprintf(outfp, "%s", cp);
}
putc('\n', outfp);
}

leninstbuf = 0;
ppc = pc;

va_end(ap);
}


  3 Responses to “Category : C Source Code
Archive   : M68KDIS.ZIP
Filename : UTILS.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/