From 32d1d2b36a8df0a7eef73b76820fd404fee58336 Mon Sep 17 00:00:00 2001 From: chopps Date: Fri, 4 Mar 1994 13:44:30 +0000 Subject: [PATCH] 1 pounds of coffee, 6 packs of smokes and a couple pizzas. This is for backup purposes only. It works in a hacked up user-mode setting. I have to get ddb working with amiga's to test this any further though. I tested the main opcodes pretty much, not too much testing on the fpu ops and it printed pflusha :^) major externally visible changes still planned. --- sys/arch/m68k/m68k/db_disasm.c | 3148 +++++++++++++++++++++++++++++++- sys/arch/m68k/m68k/db_disasm.h | 423 +++++ 2 files changed, 3553 insertions(+), 18 deletions(-) create mode 100644 sys/arch/m68k/m68k/db_disasm.h diff --git a/sys/arch/m68k/m68k/db_disasm.c b/sys/arch/m68k/m68k/db_disasm.c index d9b60f46fe44..38a2313d1064 100644 --- a/sys/arch/m68k/m68k/db_disasm.c +++ b/sys/arch/m68k/m68k/db_disasm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1993 Christopher G. Demetriou + * Copyright (c) 1994 Christian E. Hopps * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -12,7 +12,7 @@ * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: - * This product includes software developed by Christopher G. Demetriou. + * This product includes software developed by Christian E. Hopps. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * @@ -27,29 +27,3141 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: db_disasm.c,v 1.2 1994/01/28 23:45:11 jtc Exp $ + * $Id: db_disasm.c,v 1.3 1994/03/04 13:44:30 chopps Exp $ + */ +/* + * Notes: + * + * Much can be done with this format, with a lot of hacking even + * a moto emul. could be built. However things like symbol lookup + * and reference are needed right away. + * + * the only functions that use the "get_xxx()" notation should be + * ones that modify things in a dis_buffer_t besides the buffers. + * (namely the used field) + * + * An attempt has been made to *always* increment dbuf->used++ immediately + * after referencing a value beyond the current "short *" address. + * this meant either only referencing the value once or placing it in + * a local var. If you play with this keep this style. Its very useful + * in eliminating a very easy to make hard to find logic error. + * + * I broke style in 2 ways with one macro ``addchar()'' + * However it makes sense, consider that it is called *a lot* and + * commonly with things like ","'s + * + * *dbuf->casm++ = ','; || ADDCHAR(dbuf,','); || addchar(dbuf,','); + * I chose: + * addchar(','); + * + * If this is not enough to convince you, please load up you emacs or + * vi and do a fancy regex-replace, and compare for yourself. + * (The 2 rules of style I broke if you failed to notice are: + * 1: lower case macro name 2: implicit reference to local var name.) + * + * (chopps - March 1, 1994) */ -/* - * Instruction disassembler. - */ -#include "param.h" -#include "proc.h" +#include + #include -#include #include +#include + +void get_modregstr __P((dis_buffer_t *, int, int, int, int)); +void get_immed __P((dis_buffer_t *, int)); +void get_fpustdGEN __P((dis_buffer_t *, u_short, const char *)); +void addstr __P((dis_buffer_t *, const char *s)); +void prints __P((dis_buffer_t *, int, int)); +void printu __P((dis_buffer_t *, u_int, int)); +void prints_wb __P((dis_buffer_t *, int, int, int)); +void printu_wb __P((dis_buffer_t *, u_int, int, int)); +void prints_bf __P((dis_buffer_t *, int, int, int)); +void printu_bf __P((dis_buffer_t *, u_int, int, int)); +void iaddstr __P((dis_buffer_t *, const char *s)); +void iprints __P((dis_buffer_t *, int, int)); +void iprintu __P((dis_buffer_t *, u_int, int)); +void iprints_wb __P((dis_buffer_t *, int, int, int)); +void iprintu_wb __P((dis_buffer_t *, u_int, int, int)); +void make_cond __P((dis_buffer_t *, int , char *)); +void print_fcond __P((dis_buffer_t *, char)); +void print_mcond __P((dis_buffer_t *, char)); +void print_disp __P((dis_buffer_t *, int, int, int)); +void print_addr __P((dis_buffer_t *, u_long)); +void print_reglist __P((dis_buffer_t *, int, u_short)); +void print_freglist __P((dis_buffer_t *, int, u_short, int)); +void print_fcode __P((dis_buffer_t *, u_short)); + +/* groups */ +void opcode_bitmanip __P((dis_buffer_t *, u_short)); +void opcode_move __P((dis_buffer_t *, u_short)); +void opcode_misc __P((dis_buffer_t *, u_short)); +void opcode_branch __P((dis_buffer_t *, u_short)); +void opcode_coproc __P((dis_buffer_t *, u_short)); +void opcode_0101 __P((dis_buffer_t *, u_short)); +void opcode_1000 __P((dis_buffer_t *, u_short)); +void opcode_addsub __P((dis_buffer_t *, u_short)); +void opcode_1010 __P((dis_buffer_t *, u_short)); +void opcode_1011 __P((dis_buffer_t *, u_short)); +void opcode_1100 __P((dis_buffer_t *, u_short)); +void opcode_1110 __P((dis_buffer_t *, u_short)); +void opcode_fpu __P((dis_buffer_t *, u_short)); +void opcode_mmu __P((dis_buffer_t *, u_short)); +void opcode_mmu040 __P((dis_buffer_t *, u_short)); + +/* subs of groups */ +void opcode_movec __P((dis_buffer_t *, u_short)); +void opcode_divmul __P((dis_buffer_t *, u_short)); +void opcode_movem __P((dis_buffer_t *, u_short)); +void opcode_fmove_ext __P((dis_buffer_t *, u_short, u_short)); +void opcode_pmove __P((dis_buffer_t *, u_short, u_short)); +void opcode_pflush __P((dis_buffer_t *, u_short, u_short)); + +#define addchar(ch) (*dbuf->casm++ = ch) +#define iaddchar(ch) (*dbuf->cinfo++ = ch) + +typedef void dis_func_t __P((dis_buffer_t *, u_short)); + +dis_func_t *const opcode_map[16] = { + opcode_bitmanip, opcode_move, opcode_move, opcode_move, + opcode_misc, opcode_0101, opcode_branch, opcode_move, + opcode_1000, opcode_addsub, opcode_1010, opcode_1011, + opcode_1100, opcode_addsub, opcode_1110, opcode_coproc +}; + +const char *const cc_table[16] = { + "t", "f", "hi", "ls", + "cc", "cs", "ne", "eq", + "vc", "vs", "pl", "mi", + "ge", "lt", "gt", "le" +}; + +const char *const fpcc_table[32] = { + "f", "eq", "ogt", "oge", "olt", "ole", "ogl", "or", + "un", "ueq", "ugt", "uge", "ult", "ule", "ne", "t", + "sf", "seq", "gt", "ge", "lt", "le", "gl", "gle", + "ngle", "ngl", "nle", "nlt", "nge", "ngt", "sne", "st" }; + +const char *const mmcc_table[16] = { + "bs", "bc", "ls", "lc", "ss", "sc", "as", "sc", + "ws", "wc", "is", "ic", "gs", "gc", "cs", "cc" }; + + +const char *const aregs[8] = {"a0","a1","a2","a3","a4","a5","a6","sp"}; +const char *const dregs[8] = {"d0","d1","d2","d3","d4","d5","d6","d7"}; +const char *const fpregs[8] = { + "fp0","fp1","fp2","fp3","fp4","fp5","fp6","fp7" }; +const char *const fpcregs[3] = { "fpiar", "fpsr", "fpcr" }; /* - * Disassemble instruction at 'loc'. 'altfmt' specifies an - * (optional) alternate format. Return address of start of - * next instruction. + * Disassemble intruction at location ``loc'' placing + * output in buffer ``buf'' (which is at least MAX_INSTBUFSIZE large). + * Returns location of next instruction. ``ibuf'' is a buffer also + * of MAX_INSTBUFSIZE if not NULL, that will be filled with extra + * info (e.g. values of things and so forth) */ -db_disasm(loc, altfmt) - db_addr_t loc; - boolean_t altfmt; -{ - /* XXX - obviously should do more than this. */ - return (loc + 2); +static char asm_buffer[1024]; +static char info_buffer[1024]; + +vm_offset_t +db_disasm(loc,mit_syntax) + vm_offset_t loc; + boolean_t mit_syntax; +{ + u_short opc; + dis_func_t *func; + dis_buffer_t dbuf; + char *symname = NULL; + off_t diff; + db_sym_t sym; + struct nlist *nl; + + dbuf.casm = dbuf.dasm = asm_buffer; + dbuf.cinfo = dbuf.info = info_buffer; + dbuf.used = 0; + dbuf.val = (short *)loc; + dbuf.mit = mit_syntax; + + dbuf.dasm[0] = 0; + dbuf.info[0] = 0; + + diff = INT_MAX; + sym = db_search_symbol(loc, DB_STGY_PROC, &diff); + db_symbol_values(sym, &symname, 0); + + /* addstr(&dbuf, "["); */ + if (symname == NULL) + printu (&dbuf, loc, SIZE_LONG); + else if (diff == 0) { + addstr(&dbuf, symname); + iprintu(&dbuf, loc, SIZE_LONG); + iaddstr(&dbuf, ":: "); + } else { + addstr(&dbuf, symname); + addstr(&dbuf, "+"); + printu(&dbuf, diff, SIZE_LONG); + } + addstr(&dbuf, ": "); + + opc = *dbuf.val; + dbuf.used++; + + func = opcode_map[OPCODE_MAP(opc)]; + func(&dbuf, opc); + + db_printf("%s",asm_buffer); + if (info_buffer[0]) + db_printf("\t[%s]\n",info_buffer); + else + db_printf("\n"); + return (loc + sizeof(short)*dbuf.used); } +/* + * Bit manipulation/MOVEP/Immediate. + */ +void +opcode_bitmanip(dbuf, opc) + dis_buffer_t *dbuf; + u_short opc; +{ + char *tmp; + u_short ext; + int sz; + + tmp = NULL; + + switch (opc) { + case ANDITOCCR_INST: + tmp = "andib\t"; + break; + case ANDIROSR_INST: + tmp = "andiw\t"; + break; + case EORITOCCR_INST: + tmp = "eorib\t"; + break; + case EORITOSR_INST: + tmp = "eoriw\t"; + break; + case ORITOCCR_INST: + tmp = "orib\t"; + break; + case ORITOSR_INST: + tmp = "oriw\t"; + break; + } + if (tmp) { + addstr(dbuf, tmp); + if (ISBITSET(opc,6)) { + get_immed(dbuf, SIZE_WORD); + addstr(dbuf, ",sr"); + } else { + get_immed(dbuf, SIZE_BYTE); + addstr(dbuf, ",ccr"); + } + return; + } + + if (IS_INST(RTM,opc)) { + addstr(dbuf, "rtm\t"); + if (ISBITSET(opc,3)) + PRINT_AREG(dbuf, BITFIELD(opc,2,0)); + else + PRINT_DREG(dbuf, BITFIELD(opc,2,0)); + return; + } + + if (IS_INST(MOVEP,opc)) { + addstr(dbuf, "movp"); + if (ISBITSET(opc,6)) + addchar('l'); + else + addchar('w'); + addchar('\t'); + if (ISBITSET(opc,7)) { + PRINT_DREG(dbuf, BITFIELD(opc, 11, 9)); + addchar(','); + } + PRINT_AREG(dbuf, BITFIELD(opc, 2, 0)); + addchar('@'); + addchar('('); + print_disp(dbuf, *(dbuf->val + 1), SIZE_WORD, + BITFIELD(opc, 2, 0)); + dbuf->used++; + addchar(')'); + if (!ISBITSET(opc,7)) { + addchar(','); + PRINT_DREG(dbuf, BITFIELD(opc, 11, 9)); + } + return; + } + + switch (opc & BCHGD_MASK) { + case BCHGD_INST: + tmp = "bchg\t"; + break; + case BCLRD_INST: + tmp = "bclr\t"; + break; + case BSETD_INST: + tmp = "bset\t"; + break; + case BTSTD_INST: + tmp = "btst\t"; + break; + } + if (tmp) { + addstr(dbuf, tmp); + PRINT_DREG(dbuf, BITFIELD(opc,11,9)); + addchar(','); + get_modregstr(dbuf,5,GETMOD_BEFORE,0,0); + return; + } + + switch (opc & BCHGS_MASK) { + case BCHGS_INST: + tmp = "bchg\t"; + break; + case BCLRS_INST: + tmp = "bclr\t"; + break; + case BSETS_INST: + tmp = "bset\t"; + break; + case BTSTS_INST: + tmp = "btst\t"; + break; + } + if (tmp) { + addstr(dbuf, tmp); + get_immed(dbuf, SIZE_BYTE); + addchar(','); + get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 1); + return; + } + + if (IS_INST(CAS2,opc)) { + u_short ext2; + + ext = *(dbuf->val + 1); + ext2 = *(dbuf->val + 2); + dbuf->used += 2; + + if (ISBITSET(opc,9)) + addstr(dbuf, "cas2l\t"); + else + addstr(dbuf, "cas2w\t"); + + PRINT_DREG(dbuf, BITFIELD(ext,2,0)); + addchar(':'); + PRINT_DREG(dbuf, BITFIELD(ext2,2,0)); + addchar(','); + + PRINT_DREG(dbuf, BITFIELD(ext,8,6)); + addchar(':'); + PRINT_DREG(dbuf, BITFIELD(ext2,8,6)); + addchar(','); + + if (ISBITSET(ext,15)) + PRINT_AREG(dbuf, BITFIELD(ext,14,12)); + else + PRINT_DREG(dbuf, BITFIELD(ext,14,12)); + addchar('@'); + addchar(':'); + if (ISBITSET(ext2,15)) + PRINT_AREG(dbuf, BITFIELD(ext2,14,12)); + else + PRINT_DREG(dbuf, BITFIELD(ext2,14,12)); + addchar('@'); + return; + } + + switch (opc & CAS_MASK) { + case CAS_INST: + ext = *(dbuf->val + 1); + dbuf->used++; + + addstr(dbuf,"cas"); + sz = BITFIELD(opc,10,9); + if (sz == 0) { + sz = SIZE_BYTE; + addchar('b'); + } else if (sz == 1) { + sz = SIZE_WORD; + addchar('w'); + } else { + sz = SIZE_LONG; + addchar('l'); + } + addchar('\t'); + PRINT_DREG(dbuf, BITFIELD(ext, 2, 0)); + addchar(','); + PRINT_DREG(dbuf, BITFIELD(ext, 8, 6)); + addchar(','); + get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1); + return; + case CHK2_INST: + /* case CMP2_INST: */ + ext = *(dbuf->val + 1); + dbuf->used++; + + if (ISBITSET(ext,11)) + addstr(dbuf,"chk2"); + else + addstr(dbuf,"cmp2"); + + sz = BITFIELD(opc,10,9); + if (sz == 0) { + sz = SIZE_BYTE; + addchar('b'); + } else if (sz == 1) { + sz = SIZE_WORD; + addchar('w'); + } else { + sz = SIZE_LONG; + addchar('l'); + } + addchar('\t'); + get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1); + + addchar(','); + if(ISBITSET(ext,15)) + PRINT_AREG(dbuf, BITFIELD(ext, 14, 12)); + else + PRINT_DREG(dbuf, BITFIELD(ext, 14, 12)); + return; + } + + switch (ADDI_MASK & opc) { + case MOVES_INST: + addstr(dbuf, "movs"); + sz = BITFIELD(opc,7,6); + if (sz == 0) { + addchar('b'); + sz = SIZE_BYTE; + } else if (sz == 1) { + addchar('w'); + sz = SIZE_WORD; + } else { + addchar ('l'); + sz = SIZE_LONG; + } + addchar('\t'); + + ext = *(dbuf->val + 1); + dbuf->used++; + + if (ISBITSET(ext,11)) { + if (ISBITSET(ext,15)) + PRINT_AREG(dbuf,BITFIELD(ext,14,12)); + else + PRINT_DREG(dbuf,BITFIELD(ext,14,12)); + addchar(','); + get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1); + } else { + get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1); + addchar(','); + if (ISBITSET(ext,15)) + PRINT_AREG(dbuf,BITFIELD(ext,14,12)); + else + PRINT_DREG(dbuf,BITFIELD(ext,14,12)); + } + return; + case ADDI_INST: + tmp = "addi"; + break; + case ANDI_INST: + tmp = "andi"; + break; + case CMPI_INST: + tmp = "cmpi"; + break; + case EORI_INST: + tmp = "eori"; + break; + case ORI_INST: + tmp = "ori"; + break; + case SUBI_INST: + tmp = "subi"; + break; + } + if (tmp) { + addstr(dbuf, tmp); + sz = BITFIELD(opc,7,6); + switch (sz) { + case 0: + addchar('b'); + addchar('\t'); + sz = SIZE_BYTE; + break; + case 1: + addchar('w'); + addchar('\t'); + sz = SIZE_WORD; + break; + case 2: + addchar ('l'); + addchar('\t'); + get_immed(dbuf,SIZE_LONG); + addchar(','); + get_modregstr(dbuf,5,GETMOD_BEFORE,SIZE_LONG,2); + return; + } + get_immed(dbuf,sz); + addchar(','); + get_modregstr(dbuf,5,GETMOD_BEFORE,sz,1); + return; + } +} + +/* + * move byte/word/long and q + * 00xx (01==.b 10==.l 11==.w) and 0111(Q) + */ +void +opcode_move(dbuf, opc) + dis_buffer_t *dbuf; + u_short opc; +{ + int sz, lused; + + switch (OPCODE_MAP(opc)) { + case 0x1: /* move.b */ + sz = SIZE_BYTE; + break; + case 0x3: /* move.w */ + sz = SIZE_WORD; + break; + case 0x2: /* move.l */ + sz = SIZE_LONG; + break; + case 0x7: /* moveq */ + addstr(dbuf, "movq\t#"); + prints_bf(dbuf, opc, 7, 0); + addchar(','); + PRINT_DREG(dbuf,BITFIELD(opc,11,9)); + return; + } + addstr(dbuf, "mov"); + + if (BITFIELD(opc,8,6) == AR_DIR) + addchar('a'); + + if (sz == SIZE_BYTE) + addchar('b'); + else if (sz == SIZE_WORD) + addchar('w'); + else + addchar('l'); + + addchar('\t'); + lused = dbuf->used; + get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0); + addchar(','); + get_modregstr(dbuf, 11, GETMOD_AFTER, sz, dbuf->used - lused); +} + +/* + * misc opcodes. + */ +void +opcode_misc(dbuf, opc) + dis_buffer_t *dbuf; + u_short opc; +{ + char *tmp; + u_short ext; + + tmp = NULL; + + /* Check against no option instructions */ + switch (opc) { + case BGND_INST: + tmp = "bgnd"; + break; + case ILLEGAL_INST: + tmp = "illegal"; + break; + case MOVEFRC_INST: + case MOVETOC_INST: + opcode_movec(dbuf, opc); + return; + case NOP_INST: + tmp = "nop"; + break; + case RESET_INST: + tmp = "reset"; + break; + case RTD_INST: + addstr(dbuf, "rtd\t"); + get_immed(dbuf, SIZE_WORD); + return; + case RTE_INST: + tmp = "rte"; + break; + case RTR_INST: + tmp = "rtr"; + break; + case RTS_INST: + tmp = "rts"; + break; + case STOP_INST: + addstr(dbuf, "stop\t"); + get_immed(dbuf, SIZE_WORD); + return; + case TRAPV_INST: + tmp = "trapv"; + break; + default: + break; + } + if (tmp) { + addstr(dbuf, tmp); + return; + } + + switch (opc & BKPT_MASK) { + case BKPT_INST: + addstr(dbuf, "bkpt\t#"); + printu_bf(dbuf, opc, 2, 0); + return; + case EXTBW_INST: + addstr(dbuf, "extw\t"); + get_modregstr(dbuf,2,DR_DIR,0,0); + return; + case EXTWL_INST: + addstr(dbuf, "extl\t"); + get_modregstr(dbuf,2,DR_DIR,0,0); + return; + case EXTBL_INST: + addstr(dbuf, "extbl\t"); + get_modregstr(dbuf,2,DR_DIR,0,0); + return; + case LINKW_INST: + case LINKL_INST: + if ((LINKW_MASK & opc) == LINKW_INST) { + addstr(dbuf, "linkw\t"); + get_modregstr(dbuf, 2, AR_DIR, 0, 1); + } else { + addstr(dbuf, "linkl\t"); + get_modregstr(dbuf, 2, AR_DIR, 0, 2); + } + addchar(','); + if ((LINKW_MASK & opc) == LINKW_INST) + get_immed(dbuf, SIZE_WORD); + else + get_immed(dbuf,SIZE_LONG); + return; + case MOVETOUSP_INST: + case MOVEFRUSP_INST: + addstr(dbuf, "movl\t"); + if (!ISBITSET(opc,3)) { + get_modregstr(dbuf, 2, AR_DIR, 0, 0); + addchar(','); + } + addstr(dbuf, "usp"); + if (ISBITSET(opc,3)) { + addchar(','); + get_modregstr(dbuf, 2, AR_DIR, 0, 0); + } + return; + case UNLK_INST: + addstr(dbuf, "unlk\t"); + get_modregstr(dbuf, 2, AR_DIR, 0, 0); + return; + } + + if ((opc & TRAP_MASK) == TRAP_INST) { + addstr(dbuf, "trap\t#"); + printu_bf(dbuf, opc, 3, 0); + return; + } + + switch (DIVSL_MASK & opc) { + case DIVSL_INST: + case MULSL_INST: + opcode_divmul(dbuf, opc); + return; + case JMP_INST: + tmp = "jmp\t"; + break; + case JSR_INST: + tmp = "jsr\t"; + break; + case MOVEFRCCR_INST: + tmp = "mov\tccr,"; + break; + case MOVEFRSR_INST: + tmp = "mov\tsr,"; + break; + case NBCD_INST: + tmp = "nbcd\t"; + break; + case PEA_INST: + tmp = "pea\t"; + break; + case TAS_INST: + tmp = "tas\t"; + break; + case MOVETOCCR_INST: + case MOVETOSR_INST: + tmp = "mov\t"; + break; + } + if (tmp) { + addstr(dbuf, tmp); + get_modregstr(dbuf,5, GETMOD_BEFORE,0, 0); + if(IS_INST(MOVETOSR,opc)) + addstr(dbuf, ",sr"); + else if(IS_INST(MOVETOCCR,opc)) + addstr(dbuf, ",ccr"); + return; + } + + if ((opc & MOVEM_MASK) == MOVEM_INST) { + opcode_movem(dbuf, opc); + return; + } + + switch (opc & CLR_MASK) { + case CLR_INST: + tmp = "clr"; + break; + case NEG_INST: + tmp = "neg"; + break; + case NEGX_INST: + tmp = "negx"; + break; + case NOT_INST: + tmp = "not"; + break; + case TST_INST: + tmp = "tst"; + break; + } + if (tmp) { + int sz, msz; + + addstr(dbuf, tmp); + + msz = BITFIELD(opc,7,6); + if (msz == 0) { + tmp = "b\t"; + sz = SIZE_BYTE; + } else if (msz == 1) { + tmp = "w\t"; + sz = SIZE_WORD; + } else { + tmp = "l\t"; + sz = SIZE_LONG; + } + addstr(dbuf, tmp); + get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0); + return; + } + + if ((opc & LEA_MASK) == LEA_INST) { + addstr(dbuf, "lea\t"); + get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_LONG, 0); + addchar(','); + get_modregstr(dbuf, 11, AR_DIR, 0, 0); + return; + } else if ((opc & CHK_MASK) == CHK_INST) { + if (BITFIELD(opc,8,7) == 0x3) { + addstr(dbuf, "chkw\t"); + get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_WORD, 0); + } else { + addstr(dbuf, "chkl\t"); + get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_LONG, 0); + } + addchar(','); + get_modregstr(dbuf, 11, DR_DIR, 0, 0); + return; + } +} +/* + * ADDQ/SUBQ/Scc/DBcc/TRAPcc + */ +void +opcode_0101(dbuf, opc) + dis_buffer_t *dbuf; + u_short opc; +{ + int data; + + if (IS_INST(TRAPcc, opc) && BITFIELD(opc,2,0) > 1) { + int opmode; + + opmode = BITFIELD(opc,2,0); + make_cond(dbuf,11,"trap"); + + if (opmode == 0x2) { + addchar('w'); + addchar('\t'); + get_immed(dbuf, SIZE_WORD); + } else if (opmode == 0x3) { + addchar('l'); + addchar('\t'); + get_immed(dbuf, SIZE_LONG); + } + return; + } else if (IS_INST(DBcc, opc)) { + make_cond(dbuf,11,"db"); + addchar('\t'); + PRINT_DREG(dbuf, BITFIELD(opc,2,0)); + addchar(','); + print_disp(dbuf, *(dbuf->val + 1), SIZE_WORD, -1); + dbuf->used++; + return; + } else if (IS_INST(Scc,opc)) { + make_cond(dbuf,11,"s"); + addchar('\t'); + get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_BYTE, 0); + return; + } else if (IS_INST(ADDQ, opc) || IS_INST(SUBQ, opc)) { + int size = BITFIELD(opc,7,6); + + if (IS_INST(SUBQ, opc)) + addstr(dbuf, "subq"); + else + addstr(dbuf, "addq"); + + if (size == 0x1) + addchar('w'); + else if (size == 0x2) + addchar('l'); + else + addchar('b'); + + addchar('\t'); + addchar('#'); + data = BITFIELD(opc,11,9); + if (data == 0) + data = 8; + printu(dbuf, data, SIZE_BYTE); + addchar(','); + get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 0); + + return; + } +} + +/* + * Bcc/BSR/BRA + */ +void +opcode_branch(dbuf, opc) + dis_buffer_t *dbuf; + u_short opc; +{ + int disp, sz; + + if (IS_INST(BRA,opc)) + addstr(dbuf, "bra"); + else if (IS_INST(BSR,opc)) + addstr(dbuf, "bsr"); + else + make_cond(dbuf,11,"b"); + + disp = BITFIELD(opc,7,0); + if (disp == 0) { + disp = *(dbuf->val + 1); + dbuf->used++; + sz = SIZE_WORD; +#if 0 /* XXX Note GNU as doesn't like this */ + addchar('w'); +#endif + } else if (disp == 0xff) { + disp = *(long *)(dbuf->val + 1); + dbuf->used += 2; + sz = SIZE_LONG; + addchar('l'); + } else { + /* + * XXX gas chokes on this, I am not sure if + * XXX it can even be made to emit it (short of .word) + */ + sz = SIZE_BYTE; + addchar('b'); + } + addchar('\t'); + print_addr(dbuf, disp + (u_long)dbuf->val + 2); +} + +/* + * ADD/ADDA/ADDX/SUB/SUBA/SUBX + */ +void +opcode_addsub(dbuf, opc) + dis_buffer_t *dbuf; + u_short opc; +{ + int sz, ch, amode; + + sz = BITFIELD(opc,7,6); + amode = 0; + + if (sz == 0) { + ch = 'b'; + sz = SIZE_BYTE; + } else if (sz == 1) { + ch = 'w'; + sz = SIZE_WORD; + } else if (sz == 2) { + ch = 'l'; + sz = SIZE_LONG; + } else { + amode = 1; + if (!ISBITSET(opc,8)) { + sz = SIZE_WORD; + ch = 'w'; + } else { + sz = SIZE_LONG; + ch = 'l'; + } + } + + if (IS_INST(ADDX,opc) || IS_INST(SUBX,opc)) { + if (IS_INST(ADDX,opc)) + addstr(dbuf,"addx"); + else + addstr(dbuf,"addx"); + + addchar(ch); + addchar('\t'); + + if (ISBITSET(opc,3)) { + PRINT_AREG(dbuf,BITFIELD(opc,2,0)); + addchar('@'); + addchar('-'); + addchar(','); + PRINT_AREG(dbuf,BITFIELD(opc,11,9)); + addchar('@'); + addchar('-'); + } else { + PRINT_DREG(dbuf,BITFIELD(opc,2,0)); + addchar(','); + PRINT_DREG(dbuf,BITFIELD(opc,11,9)); + } + } else { + if (IS_INST(ADD,opc)) + addstr(dbuf, "add"); + else + addstr(dbuf, "sub"); + + if (amode) + addchar('a'); + addchar(ch); + addchar('\t'); + + if (ISBITSET(opc,8) && amode == 0) { + PRINT_DREG(dbuf,BITFIELD(opc,11,9)); + addchar(','); + get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0); + } else { + get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0); + addchar(','); + if (amode) + PRINT_AREG(dbuf,BITFIELD(opc,11,9)); + else + PRINT_DREG(dbuf,BITFIELD(opc,11,9)); + } + } + return; +} + +/* + * Shift/Rotate/Bit Field + */ +void +opcode_1110(dbuf, opc) + dis_buffer_t *dbuf; + u_short opc; +{ + char *tmp; + u_short ext; + int type, sz; + + tmp = NULL; + + switch (opc & BFCHG_MASK) { + case BFCHG_INST: + tmp = "bfchg"; + break; + case BFCLR_INST: + tmp = "bfclr"; + break; + case BFEXTS_INST: + tmp = "bfexts"; + break; + case BFEXTU_INST: + tmp = "bfextu"; + break; + case BFFFO_INST: + tmp = "bfffo"; + break; + case BFINS_INST: + tmp = "bfins"; + break; + case BFSET_INST: + tmp = "bfset"; + break; + case BFTST_INST: + tmp = "bftst"; + break; + } + if (tmp) { + short bf; + + addstr(dbuf, tmp); + addchar('\t'); + + ext = *(dbuf->val + 1); + dbuf->used++; + + if (IS_INST(BFINS,opc)) { + PRINT_DREG(dbuf, BITFIELD(ext,14,12)); + addchar(','); + } + get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 1); + addchar('{'); + + bf = BITFIELD(ext,10,6); + if (ISBITSET(ext, 11)) + PRINT_DREG(dbuf, bf); + else + printu_wb(dbuf, bf, SIZE_BYTE, 10); + + addchar(':'); + + bf = BITFIELD(ext, 4, 0); + if (ISBITSET(ext, 5)) + PRINT_DREG(dbuf, bf); + else { + if (bf == 0) + bf = 32; + printu_wb(dbuf, bf, SIZE_BYTE, 10); + } + addchar('}'); + if (ISBITSET(opc,8) && !IS_INST(BFINS,opc)) { + addchar(','); + PRINT_DREG(dbuf, BITFIELD(ext,14,12)); + } else + *dbuf->casm = 0; + return; + } + sz = BITFIELD(opc,7,6); + if (sz == 0x3) + type = BITFIELD(opc, 10, 9); + else + type = BITFIELD(opc, 4, 3); + + switch (type) { + case AS_TYPE: + addchar('a'); + addchar('s'); + break; + case LS_TYPE: + addchar('l'); + addchar('s'); + break; + case RO_TYPE: + addchar('r'); + addchar('o'); + break; + case ROX_TYPE: + addchar('r'); + addchar('o'); + addchar('x'); + break; + } + + if (ISBITSET(opc,8)) + addchar('l'); + else + addchar('r'); + + switch (sz) { + case 0: + sz = SIZE_BYTE; + addchar('b'); + break; + case 3: + case 1: + sz = SIZE_WORD; + addchar('w'); + break; + case 2: + sz = SIZE_LONG; + addchar('l'); + break; + + } + addchar('\t'); + if(BITFIELD(opc,7,6) == 0x3) { + get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0); + return; + } else if (ISBITSET(opc,5)) + PRINT_DREG(dbuf, BITFIELD(opc,11,9)); + else { + addchar('#'); + sz = BITFIELD(opc,11,9); + if (sz == 0) + sz = 8; + printu_wb(dbuf, sz, SIZE_BYTE, 10); + } + addchar(','); + PRINT_DREG(dbuf, BITFIELD(opc,2,0)); + return; +} + +/* + * CMP/CMPA/EOR + */ +void +opcode_1011(dbuf, opc) + dis_buffer_t *dbuf; + u_short opc; +{ + int sz; + + if (IS_INST(CMPA,opc)) { + addstr(dbuf, "cmpa"); + + if (ISBITSET(opc, 8)) { + addchar('l'); + sz = SIZE_LONG; + } else { + addchar('w'); + sz = SIZE_WORD; + } + addchar('\t'); + } else { + if (IS_INST(CMP, opc)) + addstr(dbuf, "cmp"); + else + addstr(dbuf, "eor"); + + sz = BITFIELD(opc,7,6); + switch (sz) { + case 0: + addchar('b'); + sz = SIZE_BYTE; + break; + case 1: + addchar('w'); + sz = SIZE_WORD; + break; + case 2: + addchar('l'); + sz = SIZE_LONG; + break; + } + addchar('\t'); + if (IS_INST(EOR,opc)) { + PRINT_DREG(dbuf, BITFIELD(opc,11,9)); + addchar(','); + } + } + get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0); + + if (IS_INST(CMPA,opc)) { + addchar(','); + PRINT_AREG(dbuf, BITFIELD(opc,11,9)); + } else if (IS_INST(CMP,opc)) { + addchar(','); + PRINT_DREG(dbuf, BITFIELD(opc,11,9)); + } + return; +} + +/* + * OR/DIV/SBCD + */ +void +opcode_1000(dbuf, opc) + dis_buffer_t *dbuf; + u_short opc; +{ + int sz; + + if (IS_INST(UNPKA,opc)) { + addstr(dbuf, "unpk\t"); + PRINT_AREG(dbuf,BITFIELD(opc,2,0)); + addstr(dbuf, "@-,"); + PRINT_AREG(dbuf,BITFIELD(opc,11,9)); + addstr(dbuf, "@-,"); + get_immed(dbuf,SIZE_WORD); + } else if (IS_INST(UNPKD,opc)) { + addstr(dbuf, "unpk\t"); + PRINT_DREG(dbuf,BITFIELD(opc,2,0)); + addchar(','); + PRINT_DREG(dbuf,BITFIELD(opc,11,9)); + addchar(','); + get_immed(dbuf,SIZE_WORD); + } else if (IS_INST(SBCDA,opc)) { + addstr(dbuf, "sbcd\t"); + PRINT_AREG(dbuf,BITFIELD(opc,2,0)); + addstr(dbuf, "@-,"); + PRINT_AREG(dbuf,BITFIELD(opc,11,9)); + addstr(dbuf, "@-"); + } else if (IS_INST(SBCDA,opc)) { + addstr(dbuf, "sbcd\t"); + PRINT_DREG(dbuf,BITFIELD(opc,2,0)); + addchar(','); + PRINT_DREG(dbuf,BITFIELD(opc,11,9)); + } else if (IS_INST(DIVSW,opc) || IS_INST(DIVUW,opc)) { + if (IS_INST(DIVSW,opc)) + addstr(dbuf, "divsw\t"); + else + addstr(dbuf, "divuw\t"); + get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_WORD, 0); + addchar(','); + PRINT_DREG(dbuf, BITFIELD(opc,11,9)); + } else { + addstr(dbuf, "or"); + + sz = BITFIELD(opc,7,6); + switch (sz) { + case 0: + addchar('b'); + sz = SIZE_BYTE; + break; + case 1: + addchar('w'); + sz = SIZE_WORD; + break; + case 2: + addchar('l'); + sz = SIZE_LONG; + break; + } + addchar('\t'); + if (ISBITSET(opc,8)) { + PRINT_DREG(dbuf, BITFIELD(opc,11,9)); + addchar(','); + } + get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0); + if (!ISBITSET(opc,8)) { + addchar(','); + PRINT_DREG(dbuf, BITFIELD(opc,11,9)); + } + } +} + +/* + * AND/MUL/ABCD/EXG (1100) + */ +void +opcode_1100(dbuf, opc) + dis_buffer_t *dbuf; + u_short opc; +{ + int sz; + + if (IS_INST(ABCDA,opc)) { + addstr(dbuf, "abcd\t"); + PRINT_AREG(dbuf,BITFIELD(opc,2,0)); + addstr(dbuf, "@-,"); + PRINT_AREG(dbuf,BITFIELD(opc,11,9)); + addstr(dbuf, "@-"); + } else if (IS_INST(ABCDA,opc)) { + addstr(dbuf, "abcd\t"); + PRINT_DREG(dbuf,BITFIELD(opc,2,0)); + addchar(','); + PRINT_DREG(dbuf,BITFIELD(opc,11,9)); + } else if (IS_INST(MULSW,opc) || IS_INST(MULUW,opc)) { + if (IS_INST(MULSW,opc)) + addstr(dbuf, "mulsw\t"); + else + addstr(dbuf, "muluw\t"); + get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_WORD, 0); + addchar(','); + PRINT_DREG(dbuf, BITFIELD(opc,11,9)); + } else if (IS_INST(EXG,opc)) { + addstr(dbuf, "exg\t"); + if (ISBITSET(opc,7)) { + PRINT_DREG(dbuf,BITFIELD(opc,11,9)); + addchar(','); + PRINT_AREG(dbuf,BITFIELD(opc,2,0)); + } else if (ISBITSET(opc,3)) { + PRINT_AREG(dbuf,BITFIELD(opc,11,9)); + addchar(','); + PRINT_AREG(dbuf,BITFIELD(opc,2,0)); + } else { + PRINT_DREG(dbuf,BITFIELD(opc,11,9)); + addchar(','); + PRINT_DREG(dbuf,BITFIELD(opc,2,0)); + } + } else { + addstr(dbuf, "and"); + + sz = BITFIELD(opc,7,6); + switch (sz) { + case 0: + addchar('b'); + sz = SIZE_BYTE; + break; + case 1: + addchar('w'); + sz = SIZE_WORD; + break; + case 2: + addchar('l'); + sz = SIZE_LONG; + break; + } + addchar('\t'); + + if (ISBITSET(opc,8)) { + PRINT_DREG(dbuf, BITFIELD(opc,11,9)); + addchar(','); + } + get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 0); + if (!ISBITSET(opc,8)) { + addchar(','); + PRINT_DREG(dbuf, BITFIELD(opc,11,9)); + } + } +} + +/* + * Coprocessor instruction + */ +void +opcode_coproc(dbuf, opc) + dis_buffer_t *dbuf; + u_short opc; +{ + switch (BITFIELD(*dbuf->val,11,9)) { + case 1: + opcode_fpu(dbuf, opc); + return; + case 0: + opcode_mmu(dbuf, opc); + return; + case 2: + opcode_mmu040(dbuf, opc); + return; + } + switch (BITFIELD(opc,8,6)) { + case 0: + dbuf->used++; + break; + case 3: + dbuf->used++; + /*FALLTHROUGH*/ + case 2: + dbuf->used++; + break; + case 1: + dbuf->used++; + case 4: + case 5: + default: + } + addstr(dbuf, "UKNOWN COPROC OPCODE"); + return; +} + +/* + * Resvd + */ +void +opcode_1010(dbuf, opc) + dis_buffer_t *dbuf; + u_short opc; +{ + addstr(dbuf, "RSVD"); + dbuf->used++; +} + +void +opcode_fpu(dbuf, opc) + dis_buffer_t *dbuf; + u_short opc; +{ + u_short ext; + int sz, type, opmode; + + type = BITFIELD(opc,8,6); + switch (type) { + /* cpGEN */ + case 0: + ext = *(dbuf->val + 1); + dbuf->used++; + opmode = BITFIELD(ext,5,0); + + if (BITFIELD(opc,5,0) == 0 && BITFIELD(ext,15,10) == 0x17) { + addstr(dbuf,"fmovcrx #"); + printu(dbuf,BITFIELD(ext,6,0),SIZE_BYTE); + return; + } + if (ISBITSET(ext,15) || ISBITSET(ext,13)) { + opcode_fmove_ext(dbuf, opc, ext); + } + + switch(opmode) { + case FMOVE: + get_fpustdGEN(dbuf,ext,"fmov"); + return; + case FABS: + get_fpustdGEN(dbuf,ext,"fabs"); + return; + case FACOS: + get_fpustdGEN(dbuf,ext,"facos"); + return; + case FADD: + get_fpustdGEN(dbuf,ext,"fadd"); + return; + case FASIN: + get_fpustdGEN(dbuf,ext,"fasin"); + return; + case FATAN: + get_fpustdGEN(dbuf,ext,"fatan"); + return; + case FATANH: + get_fpustdGEN(dbuf,ext,"fatanh"); + return; + case FCMP: + get_fpustdGEN(dbuf,ext,"fcmp"); + return; + case FCOS: + get_fpustdGEN(dbuf,ext,"fcos"); + return; + case FCOSH: + get_fpustdGEN(dbuf,ext,"fcosh"); + return; + case FDIV: + get_fpustdGEN(dbuf,ext,"fdiv"); + return; + case FETOX: + get_fpustdGEN(dbuf,ext,"fetox"); + return; + case FGETEXP: + get_fpustdGEN(dbuf,ext,"fgetexp"); + return; + case FGETMAN: + get_fpustdGEN(dbuf,ext,"fgetman"); + return; + case FINT: + get_fpustdGEN(dbuf,ext,"fint"); + return; + case FINTRZ: + get_fpustdGEN(dbuf,ext,"fintrz"); + return; + case FLOG10: + get_fpustdGEN(dbuf,ext,"flog10"); + return; + case FLOG2: + get_fpustdGEN(dbuf,ext,"flog2"); + return; + case FLOGN: + get_fpustdGEN(dbuf,ext,"flogn"); + return; + case FLOGNP1: + get_fpustdGEN(dbuf,ext,"flognp1"); + return; + case FMOD: + get_fpustdGEN(dbuf,ext,"fmod"); + return; + case FMUL: + get_fpustdGEN(dbuf,ext,"fmul"); + return; + case FNEG: + get_fpustdGEN(dbuf,ext,"fneg"); + return; + case FREM: + get_fpustdGEN(dbuf,ext,"frem"); + return; + case FSCALE: + get_fpustdGEN(dbuf,ext,"fscale"); + return; + case FSGLDIV: + get_fpustdGEN(dbuf,ext,"fsgldiv"); + return; + case FSGLMUL: + get_fpustdGEN(dbuf,ext,"fsglmul"); + return; + case FSIN: + get_fpustdGEN(dbuf,ext,"fsin"); + return; + case FSINH: + get_fpustdGEN(dbuf,ext,"fsinh"); + return; + case FSQRT: + get_fpustdGEN(dbuf,ext,"fsqrt"); + return; + case FSUB: + get_fpustdGEN(dbuf,ext,"fsub"); + return; + case FTAN: + get_fpustdGEN(dbuf,ext,"ftan"); + return; + case FTANH: + get_fpustdGEN(dbuf,ext,"ftanh"); + return; + case FTENTOX: + get_fpustdGEN(dbuf,ext,"ftentox"); + return; + case FTST: + get_fpustdGEN(dbuf,ext,"ftst"); + return; + case FTWOTOX: + get_fpustdGEN(dbuf,ext,"ftwotox"); + return; + + } + /* cpBcc */ + case 2: + if (BITFIELD(opc,5,0) == 0 && *(dbuf->val + 1) == 0) { + dbuf->used++; + addstr (dbuf, "fnop"); + return; + } + case 3: + addstr(dbuf, "fb"); + print_fcond(dbuf, BITFIELD(opc,5,0)); + if (type == 2) { + addchar('w'); + addchar('\t'); + print_disp(dbuf,*(dbuf->val + 1), SIZE_WORD, -1); + dbuf->used++; + } else { + addchar('l'); + addchar('\t'); + print_disp(dbuf,*(long *)(dbuf->val + 1), SIZE_LONG, + -1); + dbuf->used += 2; + } + return; + /* cpDBcc/cpScc/cpTrap */ + case 1: + ext = *(dbuf->val + 1); + dbuf->used++; + + if (BITFIELD(opc,5,3) == 0x1) { + /* fdbcc */ + addstr(dbuf,"fdb"); + print_fcond(dbuf,BITFIELD(ext,5,0)); + addchar('\t'); + PRINT_DREG(dbuf, BITFIELD(opc,2,0)); + addchar(','); + print_disp(dbuf, *(dbuf->val + 2), SIZE_WORD, -1); + dbuf->used++; + } else if (BITFIELD(opc,5,3) == 0x7 && + BITFIELD(opc,2,0) > 1) { + addstr(dbuf,"ftrap"); + print_fcond(dbuf,BITFIELD(ext,5,0)); + + if (BITFIELD(opc,2,0) == 0x2) { + addchar('w'); + addchar('\t'); + dbuf->val++; + get_immed(dbuf, SIZE_WORD); + dbuf->val--; + } else if (BITFIELD(opc,2,0) == 0x3) { + addchar('l'); + addchar('\t'); + dbuf->val++; + get_immed(dbuf, SIZE_LONG); + dbuf->val--; + } + } else { + addstr(dbuf,"fs"); + print_fcond(dbuf,BITFIELD(ext,5,0)); + addchar('\t'); + get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_BYTE, 1); + } + return; + case 4: + addstr(dbuf,"fsave\t"); + get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 0); + return; + case 5: + addstr(dbuf,"frestor\t"); + get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 0); + return; + } +} + +void +opcode_fmove_ext(dbuf, opc, ext) + dis_buffer_t *dbuf; + u_short opc, ext; +{ + int sz; + + if (BITFIELD(ext,15,13) == 3) { + /* fmove r ==> m */ + addstr(dbuf, "fmov"); + switch (BITFIELD(ext,12,10)) { + case 0: + addchar('l'); + sz = SIZE_LONG; + break; + case 1: + addchar('s'); + sz = SIZE_SINGLE; + break; + case 2: + addchar('x'); + sz = SIZE_EXTENDED; + break; + case 7: + case 3: + addchar('p'); + sz = SIZE_PACKED; + break; + case 4: + addchar('w'); + sz = SIZE_WORD; + break; + case 5: + addchar('d'); + sz = SIZE_DOUBLE; + break; + case 6: + addchar('b'); + sz = SIZE_BYTE; + break; + } + addchar('\t'); + PRINT_FPREG(dbuf, BITFIELD(ext,9,7)); + addchar(','); + get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1); + if (sz == SIZE_PACKED) { + addchar('{'); + if (ISBITSET(ext,12)) { + PRINT_DREG(dbuf,BITFIELD(ext,6,4)); + } else { + addchar('#'); + prints_bf(dbuf, ext, 6, 4); + } + addchar('}'); + } + return; + } + addstr(dbuf,"fmovm"); + + if (!ISBITSET(ext,14)) { + /* fmove[m] control reg */ + addchar('l'); + addchar('\t'); + + if (!ISBITSET(ext,13)) { + print_freglist(dbuf, AR_DEC, BITFIELD(ext,12,10), 1); + addchar(','); + } + get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_LONG, 1); + if (ISBITSET(ext,13)) { + addchar(','); + print_freglist(dbuf, AR_DEC, BITFIELD(ext,12,10), 1); + } + return; + } + addchar('x'); + addchar('\t'); + + if (ISBITSET(ext,11)) { + if (ISBITSET(ext,13)) { + PRINT_DREG(dbuf,BITFIELD(ext,6,4)); + addchar(','); + } + get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_EXTENDED, 1); + if (!ISBITSET(ext,13)) { + addchar(','); + PRINT_DREG(dbuf,BITFIELD(ext,6,4)); + } + } else { + if (ISBITSET(ext,13)) { + print_freglist(dbuf, BITFIELD(opc,5,3), + BITFIELD(ext,7,0), 0); + addchar(','); + } + get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_EXTENDED, 1); + if (!ISBITSET(ext,13)) { + addchar(','); + print_freglist(dbuf, BITFIELD(opc,5,3), + BITFIELD(ext,7,0), 0); + } + } +} + +void +opcode_mmu(dbuf, opc) + dis_buffer_t *dbuf; + u_short opc; +{ + u_short ext; + int sz, type, opmode; + + type = BITFIELD(opc,8,6); + switch (type) { + /* cpGEN? */ + case 0: + ext = *(dbuf->val + 1); + dbuf->used++; + + switch(BITFIELD(ext,15,13)) { + case 5: + case 1: + opcode_pflush(dbuf, opc, ext); + return; + case 0: + case 3: + case 2: + opcode_pmove(dbuf, opc, ext); + return; + case 4: + addstr(dbuf, "ptest"); + if (ISBITSET(ext,9)) + addchar('r'); + else + addchar('w'); + addchar('\t'); + print_fcode(dbuf, BITFIELD(ext, 5, 0)); + addchar(','); + get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 1); + addchar(','); + addchar('#'); + printu_bf(dbuf, ext, 12, 10); + if (ISBITSET(ext, 8)) { + addchar(','); + PRINT_AREG(dbuf, BITFIELD(ext, 7, 5)); + } + } + return; + case 2: + case 3: + addstr(dbuf, "pb"); + print_mcond(dbuf, BITFIELD(opc,5,0)); + if (type == 2) { + addchar('w'); + addchar('\t'); + print_disp(dbuf,*(dbuf->val + 1), SIZE_WORD, -1); + dbuf->used++; + } else { + addchar('l'); + addchar('\t'); + print_disp(dbuf,*(long *)(dbuf->val + 1), SIZE_LONG, + -1); + dbuf->used += 2; + } + case 1: + ext = *(dbuf->val + 1); + dbuf->used++; + + if (BITFIELD(opc,5,3) == 0x1) { + /* fdbcc */ + addstr(dbuf,"pdb"); + print_fcond(dbuf,BITFIELD(ext,5,0)); + addchar('\t'); + PRINT_DREG(dbuf, BITFIELD(opc,2,0)); + addchar(','); + print_disp(dbuf, *(dbuf->val + 2), SIZE_WORD, -1); + dbuf->used++; + } else if (BITFIELD(opc,5,3) == 0x7 && + BITFIELD(opc,2,0) > 1) { + addstr(dbuf,"ptrap"); + print_fcond(dbuf,BITFIELD(ext,5,0)); + + if (BITFIELD(opc,2,0) == 0x2) { + addchar('w'); + addchar('\t'); + dbuf->val++; + get_immed(dbuf, SIZE_WORD); + dbuf->val--; + } else if (BITFIELD(opc,2,0) == 0x3) { + addchar('l'); + addchar('\t'); + dbuf->val++; + get_immed(dbuf, SIZE_LONG); + dbuf->val--; + } + } else { + addstr(dbuf,"ps"); + print_fcond(dbuf,BITFIELD(ext,5,0)); + addchar('\t'); + get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_BYTE, 1); + } + return; + case 4: + addstr(dbuf,"psave\t"); + get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 0); + return; + case 5: + addstr(dbuf,"prestore\t"); + get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 0); + return; + } +} + +void +opcode_pflush(dbuf, opc, ext) + dis_buffer_t *dbuf; + u_short opc, ext; +{ + u_short mode, mask, fc; + + mode = BITFIELD(ext,12,10); + mask = BITFIELD(ext,8,5); + fc = BITFIELD(ext, 5, 0); + + if (ext == 0xa000) { + addstr(dbuf,"pflushr\t"); + get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_LONG, 1); + return; + } + + if (mode == 0) { + addstr(dbuf,"pload"); + if (ISBITSET(ext,9)) + addchar('r'); + else + addchar('w'); + addchar(' '); + print_fcode(dbuf, fc); + } + + addstr(dbuf,"pflush"); + switch (mode) { + case 1: + addchar('a'); + *dbuf->casm = 0; + break; + case 7: + case 5: + addchar('s'); + /*FALLTHROUGH*/ + case 6: + case 4: + addchar('\t'); + print_fcode(dbuf, fc); + addchar(','); + addchar('#'); + printu(dbuf, mask, SIZE_BYTE); + if (!ISBITSET(mode,1)) + break; + addchar(','); + get_modregstr(dbuf, 5, GETMOD_BEFORE, SIZE_LONG, 1); + } +} + +void +opcode_pmove(dbuf, opc, ext) + dis_buffer_t *dbuf; + u_short opc, ext; +{ + const char *reg; + int rtom, sz, preg; + + rtom = ISBITSET(ext, 9); + preg = BITFIELD(ext, 12, 10); + + addstr(dbuf,"pmov"); + if (ISBITSET(ext,8)) { + addchar('f'); + addchar('d'); + } + switch (BITFIELD(ext, 15, 13)) { + case 0: /* tt regs 030o */ + switch (preg) { + case 2: + reg = "tt0"; + break; + case 3: + reg = "tt1"; + break; + } + sz = SIZE_LONG; + break; + case 2: + switch (preg) { + case 0: + reg = "tc"; + sz = SIZE_LONG; + break; + case 1: + reg = "drp"; + sz = SIZE_QUAD; + break; + case 2: + reg = "srp"; + sz = SIZE_QUAD; + break; + case 3: + reg = "crp"; + sz = SIZE_QUAD; + break; + case 4: + reg = "cal"; + sz = SIZE_BYTE; + break; + case 5: + reg = "val"; + sz = SIZE_BYTE; + break; + case 6: + reg = "scc"; + sz = SIZE_BYTE; + break; + case 7: + reg = "ac"; + sz = SIZE_WORD; + } + break; + case 3: + switch (preg) { + case 0: + reg = "mmusr"; + break; + case 1: + reg = "pcsr"; + break; + case 4: + reg = "bad"; + break; + case 5: + reg = "bac"; + break; + } + sz = SIZE_WORD; + break; + } + switch (sz) { + case SIZE_BYTE: + addchar ('b'); + break; + case SIZE_WORD: + addchar ('w'); + break; + case SIZE_LONG: + addchar ('l'); + break; + case SIZE_QUAD: + addchar ('d'); + break; + } + addchar('\t'); + + if (!rtom) { + get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1); + addchar(','); + } + addstr(dbuf, reg); + if (BITFIELD(ext, 15, 13) == 3 && preg > 1) + printu_bf(dbuf, ext, 4, 2); + if (rtom) { + addchar(','); + get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1); + } + return; +} + +void +print_fcode(dbuf, fc) + dis_buffer_t *dbuf; + u_short fc; +{ + if (ISBITSET(fc, 5)) + printu_bf(dbuf, fc, 4, 0); + else if (ISBITSET(fc, 4)) + PRINT_DREG(dbuf, BITFIELD(fc, 3, 0)); + else if (fc == 1) + addstr(dbuf, "sfc"); + else + addstr(dbuf, "dfc"); +} +void +opcode_mmu040(dbuf, opc) + dis_buffer_t *dbuf; + u_short opc; +{ + u_short ext; + int sz, type; + + if (ISBITSET(opc, 6)) { + addstr(dbuf, "ptest"); + if (ISBITSET(opc, 5)) + addchar('r'); + else + addchar('w'); + addchar('\t'); + PRINT_AREG(dbuf, BITFIELD(opc,2,0)); + addchar('@'); + } else { + addstr(dbuf, "pflush"); + switch (BITFIELD(opc, 4, 3)) { + case 3: + addchar('a'); + break; + case 2: + addchar('a'); + addchar('n'); + break; + case 0: + addchar('n'); + /*FALLTHROUGH*/ + case 1: + addchar('\t'); + PRINT_AREG(dbuf, BITFIELD(opc,2,0)); + addchar('@'); + break; + } + } + *dbuf->casm = 0; +} + + +/* + * disassemble long format (64b) divs/muls divu/mulu opcode. + * Note: opcode's dbuf->used already accounted for. + */ +void +opcode_divmul(dbuf, opc) + dis_buffer_t *dbuf; + u_short opc; +{ + u_short ext; + int iq, hr; + + ext = *(dbuf->val + 1); + dbuf->used++; + + iq = BITFIELD(ext,14,12); + hr = BITFIELD(ext,2,0); + + if (IS_INST(DIVSL,opc)) + addstr(dbuf, "div"); + else + addstr(dbuf, "mul"); + if (ISBITSET(ext,11)) + addchar('s'); + else + addchar('u'); + addchar('l'); + if (IS_INST(DIVSL,opc) && !ISBITSET(ext,10) && iq != hr) + addchar('l'); + addchar('\t'); + + get_modregstr(dbuf,5,GETMOD_BEFORE,SIZE_LONG,1); + addchar(','); + + if (ISBITSET(ext,10) || + (iq != hr && IS_INST(DIVSL,opc))) { + /* 64 bit version */ + PRINT_DREG(dbuf, hr); + if (dbuf->mit) + addchar(','); + else + addchar(':'); + } + PRINT_DREG(dbuf, iq); +} + +void +print_reglist(dbuf, mod, rl) + dis_buffer_t *dbuf; + int mod; + u_short rl; +{ + const char *const regs[16] = { + "d0","d1","d2","d3","d4","d5","d6","d7", + "a0","a1","a2","a3","a4","a5","a6","a7" }; + int bit, list; + + if (mod == AR_DEC) { + list = rl; + rl = 0; + /* I am sure there is some trick... */ + for (bit = 0; bit < 16; bit++) + if (list & (1 << bit)) + rl |= (0x8000 >> bit); + } + for (bit = 0, list = 0; bit < 16; bit++) { + if (ISBITSET(rl,bit) && bit != 8) { + if (list == 0) { + list = 1; + addstr(dbuf, regs[bit]); + } else if (list == 1) { + list++; + addchar('-'); + } + } else { + if (list) { + if (list > 1) + addstr(dbuf, regs[bit-1]); + addchar('/'); + list = 0; + } + if (ISBITSET(rl,bit)) { + addstr(dbuf, regs[bit]); + list = 1; + } + } + } + if (dbuf->casm[-1] == '/' || dbuf->casm[-1] == '-') + dbuf->casm--; + *dbuf->casm = 0; +} + +void +print_freglist(dbuf, mod, rl, cntl) + dis_buffer_t *dbuf; + int mod, cntl; + u_short rl; +{ + const char *const * regs; + int bit, list, upper; + + regs = cntl ? fpcregs : fpregs; + upper = cntl ? 3 : 8; + + if (mod == AR_DEC) { + list = rl; + rl = 0; + /* I am sure there is some trick... */ + for (bit = 0; bit < upper; bit++) + if (list & (1 << bit)) + rl |= (0x8000 >> bit); + } + for (bit = 0, list = 0; bit < upper; bit++) { + if (ISBITSET(rl,bit)) { + if (list == 0) { + list = 1; + addstr(dbuf, regs[bit]); + } else if (list == 1) { + list++; + addchar('-'); + } + } else { + if (list) { + if (list > 1) + addstr(dbuf, regs[bit-1]); + addchar('/'); + list = 0; + } + } + } + if (dbuf->casm[-1] == '/' || dbuf->casm[-1] == '-') + dbuf->casm--; + *dbuf->casm = 0; +} + +/* + * disassemble movem opcode. + */ +void +opcode_movem(dbuf, opc) + dis_buffer_t *dbuf; + u_short opc; +{ + u_short rl; + + rl = *(dbuf->val + 1); + dbuf->used++; + + if (ISBITSET(opc,6)) + addstr(dbuf, "movml\t"); + else + addstr(dbuf, "movmw\t"); + if (ISBITSET(opc,10)) { + get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 1); + addchar(','); + print_reglist(dbuf, BITFIELD(opc,5,3), rl); + } else { + print_reglist(dbuf, BITFIELD(opc,5,3), rl); + addchar(','); + get_modregstr(dbuf, 5, GETMOD_BEFORE, 0, 1); + } +} + +/* + * disassemble movec opcode. + */ +void +opcode_movec(dbuf, opc) + dis_buffer_t *dbuf; + u_short opc; +{ + char *tmp; + u_short ext; + + ext = *(dbuf->val + 1); + dbuf->used++; + + addstr(dbuf, "movc\t"); + if (ISBITSET(opc,0)) { + dbuf->val++; + if (ISBITSET(ext,15)) + get_modregstr(dbuf,14,AR_DIR,0,0); + else + get_modregstr(dbuf,14,DR_DIR,0,0); + dbuf->val--; + addchar(','); + } + switch (BITFIELD(ext,11,0)) { + /* 010/020/030/040/CPU32 */ + case 0x000: + tmp = "sfc"; + break; + case 0x001: + tmp = "dfc"; + break; + case 0x800: + tmp = "usp"; + break; + case 0x801: + tmp = "vbr"; + break; + /* 020/030 */ + case 0x802: + tmp = "caar"; + break; + /* 020/030/040 */ + case 0x002: + tmp = "cacr"; + break; + case 0x803: + tmp = "msp"; + break; + case 0x804: + tmp = "isp"; + break; + /* 040 */ + case 0x003: + tmp = "tc"; + break; + case 0x004: + tmp = "itt0"; + break; + case 0x005: + tmp = "itt1"; + break; + case 0x006: + tmp = "dtt0"; + break; + case 0x007: + tmp = "dtt1"; + break; + case 0x805: + tmp = "mmusr"; + break; + case 0x806: + tmp = "urp"; + break; + case 0x807: + tmp = "srp"; + break; + default: + tmp = "INVALID"; + break; + } + addstr(dbuf, tmp); + if (!ISBITSET(opc,0)) { + dbuf->val++; + addchar(','); + if (ISBITSET(ext,15)) + get_modregstr(dbuf,14,AR_DIR,0,0); + else + get_modregstr(dbuf,14,DR_DIR,0,0); + dbuf->val--; + } +} + + +/* + * copy const string 's' into ``dbuf''->casm + */ +void +addstr(dbuf, s) + dis_buffer_t *dbuf; + const char *s; +{ + while (*dbuf->casm++ = *s++) + ; + dbuf->casm--; +} + +/* + * copy const string 's' into ``dbuf''->cinfo + */ +void +iaddstr(dbuf, s) + dis_buffer_t *dbuf; + const char *s; +{ + while (*dbuf->cinfo++ = *s++) + ; + dbuf->cinfo--; +} + +void +get_modregstr_moto(dbuf, bit, mod, sz, dd) + dis_buffer_t *dbuf; + int bit, mod, sz, dd; +{ + u_char scale, idx; + const short *nval; + u_short ext; + int disp, odisp, bd, od, reg; + + /* check to see if we have been given the mod */ + if (mod != GETMOD_BEFORE && mod != GETMOD_AFTER) + reg = BITFIELD(*dbuf->val, bit, bit-2); + else if (mod == GETMOD_BEFORE) { + mod = BITFIELD(*dbuf->val, bit, bit-2); + reg = BITFIELD(*dbuf->val, bit-3, bit-5); + } else { + reg = BITFIELD(*dbuf->val, bit, bit-2); + mod = BITFIELD(*dbuf->val, bit-3, bit-5); + } + switch (mod) { + case DR_DIR: + case AR_DIR: + if (mod == DR_DIR) + PRINT_DREG(dbuf, reg); + else + PRINT_AREG(dbuf, reg); + break; + case AR_DIS: + print_disp(dbuf, *(dbuf->val + 1 + dd), SIZE_WORD,reg); + dbuf->used++; + /*FALLTHROUGH*/ + case AR_IND: + case AR_INC: + case AR_DEC: + if (mod == AR_DEC) + addchar('-'); + addchar('('); + PRINT_AREG(dbuf, reg); + addchar(')'); + if (mod == AR_INC) + addchar('+'); + break; + /* mod 6 & 7 are the biggies. */ + case MOD_SPECIAL: + if (reg == 0) { + /* abs short addr */ + print_addr(dbuf, *(dbuf->val + 1 + dd)); + dbuf->used++; + addchar('.'); + addchar('w'); + break; + } else if (reg == 1) { + /* abs long addr */ + print_addr(dbuf, *(u_long *)(dbuf->val + 1 + dd)); + dbuf->used += 2; + addchar('.'); + addchar('l'); + break; + } else if (reg == 2) { + /* pc ind displ. xxx(PC) */ + dbuf->used++; + print_disp(dbuf, *(dbuf->val + 1 + dd), SIZE_WORD, + -1); + addstr(dbuf,"(pc)"); + break; + } else if (reg == 4) { + /* uses ``sz'' to figure imediate data. */ + if (sz == SIZE_BYTE) { + addchar('#'); + prints(dbuf, + *((char *)dbuf->val + 3+ (dd * 2)), sz); + dbuf->used++; + } else if (sz == SIZE_WORD) { + addchar('#'); + prints(dbuf, *(dbuf->val + 1 + dd), sz); + dbuf->used++; + } else if (sz == SIZE_LONG) { + addchar('#'); + prints(dbuf, *(long *)(dbuf->val + 1 + dd), + sz); + dbuf->used += 2; + } else if (sz == SIZE_QUAD) { + dbuf->used += 4; + addstr(dbuf,"#"); + } else if (sz == SIZE_SINGLE) { + dbuf->used += 2; + addstr(dbuf,"#"); + } else if (sz == SIZE_DOUBLE) { + dbuf->used += 4; + addstr(dbuf,"#"); + } else if (sz == SIZE_PACKED) { + dbuf->used += 6; + addstr(dbuf,"#"); + } else if (sz == SIZE_EXTENDED) { + dbuf->used += 6; + addstr(dbuf,"#"); + } + break; + } + /* standrd PC stuff. */ + /*FALLTHROUGH*/ + case AR_IDX: + ext = *(dbuf->val + 1 + dd); + dbuf->used++; + nval = dbuf->val + 2 + dd; /* set to possible displacements */ + scale = BITFIELD(ext,10,9); + idx = BITFIELD(ext,14,12); + + if (ISBITSET(ext,8)) { + /* either base disp, or memory indirect */ + bd = BITFIELD(ext,5,4); + od = BITFIELD(ext,1,0); + if (bd == 1) + disp = 0; + else if (bd == 2) { + dbuf->used++; + disp = *nval++; + } else { + dbuf->used += 2; + disp = *(long *)nval; + nval += 2; + } + + if (od == 1) + odisp = 0; + else if (od == 2) { + dbuf->used++; + odisp = *nval++; + } else if (od == 3) { + dbuf->used += 2; + odisp = *(long *)nval; + nval += 2; + } + } else { + /* + * We set od and bd to zero, these values are + * not allowed in opcodes that use base and + * outer displacement, e.g. we can tell if we + * are using on of those modes by checking + * `bd' and `od'. + */ + od = 0; + bd = 0; + disp = (char)BITFIELD(ext,7,0); + } + /* + * write everything into buf + */ + addchar('('); + if (od) + addchar('['); /* begin memory indirect xxx-indexed */ + prints(dbuf, disp, + bd == 2 ? SIZE_WORD : + bd == 3 ? SIZE_LONG : + SIZE_BYTE); + addchar(','); + if (bd && ISBITSET(ext,7)) { + addchar('z'); + if (mod != MOD_SPECIAL) + PRINT_AREG(dbuf,reg); + else { + addchar('p'); + addchar('c'); + } + } else if (mod == AR_IDX) + PRINT_AREG(dbuf, reg); + else { + addchar('p'); + addchar('c'); + } + + if (od && ISBITSET(ext,2)) + addchar(']'); /* post-indexed. */ + addchar(','); + if (bd && ISBITSET(ext,6)) + addchar('0'); + else { + if (0x8000 & ext) + PRINT_AREG(dbuf, idx); + else + PRINT_DREG(dbuf, idx); + addchar('.'); + addchar(0x800 & ext ? 'l' : 'w'); + if (scale) { + addchar('*'); + addchar('0' + (1 << scale)); + } + } + if (od) { + if (!ISBITSET(ext,2)) + addchar(']'); /* pre-indexed */ + addchar(','); + prints(dbuf, odisp, + od == 2 ? SIZE_WORD : + od == 3 ? SIZE_LONG : + SIZE_BYTE); + } + addchar(')'); + break; + } + *dbuf->casm = 0; +} + +/* mit syntax makes for spaghetti parses */ +void +get_modregstr_mit(dbuf, bit, mod, sz, dd) + dis_buffer_t *dbuf; + int bit, mod, sz, dd; +{ + u_char scale, idx; + const short *nval; + u_short ext; + int disp, odisp, bd, od, reg; + + /* check to see if we have been given the mod */ + if (mod != GETMOD_BEFORE && mod != GETMOD_AFTER) + reg = BITFIELD(*dbuf->val, bit, bit-2); + else if (mod == GETMOD_BEFORE) { + mod = BITFIELD(*dbuf->val, bit, bit-2); + reg = BITFIELD(*dbuf->val, bit-3, bit-5); + } else { + reg = BITFIELD(*dbuf->val, bit, bit-2); + mod = BITFIELD(*dbuf->val, bit-3, bit-5); + } + switch (mod) { + case DR_DIR: + case AR_DIR: + if (mod == DR_DIR) + PRINT_DREG(dbuf, reg); + else + PRINT_AREG(dbuf, reg); + break; + case AR_DIS: + dbuf->used++; /* tell caller we used an ext word. */ + disp = *(dbuf->val + 1 + dd); + /*FALLTHROUGH*/ + case AR_IND: + case AR_INC: + case AR_DEC: + PRINT_AREG(dbuf, reg); + addchar('@' ); + if (mod == AR_DEC) + addchar('-'); + else if (mod == AR_INC) + addchar('+'); + else if (mod == AR_DIS) { + addchar('('); + print_disp(dbuf, disp, SIZE_WORD, reg); + addchar(')'); + } + break; + /* mod 6 & 7 are the biggies. */ + case MOD_SPECIAL: + if (reg == 0) { + /* abs short addr */ + print_addr(dbuf, *(dbuf->val + 1 + dd)); + dbuf->used++; + break; + } else if (reg == 1) { + /* abs long addr */ + print_addr(dbuf, *(u_long *)(dbuf->val + 1 + dd)); + dbuf->used += 2; + break; + } else if (reg == 2) { + /* pc ind displ. pc@(xxx) */ + addstr(dbuf,"pc@("); + print_disp(dbuf, *(dbuf->val + 1 + dd), SIZE_WORD, -1); + dbuf->used++; + addchar(')'); + break; + } else if (reg == 4) { + /* uses ``sz'' to figure imediate data. */ + if (sz == SIZE_BYTE) { + addchar('#'); + prints(dbuf, + *((char *)dbuf->val + 3 + (dd * 2)), sz); + dbuf->used++; + } else if (sz == SIZE_WORD) { + addchar('#'); + prints(dbuf, *(dbuf->val + 1 + dd), sz); + dbuf->used++; + } else if (sz == SIZE_LONG) { + addchar('#'); + prints(dbuf, *(long *)(dbuf->val + 1 + dd), + sz); + dbuf->used += 2; + } else if (sz == SIZE_QUAD) { + dbuf->used += 4; + addstr(dbuf,"#"); + } else if (sz == SIZE_SINGLE) { + dbuf->used += 2; + addstr(dbuf,"#"); + } else if (sz == SIZE_DOUBLE) { + dbuf->used += 4; + addstr(dbuf,"#"); + } else if (sz == SIZE_PACKED) { + dbuf->used += 6; + addstr(dbuf,"#"); + } else if (sz == SIZE_EXTENDED) { + dbuf->used += 6; + addstr(dbuf,"#"); + } + break; + } + /* standrd PC stuff. */ + /*FALLTHROUGH*/ + case AR_IDX: + dbuf->used++; /* indicate use of ext word. */ + ext = *(dbuf->val + 1 + dd); + nval = dbuf->val + 2 + dd; /* set to possible displacements */ + scale = BITFIELD(ext,10,9); + idx = BITFIELD(ext,14,12); + + if (ISBITSET(ext,8)) { + /* either base disp, or memory indirect */ + bd = BITFIELD(ext,5,4); + od = BITFIELD(ext,1,0); + if (bd == 1) + disp = 0; + else if (bd == 2) { + dbuf->used++; + disp = *nval++; + } else { + dbuf->used += 2; + disp = *(long *)nval; + nval += 2; + } + + if (od == 1) + odisp = 0; + else if (od == 2) { + dbuf->used++; + odisp = *nval++; + } else if (od == 3) { + dbuf->used += 2; + odisp = *(long *)nval; + nval += 2; + } + } else { + /* + * We set od and bd to zero, these values are + * not allowed in opcodes that use base and + * outer displacement, e.g. we can tell if we + * are using on of those modes by checking + * `bd' and `od'. + */ + od = 0; + bd = 0; + disp = (char)BITFIELD(ext,7,0); + } + /* + * write everything into buf + */ + /* if base register not suppresed */ + if (mod == AR_IDX && (!bd || !ISBITSET(ext,7))) + PRINT_AREG(dbuf, reg); + else if (mod == MOD_SPECIAL && ISBITSET(ext,7)) { + addchar('z'); + addchar('p'); + addchar('c'); + } else if (mod == MOD_SPECIAL) { + addchar('p'); + addchar('c'); + } + addchar('@'); + addchar('('); + + if (bd && bd != 1) { + prints(dbuf, disp, + bd == 2 ? SIZE_WORD : + bd == 3 ? SIZE_LONG : + SIZE_BYTE); + if (od && !ISBITSET(ext,6) && !ISBITSET(ext,2)) + /* Pre-indexed and not supressing index */ + addchar(','); + else if (od && ISBITSET(ext,2)) { + /* Post-indexed */ + addchar(')'); + addchar('@'); + addchar('('); + } else if (!od) + addchar(','); + } else if (!bd) { + /* don't forget simple 8 bit displacement. */ + prints(dbuf, disp, + bd == 2 ? SIZE_WORD : + bd == 3 ? SIZE_LONG : + SIZE_BYTE); + addchar(','); + } + + /* Post-indexed? */ + if (od && ISBITSET(ext,2)) { + /* have displacement? */ + if (od != 1) { + prints(dbuf, odisp, + od == 2 ? SIZE_WORD : + od == 3 ? SIZE_LONG : + SIZE_BYTE); + addchar(','); + } + } + + if (!bd || !ISBITSET(ext,6)) { + if (ISBITSET(ext,15)) + PRINT_AREG(dbuf,idx); + else + PRINT_DREG(dbuf,idx); + addchar(':'); + addchar(ISBITSET(ext,11) ? 'l' : 'w'); + if (scale) { + addchar(':'); + addchar('0' + (1 << scale)); + } + } + /* pre-indexed? */ + if (od && !ISBITSET(ext,2)) { + if (od != 1) { + addchar(')'); + addchar('@'); + addchar('('); + prints(dbuf, odisp, + od == 2 ? SIZE_WORD : + od == 3 ? SIZE_LONG : + SIZE_BYTE); + } + } + addchar(')'); + break; + } + *dbuf->casm = 0; +} + +/* + * Given a disassembly buffer ``dbuf'' and a starting bit of the + * mod|reg field ``bit'' (or just a reg field if ``mod'' is not + * GETMOD_BEFORE or GETMOD_AFTER), disassemble and write into ``dbuf'' + * the mod|reg pair. + */ +void get_modregstr(dbuf, bit, mod, sz, dispdisp) + dis_buffer_t *dbuf; + int bit, mod, sz, dispdisp; +{ + if (dbuf->mit) + get_modregstr_mit(dbuf,bit,mod,sz,dispdisp); + else + get_modregstr_moto(dbuf,bit,mod,sz,dispdisp); +} + +/* + * given a bit position ``bit'' in the current ``dbuf''->val + * and the ``base'' string of the opcode, append the full + * opcode name including condition found at ``bit''. + */ +void +make_cond(dbuf, bit, base) + dis_buffer_t *dbuf; + int bit; + char *base; +{ + int cc; + const char *ccs; + + cc = BITFIELD(*dbuf->val,bit,bit-3); + ccs = cc_table[cc]; + + addstr(dbuf, base); + addstr(dbuf, ccs); +} + +void +print_fcond(dbuf, cp) + dis_buffer_t *dbuf; + char cp; +{ + addstr(dbuf,fpcc_table[cp]); +} + +void +print_mcond(dbuf, cp) + dis_buffer_t *dbuf; + char cp; +{ + addstr(dbuf,mmcc_table[cp]); +} + +/* + * given dis_buffer_t ``dbuf'' get the immediate value from the + * extension words following current instruction, output a + * hash (``#'') sign and the value. Increment the ``dbuf''->used + * field accordingly. + */ +void +get_immed(dbuf,sz) + dis_buffer_t *dbuf; + int sz; +{ + addchar('#'); + switch (sz) { + case SIZE_BYTE: + prints(dbuf, BITFIELD(*(dbuf->val + 1),7,0), SIZE_BYTE); + dbuf->used++; + break; + case SIZE_WORD: + prints(dbuf, *(dbuf->val + 1), SIZE_WORD); + dbuf->used++; + break; + case SIZE_LONG: + prints(dbuf, *(long *)(dbuf->val + 1), SIZE_LONG); + dbuf->used += 2; + break; + } + return; +} + +void +get_fpustdGEN(dbuf,ext,name) + dis_buffer_t *dbuf; + u_short ext; + const char *name; +{ + int sz; + + /* + * If bit seven is set, its a 040 s/d opcode, then if bit 2 is + * set its "d". This is not documented, however thats the way + * it is. + */ + + addchar(*name++); + if (ISBITSET(ext,7)) { + if(ISBITSET(ext,2)) + addchar('d'); + else + addchar('s'); + } + addstr(dbuf,name); + + if (ISBITSET(ext,14)) { + switch (BITFIELD(ext,12,10)) { + case 0: + addchar('l'); + sz = SIZE_LONG; + break; + case 1: + addchar('s'); + sz = SIZE_SINGLE; + break; + case 2: + addchar('x'); + sz = SIZE_EXTENDED; + break; + case 3: + addchar('p'); + sz = SIZE_PACKED; + break; + case 4: + addchar('w'); + sz = SIZE_WORD; + break; + case 5: + addchar('d'); + sz = SIZE_DOUBLE; + break; + case 6: + addchar('b'); + sz = SIZE_BYTE; + break; + } + addchar('\t'); + get_modregstr(dbuf, 5, GETMOD_BEFORE, sz, 1); + if (BITFIELD(ext,6,3) == 6) { + addchar(','); + PRINT_FPREG(dbuf, BITFIELD(ext,2,0)); + addchar(':'); + PRINT_FPREG(dbuf, BITFIELD(ext,9,7)); + } else if (BITFIELD(ext,5,0) != FTST) { + addchar(','); + PRINT_FPREG(dbuf, BITFIELD(ext,9,7)); + } + } else { + addchar('x'); + addchar('\t'); + PRINT_FPREG(dbuf, BITFIELD(ext,12,10)); + if (BITFIELD(ext,6,3) == 6) { + addchar(','); + PRINT_FPREG(dbuf, BITFIELD(ext,2,0)); + addchar(':'); + PRINT_FPREG(dbuf, BITFIELD(ext,9,7)); + } else if (BITFIELD(ext,5,0) != FTST) { + addchar(','); + PRINT_FPREG(dbuf, BITFIELD(ext,9,7)); + } + } +} + +u_long +get_areg_val(reg) + int reg; +{ + return (0); +} + +/* + * given value ``disp'' print it to ``dbuf''->buf. ``rel'' is a + * register number 0-7 (a0-a7), or -1 (pc). Thus possible extra info + * could be output to the ``dbuf''->info buffer. + */ +void +print_disp(dbuf, disp, sz, rel) + dis_buffer_t *dbuf; + int disp, sz, rel; +{ + off_t diff; + db_sym_t sym; + char *symname; + u_long nv; + + prints(dbuf, disp, sz); + + if (rel == -1) + /* XXX This may be wrong for a couple inst. */ + nv = disp + (u_int)dbuf->val + 2; + else + return; /* nv = get_areg_val(rel); */ + + diff = INT_MAX; + symname = NULL; + sym = db_search_symbol(nv, DB_STGY_PROC, &diff); + db_symbol_values(sym, &symname, 0); + + if (symname) { + iaddstr(dbuf, "disp:"); + iaddstr(dbuf, symname); + iaddchar('+'); + iprintu(dbuf, diff, SIZE_LONG); + iaddchar(' '); + *dbuf->cinfo = 0; + } +} + +void +print_addr(dbuf, addr) + dis_buffer_t *dbuf; + u_long addr; +{ + off_t diff; + db_sym_t sym; + char *symname; + + diff = INT_MAX; + symname = NULL; + sym = db_search_symbol(addr, DB_STGY_ANY, &diff); + db_symbol_values(sym, &symname, 0); + + if (symname) { + if (diff == 0) + addstr(dbuf,symname); + else { + addchar('<'); + addstr(dbuf,symname); + addchar('+'); + printu(dbuf, diff, SIZE_LONG); + addchar('>'); + *dbuf->casm = 0; + } + iaddstr(dbuf,"addr:"); + iprintu(dbuf, addr, SIZE_LONG); + iaddchar(' '); + *dbuf->cinfo = 0; + } else { + printu(dbuf, addr, SIZE_LONG); + } +} + +void +prints(dbuf, val, sz) + dis_buffer_t *dbuf; + int val; + int sz; +{ + extern int db_radix; + + if (val == 0) { + dbuf->casm[0] = '0'; + dbuf->casm[1] = 0; + } else if (sz == SIZE_BYTE) + prints_wb(dbuf, (char)val, sz, db_radix); + else if (sz == SIZE_WORD) + prints_wb(dbuf, (short)val, sz, db_radix); + else + prints_wb(dbuf, (long)val, sz, db_radix); + + dbuf->casm = &dbuf->casm[strlen(dbuf->casm)]; +} + +void +iprints(dbuf, val, sz) + dis_buffer_t *dbuf; + int val; + int sz; +{ + extern int db_radix; + + if (val == 0) { + dbuf->cinfo[0] = '0'; + dbuf->cinfo[1] = 0; + } else if (sz == SIZE_BYTE) + iprints_wb(dbuf, (char)val, sz, db_radix); + else if (sz == SIZE_WORD) + iprints_wb(dbuf, (short)val, sz, db_radix); + else + iprints_wb(dbuf, (long)val, sz, db_radix); + + dbuf->cinfo = &dbuf->cinfo[strlen(dbuf->cinfo)]; +} + +void +printu(dbuf, val, sz) + dis_buffer_t *dbuf; + u_int val; + int sz; +{ + extern int db_radix; + + if (val == 0) { + dbuf->casm[0] = '0'; + dbuf->casm[1] = 0; + } else if (sz == SIZE_BYTE) + printu_wb(dbuf, (u_char)val, sz, db_radix); + else if (sz == SIZE_WORD) + printu_wb(dbuf, (u_short)val, sz, db_radix); + else + printu_wb(dbuf, (u_long)val, sz, db_radix); + dbuf->casm = &dbuf->casm[strlen(dbuf->casm)]; +} + +void +iprintu(dbuf, val, sz) + dis_buffer_t *dbuf; + u_int val; + int sz; +{ + extern int db_radix; + + if (val == 0) { + dbuf->cinfo[0] = '0'; + dbuf->cinfo[1] = 0; + } else if (sz == SIZE_BYTE) + iprintu_wb(dbuf, (u_char)val, sz, db_radix); + else if (sz == SIZE_WORD) + iprintu_wb(dbuf, (u_short)val, sz, db_radix); + else + iprintu_wb(dbuf, (u_long)val, sz, db_radix); + dbuf->cinfo = &dbuf->cinfo[strlen(dbuf->cinfo)]; +} + +void +printu_wb(dbuf, val, sz, base) + dis_buffer_t *dbuf; + u_int val; + int sz, base; +{ + static char buf[sizeof(long) * NBBY / 3 + 2]; + char *p, ch; + + if (base == 16) + addchar('$'); + else if (base == 8) + addchar('0'); + else if (base != 10) { + base = 16; + addchar('$'); + } + + p = buf; + do { + *++p = "0123456789abcdef"[val % base]; + } while (val /= base); + + while (ch = *p--) + addchar(ch); + + *dbuf->casm = 0; +} + +void +prints_wb(dbuf, val, sz, base) + dis_buffer_t *dbuf; + int val; + int sz, base; +{ + if (val < 0) { + addchar('-'); + val = -val; + } + printu_wb(dbuf, val, sz, base); +} + +void +iprintu_wb(dbuf, val, sz, base) + dis_buffer_t *dbuf; + u_int val; + int sz, base; +{ + static char buf[sizeof(long) * NBBY / 3 + 2]; + char *p, ch; + + if (base == 16) + iaddchar('$'); + else if (base == 8) + iaddchar('0'); + else if (base != 10) { + base = 16; + iaddchar('$'); + } + + p = buf; + do { + *++p = "0123456789abcdef"[val % base]; + } while (val /= base); + + while (ch = *p--) + iaddchar(ch); + + *dbuf->cinfo = 0; +} + +void +iprints_wb(dbuf, val, sz, base) + dis_buffer_t *dbuf; + int val; + int sz, base; +{ + if (val < 0) { + iaddchar('-'); + val = -val; + } + iprintu_wb(dbuf, val, sz, base); +} + + +void +prints_bf(dbuf, val, sb, eb) + dis_buffer_t *dbuf; + int val, sb, eb; +{ + if (ISBITSET(val,sb)) + val = (~0 & ~BITFIELD(~0, sb, eb)) | BITFIELD(val, sb, eb); + else + val = BITFIELD(val,sb,eb); + + prints(dbuf, val, SIZE_LONG); +} + +void +printu_bf(dbuf, val, sb, eb) + dis_buffer_t *dbuf; + u_int val; + int sb, eb; +{ + printu(dbuf,BITFIELD(val,sb,eb),SIZE_LONG); +} diff --git a/sys/arch/m68k/m68k/db_disasm.h b/sys/arch/m68k/m68k/db_disasm.h new file mode 100644 index 000000000000..a61c85cb8f82 --- /dev/null +++ b/sys/arch/m68k/m68k/db_disasm.h @@ -0,0 +1,423 @@ +/* + * Copyright (c) 1994 Christian E. Hopps + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Christian E. Hopps. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id: db_disasm.h,v 1.1 1994/03/04 13:44:31 chopps Exp $ + */ + +#define ENCB(b7,b6,b5,b4,b3,b2,b1,b0) \ + ((b7 << 7) | (b6 << 6) | (b5 << 5) | (b4 << 4) | \ + (b3 << 3) | (b2 << 2) | (b1 << 1) | (b0)) + + +#define ENCW(b15,b14,b13,b12,b11,b10,b9,b8,b7,b6,b5,b4,b3,b2,b1,b0) \ + ((ENCB(b15,b14,b13,b12,b11,b10,b9,b8) << 8) |\ + ENCB(b7,b6,b5,b4,b3,b2,b1,b0)) + +/* + * Group Bit-manip (0000) + */ +#define ANDITOCCR_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1) +#define ANDIROSR_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1) +#define EORITOCCR_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1) +#define EORITOSR_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1) +#define ORITOCCR_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1) +#define ORITOSR_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1) +#define ANDITOCCR_INST ENCW(0,0,0,0, 0,0,1,0, 0,0,1,1, 1,1,0,0) +#define ANDIROSR_INST ENCW(0,0,0,0, 0,0,1,0, 0,1,1,1, 1,1,0,0) +#define EORITOCCR_INST ENCW(0,0,0,0, 1,0,1,0, 0,0,1,1, 1,1,0,0) +#define EORITOSR_INST ENCW(0,0,0,0, 1,0,1,0, 0,1,1,1, 1,1,0,0) +#define ORITOCCR_INST ENCW(0,0,0,0, 0,0,0,0, 0,0,1,1, 1,1,0,0) +#define ORITOSR_INST ENCW(0,0,0,0, 0,0,0,0, 0,1,1,1, 1,1,0,0) + +/* + * RTM: this is what gas *and* my amiga assembler spit out, however + * my moto manual disagrees, another 030 manual I have also has + * something different from all of the above! + * + * BTW there may be a consipircy, as many may recognize + * from the acronym associated with this opcode's name. *grin* + */ +#define RTM_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,1,1, 0,0,0,0) +#define RTM_INST ENCW(0,0,0,0, 0,1,1,0, 1,1,0,0, 0,0,0,0) + +/* Note: bit eight being 1 here allows these to be check before all else */ + +/* Note: for movp bits 5-3, specify a mode An, which all the other + * bit 8 set commands do not, so have check first. */ +#define MOVEP_MASK ENCW(1,1,1,1, 0,0,0,1, 0,0,1,1, 1,0,0,0) +#define MOVEP_INST ENCW(0,0,0,0, 0,0,0,1, 0,0,0,0, 1,0,0,0) + +#define BCHGD_MASK ENCW(1,1,1,1, 0,0,0,1, 1,1,0,0, 0,0,0,0) +#define BCLRD_MASK ENCW(1,1,1,1, 0,0,0,1, 1,1,0,0, 0,0,0,0) +#define BSETD_MASK ENCW(1,1,1,1, 0,0,0,1, 1,1,0,0, 0,0,0,0) +#define BTSTD_MASK ENCW(1,1,1,1, 0,0,0,1, 1,1,0,0, 0,0,0,0) +#define BCHGD_INST ENCW(0,0,0,0, 0,0,0,1, 0,1,0,0, 0,0,0,0) +#define BCLRD_INST ENCW(0,0,0,0, 0,0,0,1, 1,0,0,0, 0,0,0,0) +#define BSETD_INST ENCW(0,0,0,0, 0,0,0,1, 1,1,0,0, 0,0,0,0) +#define BTSTD_INST ENCW(0,0,0,0, 0,0,0,1, 0,0,0,0, 0,0,0,0) + +#define BCHGS_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define BCLRS_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define BSETS_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define BTSTS_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define BCHGS_INST ENCW(0,0,0,0, 1,0,0,0, 0,1,0,0, 0,0,0,0) +#define BCLRS_INST ENCW(0,0,0,0, 1,0,0,0, 1,0,0,0, 0,0,0,0) +#define BSETS_INST ENCW(0,0,0,0, 1,0,0,0, 1,1,0,0, 0,0,0,0) +#define BTSTS_INST ENCW(0,0,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0) + +#define CAS2_MASK ENCW(1,1,1,1, 1,1,0,1, 1,1,1,1, 1,1,1,1) +#define CAS2_INST ENCW(0,0,0,0, 1,1,0,0, 1,1,1,1, 1,1,0,0) + +#define CAS_MASK ENCW(1,1,1,1, 1,0,0,1, 1,1,0,0, 0,0,0,0) +#define CHK2_MASK ENCW(1,1,1,1, 1,0,0,1, 1,1,0,0, 0,0,0,0) +#define CMP2_MASK ENCW(1,1,1,1, 1,0,0,1, 1,1,0,0, 0,0,0,0) +#define CAS_INST ENCW(0,0,0,0, 1,0,0,0, 1,1,0,0, 0,0,0,0) +#define CHK2_INST ENCW(0,0,0,0, 0,0,0,0, 1,1,0,0, 0,0,0,0) +#define CMP2_INST ENCW(0,0,0,0, 0,0,0,0, 1,1,0,0, 0,0,0,0) + +/* close ties with Bxxx but bit eight here is 0 and there 1 */ +/* also above (cas,chk2,cmp2) bits 7-6 here are size and never 11 */ +#define ADDI_MASK ENCW(1,1,1,1, 1,1,1,1, 0,0,0,0, 0,0,0,0) +#define ANDI_MASK ENCW(1,1,1,1, 1,1,1,1, 0,0,0,0, 0,0,0,0) +#define CMPI_MASK ENCW(1,1,1,1, 1,1,1,1, 0,0,0,0, 0,0,0,0) +#define EORI_MASK ENCW(1,1,1,1, 1,1,1,1, 0,0,0,0, 0,0,0,0) +#define MOVES_MASK ENCW(1,1,1,1, 1,1,1,1, 0,0,0,0, 0,0,0,0) +#define ORI_MASK ENCW(1,1,1,1, 1,1,1,1, 0,0,0,0, 0,0,0,0) +#define SUBI_MASK ENCW(1,1,1,1, 1,1,1,1, 0,0,0,0, 0,0,0,0) +#define ADDI_INST ENCW(0,0,0,0, 0,1,1,0, 0,0,0,0, 0,0,0,0) +#define ANDI_INST ENCW(0,0,0,0, 0,0,1,0, 0,0,0,0, 0,0,0,0) +#define CMPI_INST ENCW(0,0,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0) +#define EORI_INST ENCW(0,0,0,0, 1,0,1,0, 0,0,0,0, 0,0,0,0) +#define MOVES_INST ENCW(0,0,0,0, 1,1,1,0, 0,0,0,0, 0,0,0,0) +#define ORI_INST ENCW(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0) +#define SUBI_INST ENCW(0,0,0,0, 0,1,0,0, 0,0,0,0, 0,0,0,0) + +/* + * Group misc. (0100) + */ +#define BGND_MASK 0xffff +#define ILLEGAL_MASK 0xffff +#define MOVEFRC_MASK 0xffff +#define MOVETOC_MASK 0xffff +#define NOP_MASK 0xffff +#define RESET_MASK 0xffff +#define RTD_MASk 0xffff +#define RTE_MASK 0xffff +#define RTR_MASK 0xffff +#define RTS_MASK 0xffff +#define STOP_MASK 0xffff +#define TRAPV_MASK 0xffff +#define BGND_INST ENCW(0,1,0,0, 1,0,1,0, 1,1,1,1, 1,0,1,0) +#define ILLEGAL_INST ENCW(0,1,0,0, 1,0,1,0, 1,1,1,1, 1,1,0,0) +#define MOVEFRC_INST ENCW(0,1,0,0, 1,1,1,0, 0,1,1,1, 1,0,1,0) +#define MOVETOC_INST ENCW(0,1,0,0, 1,1,1,0, 0,1,1,1, 1,0,1,1) +#define NOP_INST ENCW(0,1,0,0, 1,1,1,0, 0,1,1,1, 0,0,0,1) +#define RESET_INST ENCW(0,1,0,0, 1,1,1,0, 0,1,1,1, 0,0,0,0) +#define RTD_INST ENCW(0,1,0,0, 1,1,1,0, 0,1,1,1, 0,1,0,0) +#define RTE_INST ENCW(0,1,0,0, 1,1,1,0, 0,1,1,1, 0,0,1,1) +#define RTR_INST ENCW(0,1,0,0, 1,1,1,0, 0,1,1,1, 0,1,1,1) +#define RTS_INST ENCW(0,1,0,0, 1,1,1,0, 0,1,1,1, 0,1,0,1) +#define STOP_INST ENCW(0,1,0,0, 1,1,1,0, 0,1,1,1, 0,0,1,0) +#define TRAPV_INST ENCW(0,1,0,0, 1,1,1,0, 0,1,1,1, 0,1,1,0) +#define SWAP_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,0,0) +#define SWAP_INST ENCW(0,1,0,0, 1,0,0,0, 0,1,0,0, 0,0,0,0) + +#define BKPT_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,0,0) +#define EXTBW_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,0,0) +#define EXTWL_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,0,0) +#define EXTBL_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,0,0) +#define LINKW_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,0,0) +#define LINKL_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,0,0) +#define MOVEFRUSP_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,0,0) +#define MOVETOUSP_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,0,0) +#define UNLK_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,1,1, 1,0,0,0) +#undef BKPT_INST +#define BKPT_INST ENCW(0,1,0,0, 1,0,0,0, 0,1,0,0, 1,0,0,0) +#define EXTBW_INST ENCW(0,1,0,0, 1,0,0,0, 1,0,0,0, 0,0,0,0) +#define EXTWL_INST ENCW(0,1,0,0, 1,0,0,0, 1,1,0,0, 0,0,0,0) +#define EXTBL_INST ENCW(0,1,0,0, 1,0,0,1, 1,1,0,0, 0,0,0,0) +#define LINKW_INST ENCW(0,1,0,0, 1,1,1,0, 0,1,0,1, 0,0,0,0) +#define LINKL_INST ENCW(0,1,0,0, 1,0,0,0, 0,0,0,0, 1,0,0,0) +#define MOVETOUSP_INST ENCW(0,1,0,0, 1,1,1,0, 0,1,1,0, 0,0,0,0) +#define MOVEFRUSP_INST ENCW(0,1,0,0, 1,1,1,0, 0,1,1,0, 1,0,0,0) +#define UNLK_INST ENCW(0,1,0,0, 1,1,1,0, 0,1,0,1, 1,0,0,0) + +#define TRAP_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,1,1, 0,0,0,0) +#define TRAP_INST ENCW(0,1,0,0, 1,1,1,0, 0,1,0,0, 0,0,0,0) + +#define DIVSL_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define DIVUL_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define JMP_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define JSR_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define MOVEFRCCR_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define MOVETOCCR_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define MOVEFRSR_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define MOVETOSR_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define MULSL_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define MULUL_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define NBCD_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define PEA_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define TAS_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define DIVSL_INST ENCW(0,1,0,0, 1,1,0,0, 0,1,0,0, 0,0,0,0) +#define DIVUL_INST DIVSL_INST +#define JMP_INST ENCW(0,1,0,0, 1,1,1,0, 1,1,0,0, 0,0,0,0) +#define JSR_INST ENCW(0,1,0,0, 1,1,1,0, 1,0,0,0, 0,0,0,0) +#define MOVEFRCCR_INST ENCW(0,1,0,0, 0,0,1,0, 1,1,0,0, 0,0,0,0) +#define MOVETOCCR_INST ENCW(0,1,0,0, 0,1,0,0, 1,1,0,0, 0,0,0,0) +#define MOVEFRSR_INST ENCW(0,1,0,0, 0,0,0,0, 1,1,0,0, 0,0,0,0) +#define MOVETOSR_INST ENCW(0,1,0,0, 0,1,1,0, 1,1,0,0, 0,0,0,0) +#define MULSL_INST ENCW(0,1,0,0, 1,1,0,0, 0,0,0,0, 0,0,0,0) +#define MULUL_INST MULSL_INST +#define NBCD_INST ENCW(0,1,0,0, 1,0,0,0, 0,0,0,0, 0,0,0,0) +#define PEA_INST ENCW(0,1,0,0, 1,0,0,0, 0,1,0,0, 0,0,0,0) +#define TAS_INST ENCW(0,1,0,0, 1,0,1,0, 1,1,0,0, 0,0,0,0) + +#define MOVEM_MASK ENCW(1,1,1,1, 1,0,1,1, 1,0,0,0, 0,0,0,0) +#define MOVEM_INST ENCW(0,1,0,0, 1,0,0,0, 1,0,0,0, 0,0,0,0) + +#define CLR_MASK ENCW(1,1,1,1, 1,1,1,1, 0,0,0,0, 0,0,0,0) +#define NEG_MASK ENCW(1,1,1,1, 1,1,1,1, 0,0,0,0, 0,0,0,0) +#define NEGX_MASK ENCW(1,1,1,1, 1,1,1,1, 0,0,0,0, 0,0,0,0) +#define NOT_MASK ENCW(1,1,1,1, 1,1,1,1, 0,0,0,0, 0,0,0,0) +#define TST_MASK ENCW(1,1,1,1, 1,1,1,1, 0,0,0,0, 0,0,0,0) +#define CLR_INST ENCW(0,1,0,0, 0,0,1,0, 0,0,0,0, 0,0,0,0) +#define NEG_INST ENCW(0,1,0,0, 0,1,0,0, 0,0,0,0, 0,0,0,0) +#define NEGX_INST ENCW(0,1,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0) +#define NOT_INST ENCW(0,1,0,0, 0,1,1,0, 0,0,0,0, 0,0,0,0) + /* Note: very similatr to MOVEM but bit 9 differentiates. */ +#define TST_INST ENCW(0,1,0,0, 1,0,1,0, 0,0,0,0, 0,0,0,0) + +#define LEA_MASK ENCW(1,1,1,1, 0,0,0,1, 1,1,0,0, 0,0,0,0) +#define LEA_INST ENCW(0,1,0,0, 0,0,0,1, 1,1,0,0, 0,0,0,0) + +#define CHK_MASK ENCW(1,1,1,1, 0,0,0,1, 0,1,0,0, 0,0,0,0) +#define CHK_INST ENCW(0,1,0,0, 0,0,0,1, 0,0,0,0, 0,0,0,0) + +/* + * Group bitfield/Shift/Rotate. (1110) + */ +#define BFCHG_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define BFCLR_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define BFEXTS_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define BFEXTU_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define BFFFO_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define BFINS_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define BFSET_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define BFTST_MASK ENCW(1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0) + +#define BFCHG_INST ENCW(1,1,1,0, 1,0,1,0, 1,1,0,0, 0,0,0,0) +#define BFCLR_INST ENCW(1,1,1,0, 1,1,0,0, 1,1,0,0, 0,0,0,0) +#define BFEXTS_INST ENCW(1,1,1,0, 1,0,1,1, 1,1,0,0, 0,0,0,0) +#define BFEXTU_INST ENCW(1,1,1,0, 1,0,0,1, 1,1,0,0, 0,0,0,0) +#define BFFFO_INST ENCW(1,1,1,0, 1,1,0,1, 1,1,0,0, 0,0,0,0) +#define BFINS_INST ENCW(1,1,1,0, 1,1,1,1, 1,1,0,0, 0,0,0,0) +#define BFSET_INST ENCW(1,1,1,0, 1,1,1,0, 1,1,0,0, 0,0,0,0) +#define BFTST_INST ENCW(1,1,1,0, 1,0,0,0, 1,1,0,0, 0,0,0,0) + +#define AS_TYPE 0x0 +#define LS_TYPE 0x1 +#define RO_TYPE 0x3 +#define ROX_TYPE 0x2 + +/* + * Group DBcc/TRAPcc/ADDQ/SUBQ (0101) + */ +#define DBcc_MASK ENCW(1,1,1,1, 0,0,0,0, 1,1,1,1, 1,0,0,0) +#define TRAPcc_MASK ENCW(1,1,1,1, 0,0,0,0, 1,1,1,1, 1,0,0,0) +#define Scc_MASK ENCW(1,1,1,1, 0,0,0,0, 1,1,0,0, 0,0,0,0) +#define ADDQ_MASK ENCW(1,1,1,1, 0,0,0,1, 0,0,0,0, 0,0,0,0) +#define SUBQ_MASK ENCW(1,1,1,1, 0,0,0,1, 0,0,0,0, 0,0,0,0) +#define DBcc_INST ENCW(0,1,0,1, 0,0,0,0, 1,1,0,0, 1,0,0,0) +#define TRAPcc_INST ENCW(0,1,0,1, 0,0,0,0, 1,1,1,1, 1,0,0,0) +#define Scc_INST ENCW(0,1,0,1, 0,0,0,0, 1,1,0,0, 0,0,0,0) +#define ADDQ_INST ENCW(0,1,0,1, 0,0,0,0, 0,0,0,0, 0,0,0,0) +#define SUBQ_INST ENCW(0,1,0,1, 0,0,0,1, 0,0,0,0, 0,0,0,0) + +/* + * Group ADD/ADDX (1101) + */ +#define ADDX_MASK ENCW(1,1,1,1, 0,0,0,1, 0,0,1,1, 0,0,0,0) +#define ADDX_INST ENCW(1,1,0,1, 0,0,0,1, 0,0,0,0, 0,0,0,0) +#define ADD_MASK ENCW(1,1,1,1, 0,0,0,0, 0,0,0,0, 0,0,0,0) +#define ADD_INST ENCW(1,1,0,1, 0,0,0,0, 0,0,0,0, 0,0,0,0) + +/* + * Group SUB/SUBX (1001) + */ +#define SUBX_MASK ENCW(1,1,1,1, 0,0,0,1, 0,0,1,1, 0,0,0,0) +#define SUBX_INST ENCW(1,0,0,1, 0,0,0,1, 0,0,0,0, 0,0,0,0) +#define SUB_MASK ENCW(1,1,1,1, 0,0,0,0, 0,0,0,0, 0,0,0,0) +#define SUB_INST ENCW(1,0,0,1, 0,0,0,0, 0,0,0,0, 0,0,0,0) + +/* + * Group CMP/CMPA/EOR (1011) + */ +#define CMPA_MASK ENCW(1,1,1,1, 0,0,0,0, 1,1,0,0, 0,0,0,0) +#define CMPA_INST ENCW(1,0,1,1, 0,0,0,0, 1,1,0,0, 0,0,0,0) + +#define CMP_MASK ENCW(1,1,1,1, 0,0,0,1, 0,0,0,0, 0,0,0,0) +#define CMP_INST ENCW(1,0,1,1, 0,0,0,0, 0,0,0,0, 0,0,0,0) + +#define EOR_MASK ENCW(1,1,1,1, 0,0,0,1, 0,0,0,0, 0,0,0,0) +#define EOR_INST ENCW(1,0,1,1, 0,0,0,1, 0,0,0,0, 0,0,0,0) + +/* + * Group branch. (0110) + */ +#define BRA_MASK ENCW(1,1,1,1, 1,1,1,1, 0,0,0,0, 0,0,0,0) +#define BSR_MASK ENCW(1,1,1,1, 1,1,1,1, 0,0,0,0, 0,0,0,0) +#define Bcc_MASK ENCW(1,1,1,1, 0,0,0,0, 0,0,0,0, 0,0,0,0) +#define BRA_INST ENCW(0,1,1,0, 0,0,0,0, 0,0,0,0, 0,0,0,0) +#define BSR_INST ENCW(0,1,1,0, 0,0,0,1, 0,0,0,0, 0,0,0,0) +#define Bcc_INST ENCW(0,1,1,0, 0,0,0,0, 0,0,0,0, 0,0,0,0) + + +/* + * Group SBCD/DIVx/OR (1000) + */ + +#define UNPKA_MASK ENCW(1,1,1,1, 0,0,0,1, 1,1,1,1, 1,0,0,0) +#define UNPKD_MASK ENCW(1,1,1,1, 0,0,0,1, 1,1,1,1, 1,0,0,0) +#define UNPKA_INST ENCW(1,0,0,0, 0,0,0,1, 1,0,0,0, 1,0,0,0) +#define UNPKD_INST ENCW(1,0,0,0, 0,0,0,1, 1,0,0,0, 0,0,0,0) +#define SBCDA_MASK ENCW(1,1,1,1, 0,0,0,1, 1,1,1,1, 1,0,0,0) +#define SBCDD_MASK ENCW(1,1,1,1, 0,0,0,1, 1,1,1,1, 1,0,0,0) +#define SBCDA_INST ENCW(1,0,0,0, 0,0,0,1, 0,0,0,0, 1,1,1,1) +#define SBCDD_INST ENCW(1,0,0,0, 0,0,0,1, 0,0,0,0, 0,1,1,1) + +#define DIVSW_MASK ENCW(1,1,1,1, 0,0,0,1, 1,1,0,0, 0,0,0,0) +#define DIVUW_MASK ENCW(1,1,1,1, 0,0,0,1, 1,1,0,0, 0,0,0,0) +#define DIVSW_INST ENCW(1,0,0,0, 0,0,0,1, 1,1,0,0, 0,0,0,0) +#define DIVUW_INST ENCW(1,0,0,0, 0,0,0,0, 1,1,0,0, 0,0,0,0) + +#define OR_MASK ENCW(1,1,1,1, 0,0,0,0, 0,0,0,0, 0,0,0,0) +#define OR_INST ENCW(1,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0) + +/* + * Group AND/MUL/ABCD/EXG (1100) + */ +#define ABCDA_MASK ENCW(1,1,1,1, 0,0,0,1, 1,1,1,1, 1,0,0,0) +#define ABCDD_MASK ENCW(1,1,1,1, 0,0,0,1, 1,1,1,1, 1,0,0,0) +#define ABCDA_INST ENCW(1,1,0,0, 0,0,0,1, 0,0,0,0, 1,0,0,0) +#define ABCDD_INST ENCW(1,1,0,0, 0,0,0,1, 0,0,0,0, 0,0,0,0) + +#define MULSW_MASK ENCW(1,1,1,1, 0,0,0,1, 1,1,0,0, 0,0,0,0) +#define MULUW_MASK ENCW(1,1,1,1, 0,0,0,1, 1,1,0,0, 0,0,0,0) +#define MULSW_INST ENCW(1,1,0,0, 0,0,0,1, 1,1,0,0, 0,0,0,0) +#define MULUW_INST ENCW(1,1,0,0, 0,0,0,0, 1,1,0,0, 0,0,0,0) + +#define EXG_MASK ENCW(1,1,1,1, 0,0,0,1, 0,0,1,1, 0,0,0,0) +#define EXG_INST ENCW(1,1,0,0, 0,0,0,1, 0,0,0,0, 0,0,0,0) + +#define AND_MASK ENCW(1,1,1,1, 0,0,0,0, 0,0,0,0, 0,0,0,0) +#define AND_INST ENCW(1,1,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0) + +#define ENCFT(b5,b4,b3,b2,b1,b0) ENCB(0,0,b5,b4,b3,b2,b1,b0) + +#define FABS ENCFT(0,1,1,0,0,0) +#define FACOS ENCFT(0,1,1,1,0,0) +#define FADD ENCFT(1,0,0,0,1,0) +#define FASIN ENCFT(0,0,1,1,0,0) +#define FATAN ENCFT(0,0,1,0,1,0) +#define FATANH ENCFT(0,0,1,1,0,1) +#define FCMP ENCFT(1,1,1,0,0,0) +#define FCOS ENCFT(0,1,1,1,0,1) +#define FCOSH ENCFT(0,1,1,0,0,1) +#define FDIV ENCFT(1,0,0,0,0,0) +#define FETOX ENCFT(0,1,0,0,0,0) +#define FGETEXP ENCFT(0,1,1,1,1,0) +#define FGETMAN ENCFT(0,1,1,1,1,1) +#define FINT ENCFT(0,0,0,0,0,1) +#define FINTRZ ENCFT(0,0,0,0,1,1) +#define FLOG10 ENCFT(0,1,0,1,0,1) +#define FLOG2 ENCFT(0,1,0,1,1,0) +#define FLOGN ENCFT(0,1,0,1,0,0) +#define FLOGNP1 ENCFT(0,0,0,1,1,0) +#define FMOD ENCFT(1,0,0,0,0,1) +#define FMOVE ENCFT(0,0,0,0,0,0) +#define FMUL ENCFT(1,0,0,0,1,1) +#define FNEG ENCFT(0,1,1,0,1,0) +#define FREM ENCFT(1,0,0,1,0,1) +#undef FSCALE +#define FSCALE ENCFT(1,0,0,1,1,0) +#define FSGLDIV ENCFT(1,0,0,1,0,0) +#define FSGLMUL ENCFT(1,0,0,1,1,1) +#define FSIN ENCFT(0,0,1,1,1,0) +#define FSINH ENCFT(0,0,0,0,1,0) +#define FSQRT ENCFT(0,0,0,1,0,0) +#define FSUB ENCFT(1,0,1,0,0,0) +#define FTAN ENCFT(0,0,1,1,1,1) +#define FTANH ENCFT(0,0,1,0,0,1) +#define FTENTOX ENCFT(0,1,0,0,1,0) +#define FTST ENCFT(1,1,1,0,1,0) +#define FTWOTOX ENCFT(0,1,0,0,0,1) + +enum getmod_flag { GETMOD_BEFORE = -1, GETMOD_AFTER = -2 }; + +enum opcode_flags { + CPU_000 = 0x1, CPU_010 = 0x2, CPU_020 = 0x4, CPU_030 = 0x8, + CPU_040 = 0x10, FPU_881 = 0x40, FPU_882 = 0x80, FPU_040 = 0x100, + MMU_851 = 0x400, MMU_030 = 0x800, MMU_040 = 0x1000, + + CPU_ANY = CPU_000 | CPU_010 | CPU_020 | CPU_030 | CPU_040, + FPU_ANY = FPU_881 | FPU_882 | FPU_040, + MMU_ANY = MMU_851 | MMU_030 | MMU_040, + CPU_020UP = CPU_020 | CPU_030 | CPU_040, +}; + +enum mod_types { + DR_DIR = 0, + AR_DIR, AR_IND, AR_INC, AR_DEC, + AR_DIS, AR_IDX, MOD_SPECIAL +}; + +enum sizes { SIZE_BYTE = sizeof(char), SIZE_WORD = sizeof(short), + SIZE_LONG = sizeof(long), SIZE_SINGLE = 5, SIZE_QUAD = 6, + SIZE_DOUBLE = SIZE_QUAD, SIZE_EXTENDED = 7, SIZE_PACKED = 8 }; + +struct dis_buffer { + short *val; /* pointer to memory. */ + char *dasm; /* actual dasm. */ + char *casm; /* current position in dasm. */ + char *info; /* extra info. */ + char *cinfo; /* current position in info. */ + int used; /* length used. */ + int mit; /* use mit sytanx. */ +}; +typedef struct dis_buffer dis_buffer_t; + +#define ISBITSET(val,b) (val & (1<> eb) +#define OPCODE_MAP(x) (BITFIELD(x,15,12)) +#define IS_INST(inst,val) ((inst ## _MASK & val) == inst ## _INST) +#define PRINT_FPREG(dbuf, reg) addstr(dbuf, fpregs[reg]) +#define PRINT_DREG(dbuf, reg) addstr(dbuf, dregs[reg]) +#define PRINT_AREG(dbuf, reg) addstr(dbuf, aregs[reg]) +