📄 dis_68k.c
字号:
/* MC68000 Disassembler:
* ELS...
* This disassembler is a hack of the mc68dis disassembler.
* NOTE: this adds approximately 20K to the size of the monitor.
*
* General notice:
* This code is part of a boot-monitor package developed as a generic base
* platform for embedded system designs. As such, it is likely to be
* distributed to various projects beyond the control of the original
* author. Please notify the author of any enhancements made or bugs found
* so that all may benefit from the changes. In addition, notification back
* to the author will allow the new user to pick up changes that may have
* been made by other users after this version of the code was distributed.
*
* Note1: the majority of this code was edited with 4-space tabs.
* Note2: as more and more contributions are accepted, the term "author"
* is becoming a mis-representation of credit.
*
* Original author: Ed Sutter
* Email: esutter@lucent.com
* Phone: 908-582-2351
*/
#include "config.h"
#if INCLUDE_DISASSEMBLER
#include "cpu.h"
#include "ctype.h"
#include "genlib.h"
#include "stddefs.h"
#include "warmstart.h"
#define NULL 0
#define BIT3(x) (int)((x >> 3) & 0x1L) /* ----x--- bit 3 */
#define BIT5(x) (int)((x >> 5) & 0x1L) /* --x----- bit 5 */
#define BIT6(x) (int)((x >> 6) & 0x1L) /* -x------ bit 6 */
#define BIT7(x) (int)((x >> 7) & 0x1L) /* x------- bit 7 */
#define BIT8(x) (int)((x >> 8) & 0x1L)
#define BIT10(x) (int)((x >> 10) & 0x1L)
#define BIT11(x) (int)((x >> 11) & 0x1L)
#define BIT12(x) (int)((x >> 12) & 0x1L)
#define BIT15(x) (int)((x >> 15) & 0x1L)
#define BITS15_8(x) (int)((x >> 8) & 0xffL)
#define BITS15_7(x) (int)((x >> 7) & 0x1ffL)
#define BITS14_12(x) (int)((x >> 12) & 0x7L)
#define BITS11_9(x) (int)((x >> 9) & 0x7L) /* bits 11 through 9 */
#define BITS11_8(x) (int)((x >> 8) & 0xfL) /* bits 11 through 8 */
#define BITS10_9(x) (int)((x >> 9) & 0x3L) /* bits 10 through 9 */
#define BITS10_8(x) (int)((x >> 8) & 0x7L) /* bits 10 through 8 */
#define BITS8_6(x) (int)((x >> 6) & 0x7L) /* bits 8 through 6 */
#define BITS8_3(x) (int)((x >> 3) & 0x3fL) /* bits 8 through 3 */
#define BITS7_6(x) (int)((x >> 6) & 0x3L) /* bits 7 through 6 */
#define BITS5_4(x) (int)((x >> 4) & 0x3L) /* bits 5 through 4 */
#define BITS5_3(x) (int)((x >> 3) & 0x7L) /* bits 5 through 3 */
#define BITS5_0(x) (int)(x & 0x3fL) /* bits 5 through 0 */
#define BITS4_3(x) (int)((x >> 3) & 0x3L) /* bits 4 through 3 */
#define BITS3_0(x) (int)(x & 0xfL) /* bits 3 through 0 */
#define BITS2_0(x) (int)(x & 0x7L) /* bits 2 through 0 */
#define LOW8(x) (int)(x & 0xffL) /* low 8 bits of quantity */
#define HIOF32(x) (int)((x >> 31) & 0x1L) /* sign bit of 32 bit quantity */
#define HI4OF16(x) (int)((x >> 12) & 0xfL)
#define NCPS 8 /* Number of chars per symbol. */
#define NHEX 80 /* Maximum # chars in object per line. */
#define NLINE 33 /* Maximum # chars in mnemonic per line.*/
#define FAIL 0
#define LEAD 1
#define NOLEAD 0
#define TERM 0
#define BYTE 1 /* values for size parm to eff_add */
#define WORD 2
#define LONG 3
#define SIGNED 1 /* immediate value signed or unsigned */
#define UNSIGNED 0
#define NOTSIGNED 0
unsigned short curinstr; /* for saving first part of instruction
when cur2bytes is used to read displ */
unsigned short oldinstr = 0; /* to save previous instruction for
testing that swbeg follows jump */
unsigned short cur2bytes; /* for storing the results of 'get2bytes()' */
static int shownext;
static long loc; /* byte location being disassembled */
/* IMPORTANT: remember that loc is incremented*/
/* only by the getbyte routine */
static char object[NHEX]; /* array to store object code for output*/
static char mneu[NLINE]; /* array to store mnemonic code for output*/
char conv_temp[NHEX]; /* Temporary location for ascii */
/* representation of operands. */
char comp_temp[NHEX]; /* temp for calling compoff */
static char size[] = {
'b','w','l'};
char *cond_codes[] = {
"t ", "f ", "hi ", "ls ",
"cc ", "cs ", "ne ", "eq ",
"vc ", "vs ", "pl ", "mi ",
"ge ", "lt ", "gt ", "le "
};
char *addregs[] = {
"%a0","%a1","%a2","%a3","%a4","%a5","%fp","%sp" };
void confused();
char *eff_add();
void bit_movep_imm(), move_byte(), move_long(), move_word(), miscell();
void addq_subq_scc_dbcc(), bcc_bsr_bra(), moveq(), or_div_sbcd(), sub_subx();
void unassigned(), cmp_eor(), and_mul_abcd_exg(), add_addx(), shft_rot();
void (*code_map[16])() =
{
bit_movep_imm, /* upper nibble 0x0 */
move_byte, /* upper nibble 0x1 */
move_long, /* upper nibble 0x2 */
move_word, /* upper nibble 0x3 */
miscell, /* upper nibble 0x4 */
addq_subq_scc_dbcc, /* upper nibble 0x5 */
bcc_bsr_bra, /* upper nibble 0x6 */
moveq, /* upper nibble 0x7 */
or_div_sbcd, /* upper nibble 0x8 */
sub_subx, /* upper nibble 0x9 */
unassigned, /* upper nibble 0xa */
cmp_eor, /* upper nibble 0xb */
and_mul_abcd_exg, /* upper nibble 0xc */
add_addx, /* upper nibble 0xd */
shft_rot, /* upper nibble 0xe */
unassigned /* upper nibble 0xf */
};
char *DisHelp[] = {
"Disassemble memory",
"{address | .} [lines]",
0,
};
extern int getreg();
/* ELS: With the original disassembler, it attempted to recover from
a confused state by re-syncing on the next line of source.
*/
void
confused()
{
printf("\tDisassembler confused around 0x%lx\n",loc);
monrestart(MISC);
}
/*
* compoff (lng, temp)
*
* This routine will compute the location to which control is to be
* transferred. 'lng' is the number indicating the jump amount
* (already in proper form, meaning masked and negated if necessary)
* and 'temp' is a character array which already has the actual
* jump amount. The result computed here will go at the end of 'temp'.
* (This is a great routine for people that don't like to compute in
* hex arithmetic.)
*/
void
compoff(long lng, char *temp)
{
extern long loc; /* from _extn.c */
lng += loc;
sprintf(temp,"%s <%lx>",temp,lng);
}
/*
* convert (num, temp, flag)
*
* Convert the passed number to hex leaving the result in the
* supplied string array.
* If LEAD is specified, preceed the number with '0' or '0x' to
* indicate the base (used for information going to the mnemonic
* printout). NOLEAD will be used for all other printing (for
* printing the offset, object code, and the second byte in two
* byte immediates, displacements, etc.) and will assure that
* there are leading zeros.
*/
void
convert(num,temp,flag)
unsigned int num;
char temp[];
int flag;
{
if (flag == NOLEAD)
sprintf(temp,"%04x",num);
if (flag == LEAD)
sprintf(temp,"0x%x",num);
}
/*
* get2bytes()
*
* This routine will get 2 bytes, print them in the object file
* and place the result in 'cur2bytes'.
*
*/
void
get2bytes()
{
uchar bytes[16], *bc;
bc = (uchar *)loc;
bytes[0] = bc[0];
bytes[1] = bc[1];
cur2bytes = *(unsigned short *)loc;
loc += 2;
convert( (cur2bytes & 0xffff), bytes, NOLEAD);
sprintf(object,"%s%s ",object, bytes);
}
/*
* print_dis ()
*
* Print the disassembled line, consisting of the object code
* and the mnemonics. The breakpointable line number, if any,
* has already been printed, and 'object' contains the offset
* within the section for the instruction.
*/
void
print_dis()
{
printf("%-35s%s\n",object,mneu);
}
/*
* prt_offset ()
*
* Print the offset, right justified, followed by a ':'.
*/
void
prt_offset()
{
if (shownext)
strcpy(object,"NextInst: ");
else
sprintf(object,"0x%08lx: ",loc);
}
int
disass(ulong at,int lines,int next)
{
int i;
ulong start;
shownext = next;
if ((at == 0) && (lines == 0)) {
lines = 1;
getreg("PC",&loc);
start = loc;
}
else {
loc = at;
start = at;
}
for(i=0;i<lines;i++) {
prt_offset();
mneu[0] = '\0';
oldinstr = curinstr;
get2bytes();
/*save bytes in case eff_add changes it*/
curinstr = cur2bytes;
comp_temp[0] = '\0';
(*code_map[HI4OF16(cur2bytes)])();
/* if there was any pc rel computation
put it at the end of assembly line */
strcat(mneu,comp_temp);
print_dis();
}
return((int)loc - start);
}
int
Dis(int argc,char *argv[])
{
int lines;
ulong at;
if (*argv[1] == '.')
getreg("PC",&at);
else
at = strtoul(argv[1],0,0);
if (argc == 3)
lines = strtol(argv[2],0,0);
else
lines = 8;
while(1) {
disass(at,lines,0);
if (More())
at = loc;
else
break;
}
return(0);
}
void
move_address()
{
strcat(mneu,"mova._ ");
mneu[5] = BIT12(cur2bytes) ? 'w' : 'l';
strcat(mneu,eff_add(BITS5_3(cur2bytes),BITS2_0(cur2bytes),
BIT12(cur2bytes) ? WORD : LONG,NOTSIGNED));
sprintf(mneu,"%s,%s",mneu,addregs[BITS11_9(curinstr)]);
}
void
bit_movep_imm()
{
static char *misc_ops[4] = {
"btst ",
"bchg ",
"bclr ",
"bset "
};
if (BIT8(cur2bytes)) {
if (BITS5_3(cur2bytes) == 1) { /* movep */
strcat(mneu,"movp._ ");
mneu[5] = BIT6(cur2bytes) ? 'l' : 'w';
if (BIT7(cur2bytes))
sprintf(mneu,"%s%%d%d,%s",mneu,
BITS11_9(curinstr),
eff_add(5,BITS2_0(cur2bytes),
NULL,NULL));
else
sprintf(mneu,"%s%s,%%d%d",mneu,
eff_add(5,BITS2_0(cur2bytes),NULL,
NULL), BITS11_9(curinstr));
}
else { /* dynamic bit */
strcat(mneu,misc_ops[BITS7_6(cur2bytes)]);
sprintf(mneu,"%s%%d%d,%s",mneu,BITS11_9(curinstr),
eff_add(BITS5_3(cur2bytes),BITS2_0(cur2bytes),
NULL,NULL));
}
return;
} /* end if (BIT8(cur2bytes)) */
switch(BITS11_9(cur2bytes)) {
char add_temp[16];
case 0:
if (BITS7_6(cur2bytes) == 3)
confused();
strcat(mneu,"ori._ ");
mneu[4] = size[BITS7_6(cur2bytes)];
strcat(mneu,eff_add(7,4,BITS7_6(cur2bytes) + 1,UNSIGNED));
strcat(mneu,",");
if (BITS5_0(curinstr) == 074) {
if (BITS7_6(curinstr) == 0)
strcat(mneu,"%cc");
else if (BITS7_6(curinstr) == 1)
strcat(mneu,"%sr");
else
confused();
}
else
strcat(mneu,eff_add(BITS5_3(curinstr),
BITS2_0(curinstr),NULL,NULL));
return;
case 1:
if (BITS7_6(cur2bytes) == 3)
confused();
strcat(mneu,"andi._ ");
mneu[5] = size[BITS7_6(cur2bytes)];
strcat(mneu,eff_add(7,4,BITS7_6(cur2bytes) + 1,UNSIGNED));
strcat(mneu,",");
if (BITS5_0(curinstr) == 074) {
if (BITS7_6(curinstr) == 0)
strcat(mneu,"%cc");
else if (BITS7_6(curinstr) == 1)
strcat(mneu,"%sr");
else
confused();
}
else
strcat(mneu,eff_add(BITS5_3(curinstr),
BITS2_0(curinstr),NULL,NULL));
return;
case 2:
if ((BITS7_6(cur2bytes) == 3) || (BITS5_0(cur2bytes) == 074))
confused();
strcat(mneu,"subi._ ");
mneu[5] = size[BITS7_6(cur2bytes)];
strcat(mneu,eff_add(7,4,BITS7_6(cur2bytes) + 1,UNSIGNED));
strcat(mneu,",");
strcat(mneu,eff_add(BITS5_3(curinstr),BITS2_0(curinstr),
NULL,NULL));
return;
case 3:
if ((BITS7_6(cur2bytes) == 3) || (BITS5_0(cur2bytes) == 074))
confused();
strcat(mneu,"addi._ ");
mneu[5] = size[BITS7_6(cur2bytes)];
strcat(mneu,eff_add(7,4,BITS7_6(cur2bytes) + 1,UNSIGNED));
strcat(mneu,",");
strcat(mneu,eff_add(BITS5_3(curinstr),BITS2_0(curinstr),
NULL,NULL));
return;
case 4:
strcat(mneu,misc_ops[BITS7_6(cur2bytes)]);
strcat(mneu,eff_add(7,4,(BITS7_6(cur2bytes) ==1) ?
BYTE : WORD,UNSIGNED));
strcat(mneu,",");
strcat(mneu,eff_add(BITS5_3(curinstr),
BITS2_0(curinstr),NULL,NULL));
return;
case 5:
if (BITS7_6(cur2bytes) == 3)
confused();
strcat(mneu,"eori._ ");
mneu[5] = size[BITS7_6(cur2bytes)];
strcat(mneu,eff_add(7,4,BITS7_6(cur2bytes) + 1,UNSIGNED));
strcat(mneu,",");
if (BITS5_0(curinstr) == 074) {
if (BITS7_6(curinstr) == 0)
strcat(mneu,"%cc");
else if (BITS7_6(curinstr == 1))
strcat(mneu,"%sr");
else
confused();
}
else
strcat(mneu,eff_add(BITS5_3(curinstr),
BITS2_0(curinstr),NULL,NULL));
return;
case 6:
if ((BITS7_6(cur2bytes) == 3) || (BITS5_0(cur2bytes) == 074))
confused();
strcat(mneu,"cmpi._ ");
mneu[5] = size[BITS7_6(cur2bytes)];
strcpy(add_temp,eff_add(7,4,BITS7_6(cur2bytes)+1,NOTSIGNED));
strcat(mneu,eff_add(BITS5_3(curinstr),BITS2_0(curinstr),
NULL,NULL));
strcat(mneu,",");
strcat(mneu,add_temp);
return;
#ifdef M68010
case 7:
{
short osz, regtype, regnum, movsdir;
char curea[24], rreg[6];
short ea1, eareg;
osz = BITS7_6(cur2bytes);
if (osz == 3)
confused();
ea1 = BITS5_3(cur2bytes);
eareg = BITS2_0(cur2bytes);
strcat(mneu,"movs.");
strcat(mneu,(osz==2)?("l"):( (osz==1)?("w"):("b") ));
strcat(mneu," ");
get2bytes();
movsdir = BIT11(cur2bytes);
regtype = BIT15(cur2bytes);
regnum = BITS14_12(cur2bytes);
strcpy(curea,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -