#include <stdio.h>
#include <string.h>
#include <mach-o/loader.h>
#include <mach-o/nlist.h>
#include <mach-o/reloc.h>
#include <mach-o/m88k/reloc.h>
#include "stuff/bytesex.h"
#include "otool.h"
#define D(x) (((x) >> 21) & 0x1f)
#define S1(x) (((x) >> 16) & 0x1f)
#define S2(x) ((x) & 0x1f)
#define CR(x) (((x) >> 5) & 0x3f)
#define T1(x) (((x) >> 9) & 0x3)
#define T2(x) (((x) >> 7) & 0x3)
#define TD(x) (((x) >> 5) & 0x3)
#define W(x) (((x) >> 10) & 0x1)
#define B(x) (((x) >> 10) & 0x1)
#define USR(x) (((x) >> 8) & 0x1)
#define TY(x) (((x) >> 10) & 0x3)
#define THRU(x) (((x) >> 7) & 0x1)
#define IO(x) (((x) >> 8) & 0x3)
#define SAT(x) (((x) >> 7) & 0x3)
#define PT(x) (((x) >> 5) & 0x3)
#define B5(x) (((x) >> 21) & 0x1f)
#define M5(x) (((x) >> 21) & 0x1f)
#define W5(x) (((x) >> 5) & 0x1f)
#define OP5(x) ((x) & 0x1f)
#define VEC9(x) ((x) & 0x1ff)
static char ty[] = { 's', 'd', 'x', '?' };
static char *ty_star[] = { ".s", ".d", ".?", ".?" };
static char *w[] = { ".bu", "" };
static char *b[] = { ".hu", ".bu" };
static char *usr[] = { "", ".usr" };
static char *tyr0[] = { ".d", "", ".x", ".?" };
static char *tyr1[] = { ".d", "", ".h", ".b" };
static char *tyf1[] = { ".d", "", ".h", ".x" };
static char *thru[] = { "", ".wt" };
static char *io[] = { "", ".co", ".ci", ".cio" };
static char *sat[] = { "", "s.u", "s.us", "s.s" };
static char *pt[] = { ".n", ".b", ".h", "" };
static char *b5[] = { "??", "??", "eq", "ne", "gt", "le", "lt", "ge", "hi",
"ls", "lo", "hs", "be", "nb", "he", "nh" };
static void print_b5(
unsigned long value);
static void print_m5(
unsigned long value);
static void print_immediate(
unsigned long value,
unsigned long sect_offset,
struct relocation_info *sorted_relocs,
unsigned long nsorted_relocs,
struct nlist *symbols,
unsigned long nsymbols,
struct nlist *sorted_symbols,
unsigned long nsorted_symbols,
char *strings,
unsigned long strings_size,
enum bool verbose);
unsigned long
m88k_disassemble(
char *sect,
unsigned long left,
unsigned long addr,
unsigned long sect_addr,
enum byte_sex object_byte_sex,
struct relocation_info *relocs,
unsigned long nrelocs,
struct nlist *symbols,
unsigned long nsymbols,
struct nlist *sorted_symbols,
unsigned long nsorted_symbols,
char *strings,
unsigned long strings_size,
enum bool verbose)
{
enum byte_sex host_byte_sex;
enum bool swapped;
unsigned long opcode;
unsigned long sect_offset;
host_byte_sex = get_host_byte_sex();
swapped = host_byte_sex != object_byte_sex;
sect_offset = addr - sect_addr;
if(left < sizeof(unsigned long)){
if(left != 0){
memcpy(&opcode, sect, left);
if(swapped)
opcode = SWAP_LONG(opcode);
printf(".long\t0x%08x\n", (unsigned int)opcode);
}
printf("(end of section)\n");
return(left);
}
memcpy(&opcode, sect, sizeof(unsigned long));
if(swapped)
opcode = SWAP_LONG(opcode);
switch(opcode & 0xfc000000){
case 0x00000000:
printf("ld.d\tx%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x04000000:
printf("ld\tx%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x08000000:
printf("ld.hu\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x0c000000:
printf("ld.bu\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x10000000:
printf("ld.d\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x14000000:
printf("ld\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x18000000:
printf("ld.h\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x1c000000:
printf("ld.b\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x20000000:
printf("st.d\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x24000000:
printf("st\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x28000000:
printf("st.h\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x2c000000:
printf("st.b\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x30000000:
printf("st.d\tx%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x34000000:
printf("st\tx%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x38000000:
printf("st.x\tx%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x3c000000:
printf("ld.x\tx%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x40000000:
printf("and\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x44000000:
printf("and.u\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x48000000:
printf("mask\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x4c000000:
printf("mask.u\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x50000000:
printf("xor\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x54000000:
printf("xor.u\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x58000000:
printf("or\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x5c000000:
printf("or.u\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x60000000:
printf("addu\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x64000000:
printf("subu\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x68000000:
printf("divu\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x6c000000:
printf("mulu\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x70000000:
printf("add\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x74000000:
printf("sub\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x78000000:
printf("divs\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x7C000000:
printf("cmp\tr%lu,r%lu,",D(opcode), S1(opcode));
print_immediate(opcode & 0xffff, sect_offset, relocs, nrelocs,
symbols, nsymbols, sorted_symbols, nsorted_symbols,
strings, strings_size, verbose);
break;
case 0x80000000:
switch(opcode & 0x0000f800){
case 0x00004000:
if((opcode & 0x001f001f) == 0)
printf("ldcr\tr%lu,cr%lu\n", D(opcode), CR(opcode));
else
printf("0x%08x\n", (unsigned int)opcode);
break;
case 0x00008000:
if((opcode & 0x03e00000) == 0)
if(S1(opcode) == S2(opcode))
printf("stcr\tr%lu,cr%lu\n", S1(opcode), CR(opcode));
else
printf("stcr\tr%lu,cr%lu\t| error: fields S1 != S2\n",
S1(opcode), CR(opcode));
else
printf("0x%08x\n", (unsigned int)opcode);
break;
case 0x0000c000:
if(S1(opcode) == S2(opcode))
printf("xcr\tr%lu,r%lu,cr%lu\n", D(opcode), S1(opcode),
CR(opcode));
else
printf("xcr\tr%lu,r%lu,cr%lu\t| error: fields S1 != S2\n",
D(opcode), S1(opcode), CR(opcode));
break;
case 0x00004800:
if((opcode & 0x001f001f) == 0)
printf("fldcr\tr%lu,fcr%lu\n", D(opcode), CR(opcode));
else
printf("0x%08x\n", (unsigned int)opcode);
break;
case 0x00008800:
if((opcode & 0x03e00000) == 0)
if(S1(opcode) == S2(opcode))
printf("fstcr\tr%lu,fcr%lu\n", S1(opcode), CR(opcode));
else
printf("fstcr\tr%lu,fcr%lu\t| error: fields S1 != S2\n",
S1(opcode), CR(opcode));
else
printf("0x%08x\n", (unsigned int)opcode);
break;
case 0x0000c800:
if(S1(opcode) == S2(opcode))
printf("fxcr\tr%lu,r%lu,fcr%lu\n", D(opcode), S1(opcode),
CR(opcode));
else
printf("fxcr\tr%lu,r%lu,fcr%lu\t| error: fields S1 != S2\n",
D(opcode), S1(opcode), CR(opcode));
break;
default:
printf("0x%08x\n", (unsigned int)opcode);
break;
}
break;
case 0x84000000:
switch(opcode & 0x00007800){
case 0x00000000:
if(opcode & 0x00008000)
printf("fmul.%c%c%c\tx%lu,x%lu,x%lu\n", ty[TD(opcode)],
ty[T1(opcode)], ty[T2(opcode)], D(opcode),
S1(opcode), S2(opcode));
else
printf("fmul.%c%c%c\tr%lu,r%lu,r%lu\n", ty[TD(opcode)],
ty[T1(opcode)], ty[T2(opcode)], D(opcode),
S1(opcode), S2(opcode));
break;
case 0x00000800:
if(opcode & 0x00008000)
printf("fcvt.%c%c\tx%lu,x%lu\n", ty[TD(opcode)],
ty[T2(opcode)], D(opcode), S2(opcode));
else
printf("fcvt.%c%c\tr%lu,r%lu\n", ty[TD(opcode)],
ty[T2(opcode)], D(opcode), S2(opcode));
break;
case 0x00002000:
if(opcode & 0x00000200)
printf("flt.%cs\tx%lu,r%lu\n", ty[TD(opcode)], D(opcode),
S2(opcode));
else
printf("flt.%cs\tr%lu,r%lu\n", ty[TD(opcode)], D(opcode),
S2(opcode));
break;
case 0x00002800:
if(opcode & 0x00008000)
printf("fadd.%c%c%c\tx%lu,x%lu,x%lu\n", ty[TD(opcode)],
ty[T1(opcode)], ty[T2(opcode)], D(opcode),
S1(opcode), S2(opcode));
else
printf("fadd.%c%c%c\tr%lu,r%lu,r%lu\n", ty[TD(opcode)],
ty[T1(opcode)], ty[T2(opcode)], D(opcode),
S1(opcode), S2(opcode));
break;
case 0x00003000:
if(opcode & 0x00008000)
printf("fsub.%c%c%c\tx%lu,x%lu,x%lu\n", ty[TD(opcode)],
ty[T1(opcode)], ty[T2(opcode)], D(opcode),
S1(opcode), S2(opcode));
else
printf("fsub.%c%c%c\tr%lu,r%lu,r%lu\n", ty[TD(opcode)],
ty[T1(opcode)], ty[T2(opcode)], D(opcode),
S1(opcode), S2(opcode));
break;
case 0x00003800:
if((opcode & 0x00000060) == 0x00000000){
if(opcode & 0x00008000)
printf("fcmp.s%c%c\tr%lu,x%lu,x%lu\n", ty[T1(opcode)],
ty[T2(opcode)], D(opcode), S1(opcode),
S2(opcode));
else
printf("fcmp.s%c%c\tr%lu,r%lu,r%lu\n", ty[T1(opcode)],
ty[T2(opcode)], D(opcode), S1(opcode),
S2(opcode));
}
else if((opcode & 0x00000060) == 0x00000020){
if(opcode & 0x00008000)
printf("fcmpu.s%c%c\tr%lu,x%lu,x%lu\n", ty[T1(opcode)],
ty[T2(opcode)], D(opcode), S1(opcode),
S2(opcode));
else
printf("fcmpu.s%c%c\tr%lu,r%lu,r%lu\n", ty[T1(opcode)],
ty[T2(opcode)], D(opcode), S1(opcode),
S2(opcode));
}
else
printf("0x%08x\n", (unsigned int)opcode);
break;
case 0x00004000:
if((opcode & 0x001f8660) == 0x00008000){
printf("mov%s\tr%lu,x%lu\n", ty_star[T2(opcode)],
D(opcode), S2(opcode));
}
else if((opcode & 0x001f8660) == 0x00000200){
printf("mov%s\tx%lu,r%lu\n", ty_star[T2(opcode)],
D(opcode), S2(opcode));
}
else if((opcode & 0x001f87e0) == 0x00008300){
printf("mov\tx%lu,x%lu\n", D(opcode), S2(opcode));
}
else
printf("0x%08x\n", (unsigned int)opcode);
break;
case 0x00004800:
if((opcode & 0x001f8660) == 0x00008000){
printf("int.s%c\tr%lu,x%lu\n", ty[T2(opcode)], D(opcode),
S2(opcode));
}
else if((opcode & 0x001f8660) == 0x00000000){
printf("int.s%c\tr%lu,r%lu\n", ty[T2(opcode)], D(opcode),
S2(opcode));
}
else
printf("0x%08x\n", (unsigned int)opcode);
break;
case 0x00005000:
if((opcode & 0x001f8660) == 0x00008000){
printf("nint.s%c\tr%lu,x%lu\n", ty[T2(opcode)], D(opcode),
S2(opcode));
}
else if((opcode & 0x001f8660) == 0x00000000){
printf("nint.s%c\tr%lu,r%lu\n", ty[T2(opcode)], D(opcode),
S2(opcode));
}
else
printf("0x%08x\n", (unsigned int)opcode);
break;
case 0x00005800:
if((opcode & 0x001f8660) == 0x00008000){
printf("trnc.s%c\tr%lu,x%lu\n", ty[T2(opcode)], D(opcode),
S2(opcode));
}
else if((opcode & 0x001f8660) == 0x00000000){
printf("trnc.s%c\tr%lu,r%lu\n", ty[T2(opcode)], D(opcode),
S2(opcode));
}
else
printf("0x%08x\n", (unsigned int)opcode);
break;
case 0x00007000:
if(opcode & 0x00008000)
printf("fdiv.%c%c%c\tx%lu,x%lu,x%lu\n", ty[TD(opcode)],
ty[T1(opcode)], ty[T2(opcode)], D(opcode),
S1(opcode), S2(opcode));
else
printf("fdiv.%c%c%c\tr%lu,r%lu,r%lu\n", ty[TD(opcode)],
ty[T1(opcode)], ty[T2(opcode)], D(opcode),
S1(opcode), S2(opcode));
break;
case 0x00007800:
if(opcode & 0x00008000)
printf("fsqrt.%c%c\tx%lu,x%lu\n", ty[TD(opcode)],
ty[T2(opcode)], D(opcode), S2(opcode));
else
printf("fsqrt.%c%c\tr%lu,r%lu\n", ty[TD(opcode)],
ty[T2(opcode)], D(opcode), S2(opcode));
break;
default:
printf("0x%08x\n", (unsigned int)opcode);
break;
}
break;
case 0x88000000:
switch(opcode & 0x0000f800){
case 0x00000000:
printf("pmul\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
break;
case 0x00002000:
printf("padd%s%s\tr%lu,r%lu,r%lu\n", sat[SAT(opcode)],
pt[PT(opcode)], D(opcode), S1(opcode), S2(opcode) );
break;
case 0x00003000:
printf("psub%s%s\tr%lu,r%lu,r%lu\n", sat[SAT(opcode)],
pt[PT(opcode)], D(opcode), S1(opcode), S2(opcode) );
break;
case 0x00003800:
printf("pcmp\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
break;
case 0x00006000:
switch(opcode & 0x00000780){
case 0x00000100:
printf("ppack.8%s\tr%lu,r%lu,r%lu\n", pt[PT(opcode)],
D(opcode), S1(opcode), S2(opcode) );
break;
case 0x00000200:
printf("ppack.16%s\tr%lu,r%lu,r%lu\n", pt[PT(opcode)],
D(opcode), S1(opcode), S2(opcode) );
break;
case 0x00000400:
printf("ppack.32%s\tr%lu,r%lu,r%lu\n", pt[PT(opcode)],
D(opcode), S1(opcode), S2(opcode) );
break;
default:
printf("0x%08x\n", (unsigned int)opcode);
break;
}
break;
case 0x00006800:
printf("punpk%s\tr%lu,r%lu\n", pt[PT(opcode)], D(opcode),
S1(opcode) );
break;
case 0x00007000:
printf("prot\tr%lu,r%lu,<%lu>\n", D(opcode), S1(opcode),
((opcode >> 7) & 0xf) << 2 );
break;
case 0x00007800:
printf("prot\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
break;
default:
printf("0x%08x\n", (unsigned int)opcode);
break;
}
break;
case 0xc0000000:
case 0xc4000000:
if((opcode & 0x04000000) == 0)
printf("br\t");
else
printf("br.n\t");
if((opcode & 0x02000000) == 0)
print_immediate(addr + ((opcode & 0x03ffffff) << 2),sect_offset,
relocs, nrelocs, symbols, nsymbols, sorted_symbols,
nsorted_symbols, strings, strings_size, verbose);
else
print_immediate(addr +
(((opcode & 0x03ffffff) << 2) | 0xf0000000), sect_offset,
relocs, nrelocs, symbols, nsymbols, sorted_symbols,
nsorted_symbols, strings, strings_size, verbose);
break;
case 0xc8000000:
case 0xcc000000:
if((opcode & 0x04000000) == 0)
printf("bsr\t");
else
printf("bsr.n\t");
if((opcode & 0x02000000) == 0)
print_immediate(addr + ((opcode & 0x03ffffff) << 2),sect_offset,
relocs, nrelocs, symbols, nsymbols, sorted_symbols,
nsorted_symbols, strings, strings_size, verbose);
else
print_immediate(addr +
(((opcode & 0x03ffffff) << 2) | 0xf0000000), sect_offset,
relocs, nrelocs, symbols, nsymbols, sorted_symbols,
nsorted_symbols, strings, strings_size, verbose);
break;
case 0xd0000000:
case 0xd4000000:
if((opcode & 0x04000000) == 0)
printf("bb0\t");
else
printf("bb0.n\t");
print_b5(B5(opcode));
printf(",r%lu,", S1(opcode) );
if((opcode & 0x00008000) == 0)
print_immediate(addr + ((opcode & 0x0000ffff) << 2),sect_offset,
relocs, nrelocs, symbols, nsymbols, sorted_symbols,
nsorted_symbols, strings, strings_size, verbose);
else
print_immediate(addr +
(((opcode & 0x0000ffff) << 2) | 0xfffc0000), sect_offset,
relocs, nrelocs, symbols, nsymbols, sorted_symbols,
nsorted_symbols, strings, strings_size, verbose);
break;
case 0xd8000000:
case 0xdc000000:
if((opcode & 0x04000000) == 0)
printf("bb1\t");
else
printf("bb1.n\t");
print_b5(B5(opcode));
printf(",r%lu,", S1(opcode) );
if((opcode & 0x00008000) == 0)
print_immediate(addr + ((opcode & 0x0000ffff) << 2),sect_offset,
relocs, nrelocs, symbols, nsymbols, sorted_symbols,
nsorted_symbols, strings, strings_size, verbose);
else
print_immediate(addr +
(((opcode & 0x0000ffff) << 2) | 0xfffc0000), sect_offset,
relocs, nrelocs, symbols, nsymbols, sorted_symbols,
nsorted_symbols, strings, strings_size, verbose);
break;
case 0xe8000000:
case 0xec000000:
if((opcode & 0x04000000) == 0)
printf("bcnd\t");
else
printf("bcnd.n\t");
print_m5(M5(opcode));
printf(",r%lu,", S1(opcode) );
if((opcode & 0x00008000) == 0)
print_immediate(addr + ((opcode & 0x0000ffff) << 2),sect_offset,
relocs, nrelocs, symbols, nsymbols, sorted_symbols,
nsorted_symbols, strings, strings_size, verbose);
else
print_immediate(addr +
(((opcode & 0x0000ffff) << 2) | 0xfffc0000), sect_offset,
relocs, nrelocs, symbols, nsymbols, sorted_symbols,
nsorted_symbols, strings, strings_size, verbose);
break;
case 0xf0000000:
switch(opcode & 0x0000c000){
case 0x00000000:
switch(opcode & 0x0000f000){
case 0x00000000:
printf("0x%08x\n", (unsigned int)opcode);
break;
case 0x00001000:
if((opcode & 0x00000200) == 0)
printf("ld%s%s\tx%lu,r%lu,r%lu\n", tyr0[TY(opcode)],
usr[USR(opcode)], D(opcode), S1(opcode),
S2(opcode) );
else
printf("ld%s%s\tx%lu,r%lu[r%lu]\n", tyr0[TY(opcode)],
usr[USR(opcode)], D(opcode), S1(opcode),
S2(opcode) );
break;
case 0x00002000:
if((opcode & 0x00000200) == 0)
printf("st%s%s%s\tx%lu,r%lu,r%lu\n", tyr0[TY(opcode)],
usr[USR(opcode)], thru[THRU(opcode)], D(opcode),
S1(opcode), S2(opcode) );
else
printf("st%s%s%s\tx%lu,r%lu[r%lu]\n", tyr0[TY(opcode)],
usr[USR(opcode)], thru[THRU(opcode)], D(opcode),
S1(opcode), S2(opcode) );
break;
default:
printf("0x%08x\n", (unsigned int)opcode);
break;
}
break;
case 0x00004000:
printf("0x%08x\n", (unsigned int)opcode);
break;
case 0x00008000:
switch(opcode & 0x0000fc00){
case 0x00008000:
printf("clr\tr%lu,r%lu,%lu<%lu>\n", D(opcode), S1(opcode),
W5(opcode), OP5(opcode) );
break;
case 0x00008800:
printf("set\tr%lu,r%lu,%lu<%lu>\n", D(opcode), S1(opcode),
W5(opcode), OP5(opcode) );
break;
case 0x00009000:
printf("ext\tr%lu,r%lu,%lu<%lu>\n", D(opcode), S1(opcode),
W5(opcode), OP5(opcode) );
break;
case 0x00009800:
printf("extu\tr%lu,r%lu,%lu<%lu>\n", D(opcode), S1(opcode),
W5(opcode), OP5(opcode) );
break;
case 0x0000a000:
printf("mak\tr%lu,r%lu,%lu<%lu>\n", D(opcode), S1(opcode),
W5(opcode), OP5(opcode) );
break;
case 0x0000a800:
printf("rot\tr%lu,r%lu,<%lu>\n", D(opcode), S1(opcode),
OP5(opcode) );
break;
default:
printf("0x%08x\n", (unsigned int)opcode);
break;
}
break;
case 0x0000c000:
switch(opcode & 0x0000fe00){
case 0x0000d000:
printf("tb0\t");
print_b5(B5(opcode));
printf(",r%lu,%lu\n", S1(opcode), VEC9(opcode) );
break;
case 0x0000d800:
printf("tb1\t");
print_b5(B5(opcode));
printf(",r%lu,%lu\n", S1(opcode), VEC9(opcode) );
break;
case 0x0000e800:
printf("tcnd\t");
print_m5(M5(opcode));
printf(",r%lu,%lu\n", S1(opcode), VEC9(opcode) );
break;
default:
printf("0x%08x\n", (unsigned int)opcode);
break;
}
break;
}
break;
case 0xf4000000:
switch(opcode & 0x0000e000){
case 0x00000000:
if((opcode & 0x00001000) == 0)
if((opcode & 0x00000800) == 0)
if((opcode & 0x00000200) == 0)
printf("xmem%s%s\tr%lu,r%lu,r%lu\n", w[W(opcode)],
usr[USR(opcode)], D(opcode), S1(opcode),
S2(opcode) );
else
printf("xmem%s%s\tr%lu,r%lu[r%lu]\n", w[W(opcode)],
usr[USR(opcode)], D(opcode), S1(opcode),
S2(opcode) );
else
if((opcode & 0x00000200) == 0)
printf("ld%s%s\tr%lu,r%lu,r%lu\n", b[B(opcode)],
usr[USR(opcode)], D(opcode), S1(opcode),
S2(opcode) );
else
printf("ld%s%s\tr%lu,r%lu[r%lu]\n", b[B(opcode)],
usr[USR(opcode)], D(opcode), S1(opcode),
S2(opcode) );
else
if((opcode & 0x00000200) == 0)
printf("ld%s%s\tr%lu,r%lu,r%lu\n", tyr1[TY(opcode)],
usr[USR(opcode)], D(opcode), S1(opcode),
S2(opcode) );
else
printf("ld%s%s\tr%lu,r%lu[r%lu]\n", tyr1[TY(opcode)],
usr[USR(opcode)], D(opcode), S1(opcode),
S2(opcode) );
break;
case 0x00002000:
if((opcode & 0x00001000) == 0)
if((opcode & 0x00000200) == 0)
printf("st%s%s%s\tr%lu,r%lu,r%lu\n", tyr1[TY(opcode)],
usr[USR(opcode)], thru[THRU(opcode)], D(opcode),
S1(opcode), S2(opcode) );
else
printf("st%s%s%s\tr%lu,r%lu[r%lu]\n", tyr1[TY(opcode)],
usr[USR(opcode)], thru[THRU(opcode)], D(opcode),
S1(opcode), S2(opcode) );
else
printf("lda%s\tr%lu,r%lu[r%lu]\n", tyf1[TY(opcode)],
D(opcode), S1(opcode), S2(opcode) );
break;
case 0x00004000:
switch(opcode & 0x00001800){
case 0x00000000:
if((opcode & 0x00000400) == 0)
printf("and\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
else
printf("and.c\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
break;
case 0x00000800:
printf("0x%08x\n", (unsigned int)opcode);
break;
case 0x00001000:
if((opcode & 0x00000400) == 0)
printf("xor\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
else
printf("xor.c\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
break;
case 0x00001800:
if((opcode & 0x00000400) == 0)
printf("or\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
else
printf("or.c\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
break;
}
break;
case 0x00006000:
switch(opcode & 0x00001c00){
case 0x00000000:
printf("addu%s\tr%lu,r%lu,r%lu\n", io[IO(opcode)], D(opcode),
S1(opcode), S2(opcode) );
break;
case 0x00000400:
printf("subu%s\tr%lu,r%lu,r%lu\n", io[IO(opcode)], D(opcode),
S1(opcode), S2(opcode) );
break;
case 0x00000800:
if((opcode & 0x00000100) == 0)
printf("divu\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
else
printf("divu.d\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
break;
case 0x00000c00:
if((opcode & 0x00000200) == 0)
if((opcode & 0x00000100) == 0)
printf("mulu\tr%lu,r%lu,r%lu\n", D(opcode),
S1(opcode), S2(opcode) );
else
printf("mulu.d\tr%lu,r%lu,r%lu\n", D(opcode),
S1(opcode), S2(opcode) );
else
printf("muls\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
break;
case 0x00001000:
printf("add%s\tr%lu,r%lu,r%lu\n", io[IO(opcode)], D(opcode),
S1(opcode), S2(opcode) );
break;
case 0x00001400:
printf("sub%s\tr%lu,r%lu,r%lu\n", io[IO(opcode)], D(opcode),
S1(opcode), S2(opcode) );
break;
case 0x00001800:
printf("divs\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
break;
case 0x00001c00:
printf("cmp\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
break;
}
break;
case 0x00008000:
case 0x0000a000:
switch(opcode & 0x0000ffe0){
case 0x00008000:
printf("clr\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
break;
case 0x00008800:
printf("set\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
break;
case 0x00009000:
printf("ext\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
break;
case 0x00009800:
printf("extu\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
break;
case 0x0000a000:
printf("mak\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
break;
case 0x0000a800:
printf("rot\tr%lu,r%lu,r%lu\n", D(opcode), S1(opcode),
S2(opcode) );
break;
default:
printf("0x%08x\n", (unsigned int)opcode);
break;
}
break;
case 0x0000c000:
switch(opcode & 0x03ffffe0){
case 0x0000c000:
printf("jmp\tr%lu\n", S2(opcode) );
break;
case 0x0000c400:
printf("jmp.n\tr%lu\n", S2(opcode) );
break;
case 0x0000c800:
printf("jsr\tr%lu\n", S2(opcode) );
break;
case 0x0000cc00:
printf("jsr.n\tr%lu\n", S2(opcode) );
break;
default:
printf("0x%08x\n", (unsigned int)opcode);
break;
}
break;
case 0x0000e000:
switch(opcode & 0x0000ffe0){
case 0x0000e800:
printf("ff1\tr%lu,r%lu\n", D(opcode), S2(opcode) );
break;
case 0x0000ec00:
printf("ff0\tr%lu,r%lu\n", D(opcode), S2(opcode) );
break;
case 0x0000f800:
printf("tbnd\tr%lu,r%lu\n", S1(opcode), S2(opcode) );
break;
case 0x0000fc00:
if((opcode & 0x3) == 0)
printf("rte\n");
else
printf("illop%lu\n", opcode & 0x3);
break;
default:
printf("0x%08x\n", (unsigned int)opcode);
break;
}
break;
}
break;
case 0xf8000000:
printf("tbnd\tr%lu,%lu\n", S1(opcode), 0xffff & opcode);
break;
default:
printf(".long 0x%08x\n", (unsigned int)opcode);
break;
}
return(4);
}
static
void
print_b5(
unsigned long value)
{
if(value < 2 || value > 15)
printf("%lu", value);
else
printf("%s", b5[value]);
}
static
void
print_m5(
unsigned long value)
{
switch(value){
case 0x01:
printf("gt0");
break;
case 0x02:
printf("eq0");
break;
case 0x03:
printf("ge0");
break;
case 0x0c:
printf("lt0");
break;
case 0x0d:
printf("ne0");
break;
case 0x0e:
printf("le0");
break;
default:
printf("%lu", value);
}
}
static
void
print_immediate(
unsigned long value,
unsigned long sect_offset,
struct relocation_info *relocs,
unsigned long nrelocs,
struct nlist *symbols,
unsigned long nsymbols,
struct nlist *sorted_symbols,
unsigned long nsorted_symbols,
char *strings,
unsigned long strings_size,
enum bool verbose)
{
long low, high, mid, reloc_found, offset;
unsigned long i, r_address, r_symbolnum, r_type, r_extern,
r_value, r_scattered, pair_r_type;
unsigned short other_half;
char *name;
struct relocation_info *rp, *pairp;
struct scattered_relocation_info *srp, *spairp;
r_symbolnum = 0;
r_type = 0;
r_extern = 0;
r_value = 0;
r_scattered = 0;
other_half = 0;
if(verbose == FALSE){
printf("0x%x\n", (unsigned int)value);
return;
}
reloc_found = 0;
if(nrelocs != 0){
for(i = 0; i < nrelocs; i++){
rp = &relocs[i];
if(rp->r_address & R_SCATTERED){
srp = (struct scattered_relocation_info *)rp;
r_scattered = 1;
r_address = srp->r_address;
r_extern = 0;
r_type = srp->r_type;
r_value = srp->r_value;
}
else{
r_scattered = 0;
r_address = rp->r_address;
r_symbolnum = rp->r_symbolnum;
r_extern = rp->r_extern;
r_type = rp->r_type;
}
if(r_type == M88K_RELOC_PAIR){
fprintf(stderr, "Stray M88K_RELOC_PAIR relocation entry "
"%lu\n", i);
continue;
}
if(r_address == sect_offset){
if(r_type == M88K_RELOC_HI16 || r_type == M88K_RELOC_LO16){
if(i+1 < nrelocs){
pairp = &rp[1];
if(pairp->r_address & R_SCATTERED){
spairp = (struct scattered_relocation_info *)
pairp;
other_half = spairp->r_address & 0xfff;
pair_r_type = spairp->r_type;
}
else{
other_half = pairp->r_address & 0xffff;
pair_r_type = pairp->r_type;
}
if(pair_r_type != M88K_RELOC_PAIR){
fprintf(stderr, "No M88K_RELOC_PAIR relocation "
"entry after entry %lu\n", i);
continue;
}
}
}
reloc_found = 1;
break;
}
if(r_type == M88K_RELOC_HI16 || r_type == M88K_RELOC_LO16){
if(i+1 < nrelocs){
pairp = &rp[1];
if(pairp->r_address & R_SCATTERED){
spairp = (struct scattered_relocation_info *)pairp;
pair_r_type = spairp->r_type;
}
else{
pair_r_type = pairp->r_type;
}
if(pair_r_type == M88K_RELOC_PAIR)
i++;
else
fprintf(stderr, "No M88K_RELOC_PAIR relocation "
"entry after entry %lu\n", i);
}
}
}
}
if(reloc_found && r_extern == 1){
if(symbols[r_symbolnum].n_un.n_strx < 0 ||
(unsigned long)symbols[r_symbolnum].n_un.n_strx >= strings_size)
name = "bad string offset";
else
name = strings + symbols[r_symbolnum].n_un.n_strx;
if(value != 0){
switch(r_type){
case M88K_RELOC_HI16:
value = value << 16 | other_half;
printf("hi16(%s+0x%x)\n", name, (unsigned int)value);
break;
case M88K_RELOC_LO16:
value = other_half << 16 | value;
printf("lo16(%s+0x%x)\n", name, (unsigned int)value);
break;
default:
printf("%s+0x%x\n", name, (unsigned int)value);
}
}
else{
switch(r_type){
case M88K_RELOC_HI16:
value = value << 16 | other_half;
if(value == 0)
printf("hi16(%s)\n", name);
else
printf("hi16(%s+0x%x)\n", name, (unsigned int)value);
break;
case M88K_RELOC_LO16:
value = other_half << 16 | value;
if(value == 0)
printf("lo16(%s)\n", name);
else
printf("lo16(%s+0x%x)\n", name, (unsigned int)value);
break;
default:
if(value == 0)
printf("%s\n", name);
else
printf("%s+0x%x\n", name, (unsigned int)value);
}
}
return;
}
offset = 0;
if(reloc_found){
if(r_type == M88K_RELOC_HI16)
value = value << 16 | other_half;
else if(r_type == M88K_RELOC_LO16)
value = other_half << 16 | value;
if(r_scattered){
offset = value - r_value;
value = r_value;
}
}
low = 0;
high = nsorted_symbols - 1;
mid = (high - low) / 2;
while(high >= low){
if(sorted_symbols[mid].n_value == value){
if(reloc_found){
switch(r_type){
case M88K_RELOC_HI16:
if(offset == 0)
printf("hi16(%s)\n",
sorted_symbols[mid].n_un.n_name);
else
printf("hi16(%s+0x%x)\n",
sorted_symbols[mid].n_un.n_name,
(unsigned int)offset);
break;
case M88K_RELOC_LO16:
if(offset == 0)
printf("lo16(%s)\n",
sorted_symbols[mid].n_un.n_name);
else
printf("lo16(%s+0x%x)\n",
sorted_symbols[mid].n_un.n_name,
(unsigned int)offset);
break;
default:
if(offset == 0)
printf("%s\n",sorted_symbols[mid].n_un.n_name);
else
printf("%s+0x%x\n",
sorted_symbols[mid].n_un.n_name,
(unsigned int)offset);
break;
}
}
else{
if(offset == 0)
printf("%s\n",sorted_symbols[mid].n_un.n_name);
else
printf("%s+0x%x\n",
sorted_symbols[mid].n_un.n_name,
(unsigned int)offset);
}
return;
}
if(sorted_symbols[mid].n_value > value){
high = mid - 1;
mid = (high + low) / 2;
}
else{
low = mid + 1;
mid = (high + low) / 2;
}
}
if(offset == 0){
if(reloc_found){
if(r_type == M88K_RELOC_HI16)
printf("hi16(0x%x)\n", (unsigned int)value);
else if(r_type == M88K_RELOC_LO16)
printf("lo16(0x%x)\n", (unsigned int)value);
}
else
printf("0x%04x\n", (unsigned int)value);
}
else{
if(reloc_found){
if(r_type == M88K_RELOC_HI16)
printf("hi16(0x%x+0x%x)\n",
(unsigned int)value, (unsigned int)offset);
else if(r_type == M88K_RELOC_LO16)
printf("lo16(0x%x+0x%x)\n",
(unsigned int)value, (unsigned int)offset);
}
else
printf("0x%x+0x%x\n",
(unsigned int)value, (unsigned int)offset);
}
return;
}