📄 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"#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 0unsigned 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.*/voidconfused(){ 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.) */voidcompoff(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. */voidconvert(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'. * */voidget2bytes(){ 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. */voidprint_dis(){ printf("%-35s%s\n",object,mneu);}/* * prt_offset () * * Print the offset, right justified, followed by a ':'. */voidprt_offset(){ if (shownext) strcpy(object,"NextInst: "); else sprintf(object,"0x%08lx: ",loc);}intdisass(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);}intDis(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);}voidmove_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)]);}voidbit_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, eff_add(ea1,eareg,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -