/* $Id: dsm.c,v 1.12 2000/07/11 21:40:26 garym Exp $ Copyright Motorola, Inc. 1993, 1994 ALL RIGHTS RESERVED You are hereby granted a copyright license to use, modify, and distribute the SOFTWARE so long as this entire notice is retained without alteration in any modified and/or redistributed versions, and that such modified versions are clearly identified as such. No licenses are granted by implication, estoppel or otherwise under any patents or trademarks of Motorola, Inc. The SOFTWARE is provided on an "AS IS" basis and without warranty. To the maximum extent permitted by applicable law, MOTOROLA DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH REGARD TO THE SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) AND ANY ACCOMPANYING WRITTEN MATERIALS. To the maximum extent permitted by applicable law, IN NO EVENT SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE. Motorola assumes no responsibility for the maintenance and support of the SOFTWARE. */ #include "bigbend.h" #include "dink.h" #include "errors.h" #include "asm_dsm.h" #include #include #ifdef ASM_DSM_AVAILABLE extern STATUS is_valid_address_range(); extern STATUS read_from_memory(); extern int more(); extern label_array_element label_table[MAXBRANCHLABEL]; asm_dasm_element ops_and_mnemonics[]; int number_of_mnemonics; /* command operand field of 32-bit instruction */ /* static unsigned int BA ( unsigned int inst ) { return ((inst >> 16) & 0x1F); } static unsigned int BB (unsigned long inst ) { return ((inst >> 11) & 0x1F); } static unsigned int BD (unsigned long inst ) { return (inst & 0x0000FFFC); } static unsigned int BF ( unsigned long inst ) { return ((inst >> 23) & 0x7); } static unsigned int BFA (unsigned long inst ) { return ((inst >> 18) & 0x7); } static unsigned int BI (unsigned long inst ) { return ((inst >> 16) & 0x1F); } static unsigned int BT (unsigned long inst ) { return ((inst >> 21) & 0x1F); } static unsigned int D (unsigned long inst ) { return (inst & 0x0000FFFF); } static unsigned int FLM ( unsigned long inst ) { return ((inst >> 17) & 0x0F); } static unsigned int FRA ( unsigned long inst ) { return ((inst >> 16) & 0x1F); } static unsigned int FRB ( unsigned long inst ) { return ((inst >> 11) & 0x1F); } static unsigned int FRC ( unsigned long inst ) { return ((inst >> 6) & 0x1F); } static unsigned int FRS ( unsigned long inst ) { return ((inst >> 21) & 0x1F); } static unsigned int FRT ( unsigned long inst ) { return ((inst >> 21) & 0x1F); } static unsigned int FXM ( unsigned long inst ) { return ((inst >> 12) & 0x0FF); } static unsigned int LI ( unsigned long inst ) { return (inst & 0x03FFFFFC); } static unsigned int MB ( unsigned long inst ) { return ((inst >> 6) & 0x1F); } static unsigned int ME ( unsigned long inst ) { return ((inst >> 1) & 0x1F); } static unsigned int NB ( unsigned long inst ) { return ((inst >> 11) & 0x1F); } */ static unsigned int RA ( unsigned long inst ) { return ((inst >> 16) & 0x1F); } static unsigned int RB ( unsigned long inst ) { return ((inst >> 11) & 0x1F); } /* static unsigned int RS ( unsigned long inst ) { return ((inst >> 21) & 0x1F); } static unsigned int RT ( unsigned long inst ) { return ((inst >> 21) & 0x1F); } static unsigned int SH ( unsigned long inst ) { return ((inst >> 11) & 0x1F); } static unsigned int SI ( unsigned long inst ) { return (inst & 0x0000FFFF); } static unsigned int TO ( unsigned long inst ) { return ((inst >> 21) & 0x1F); } static unsigned int U ( unsigned long inst ) { return ((inst >> 12) & 0x0F); } static unsigned int UI ( unsigned long inst ) { return (inst & 0x0000FFFF); } static unsigned int SR ( unsigned long inst ) { return ((inst >> 16) & 0x0000000F); } static unsigned int SPR ( unsigned long inst ) { return ((inst >> 11) & 0x3FF); } static unsigned int BO ( unsigned long inst ) { return ((inst >> 21) & 0x1F); } */ /* new VMX fields */ static unsigned int VT6_10 ( unsigned long inst ) { return ((inst >> 21) & 0x1F); } /* unreferenced function static unsigned int VS6_10 ( unsigned long inst ) { return ((inst >> 21) & 0x1F); } */ static unsigned int VA11_15 ( unsigned long inst ) { return ((inst >> 16) & 0x1F); } static unsigned int IMM11_15 ( unsigned long inst ) { return ((inst >> 16) & 0x1F); } static unsigned int VB16_20 ( unsigned long inst ) { return ((inst >> 11) & 0x1F); } static unsigned int VC21_25 ( unsigned long inst ) { return ((inst >> 6) & 0x1F); } static unsigned int SH22_25 ( unsigned long inst ) { return ((inst >> 6) & 0x0F); } static unsigned int IMM9_10 ( unsigned long inst ) { return ((inst >> 21) & 0x03); } static ALTVEC_DISASS_STRUC altvec_tbl[] = { /* mask, opcode, num_opa, fmt, opa_func_1, opa_func_2, opa_func_3, opa_func_4 */ { 0xFC00003F, 0x1000002B, 4, "vperm V%d,V%d,V%d,V%d",{ VT6_10,VA11_15,VB16_20,VC21_25 }}, { 0xFC0007FF, 0x1000000E, 3, "vpkuhum V%d,V%d,V%d",{ VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x1000004E, 3, "vpkuwum V%d,V%d,V%d",{ VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x1000008E, 3, "vpkuhus V%d,V%d,V%d",{ VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x100000CE, 3, "vpkuwus V%d,V%d,V%d",{ VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x1000010E, 3, "vpkshus V%d,V%d,V%d",{ VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x1000014E, 3, "vpkswus V%d,V%d,V%d",{ VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x1000018E, 3, "vpkshss V%d,V%d,V%d",{ VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x100001CE, 3, "vpkswss V%d,V%d,V%d",{ VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x1000020E, 2, "vupkhsb V%d,V%d",{ VT6_10,VB16_20, 0,0 }}, { 0xFC0007FF, 0x1000024E, 2, "vupkhsh V%d,V%d",{ VT6_10,VB16_20, 0,0 }}, { 0xFC0007FF, 0x1000028E, 2, "vupklsb V%d,V%d",{ VT6_10,VB16_20, 0,0 }}, { 0xFC0007FF, 0x100002CE, 2, "vupklsh V%d,V%d",{ VT6_10,VB16_20, 0,0 }}, { 0xFC0007FF, 0x1000030E, 3, "vpkpx V%d,V%d,V%d",{ VT6_10,VA11_15,VB16_20,0 }}, { 0xFC0007FF, 0x1000034E, 2, "vupkhpx V%d,V%d",{ VT6_10,VB16_20, 0, 0 }}, { 0xFC0007FF, 0x100003CE, 2, "vupklpx V%d,V%d",{ VT6_10,VB16_20, 0, 0 }}, { 0xFC0007FF, 0x1000000C, 3, "vmrghb V%d,V%d,V%d", { VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x1000004C, 3, "vmrghh V%d,V%d,V%d", { VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x1000008C, 3, "vmrghw V%d,V%d,V%d", { VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x1000010C, 3, "vmrglb V%d,V%d,V%d", { VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x1000014C, 3, "vmrglh V%d,V%d,V%d", { VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x1000018C, 3, "vmrglw V%d,V%d,V%d", { VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x1000020C, 3, "vspltb V%d,V%d,0x%x", { VT6_10,VB16_20,IMM11_15, 0}}, { 0xFC0007FF, 0x1000024C, 3, "vsplth V%d,V%d,0x%x", { VT6_10,VB16_20,IMM11_15, 0 }}, { 0xFC0007FF, 0x1000028C, 3, "vspltw V%d,V%d,0x%x", { VT6_10,VB16_20,IMM11_15, 0 }}, { 0xFC0007FF, 0x1000030C, 2, "vspltisb V%d,0x%x",{VT6_10,IMM11_15, 0, 0 }}, { 0xFC0007FF, 0x1000034C, 2, "vspltish V%d,0x%x",{VT6_10,IMM11_15, 0, 0 }}, { 0xFC0007FF, 0x1000038C, 2, "vspltisw V%d,0x%x",{VT6_10,IMM11_15, 0, 0 }}, { 0xFC00003F, 0x1000002C, 4, "vsldoi V%d,V%d,V%d,0x%x",{VT6_10,VA11_15,VB16_20,SH22_25}}, { 0xFC0007FF, 0x1000040C, 3, "vslo V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0}}, { 0xFC0007FF, 0x1000044C, 3, "vsro V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0}}, { 0xFC00003F, 0x10000022, 4, "vmladduhm V%d,V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20,VC21_25 }}, { 0xFC00003F, 0x10000024, 4, "vmsumubm V%d,V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20,VC21_25 }}, { 0xFC00003F, 0x10000025, 4, "vmsummbm V%d,V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20,VC21_25 }}, { 0xFC00003F, 0x10000026, 4, "vmsumuhm V%d,V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20,VC21_25 }}, { 0xFC00003F, 0x10000027, 4, "vmsumuhs V%d,V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20,VC21_25 }}, { 0xFC00003F, 0x10000028, 4, "vmsumshm V%d,V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20,VC21_25 }}, { 0xFC00003F, 0x10000029, 4, "vmsumshs V%d,V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20,VC21_25 }}, { 0xFC00003F, 0x10000020, 4, "vmhaddshs V%d,V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20,VC21_25 }}, { 0xFC00003F, 0x10000021, 4, "vmhraddshs V%d,V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20,VC21_25 }}, { 0xFC0007FF, 0x10000788, 3, "vsumsws V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000688, 3, "vsum2sws V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000708, 3, "vsum4sbs V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000608, 3, "vsum4ubs V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000648, 3, "vsum4shs V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000008, 3, "vmuloub V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000108, 3, "vmulosb V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000048, 3, "vmulouh V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000148, 3, "vmulosh V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000208, 3, "vmuleub V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000308, 3, "vmulesb V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000248, 3, "vmuleuh V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000348, 3, "vmulesh V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000000, 3, "vaddubm V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000200, 3, "vaddubs V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000300, 3, "vaddsbs V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000040, 3, "vadduhm V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000240, 3, "vadduhs V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000340, 3, "vaddshs V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000080, 3, "vadduwm V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000280, 3, "vadduws V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000380, 3, "vaddsws V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000400, 3, "vsububm V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000600, 3, "vsububs V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000700, 3, "vsubsbs V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000440, 3, "vsubuhm V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000640, 3, "vsubuhs V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000740, 3, "vsubshs V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000480, 3, "vsubuwm V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000680, 3, "vsubuws V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000780, 3, "vsubsws V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000180, 3, "vaddcuw V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000580, 3, "vsubcuw V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000402, 3, "vavgub V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000502, 3, "vavgsb V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000442, 3, "vavguh V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000542, 3, "vavgsh V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000482, 3, "vavguw V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000582, 3, "vavgsw V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000002, 3, "vmaxub V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000102, 3, "vmaxsb V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000042, 3, "vmaxuh V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000142, 3, "vmaxsh V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000082, 3, "vmaxuw V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000182, 3, "vmaxsw V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000202, 3, "vminub V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000302, 3, "vminsb V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000242, 3, "vminuh V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000342, 3, "vminsh V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000282, 3, "vminuw V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000382, 3, "vminsw V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000006, 3, "vcmpequb V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000046, 3, "vcmpequh V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000086, 3, "vcmpequw V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000206, 3, "vcmpgtub V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000306, 3, "vcmpgtsb V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000246, 3, "vcmpgtuh V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000346, 3, "vcmpgtsh V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000286, 3, "vcmpgtuw V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000386, 3, "vcmpgtsw V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000406, 3, "vcmpequb. V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000446, 3, "vcmpequh. V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000486, 3, "vcmpequw. V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000606, 3, "vcmpgtub. V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000706, 3, "vcmpgtsb. V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000646, 3, "vcmpgtuh. V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000746, 3, "vcmpgtsh. V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000686, 3, "vcmpgtuw. V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000786, 3, "vcmpgtsw. V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000004, 3, "vrlb V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000044, 3, "vrlh V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000084, 3, "vrlw V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000104, 3, "vslb V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000144, 3, "vslh V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000184, 3, "vslw V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x100001C4, 3, "vsl V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000204, 3, "vsrb V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000304, 3, "vsrab V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000244, 3, "vsrh V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000344, 3, "vsrah V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000284, 3, "vsrw V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000384, 3, "vsraw V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x100002C4, 3, "vsr V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000404, 3, "vand V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000444, 3, "vandc V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000484, 3, "vor V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x100004C4, 3, "vxor V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x10000504, 3, "vnor V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC00003F, 0x1000002A, 4, "vsel V%d,V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20,VC21_25}}, { 0xFC0007FF, 0x10000604, 1, "mfvscr V%d",{VT6_10, 0, 0, 0 }}, { 0xFC0007FF, 0x10000644, 1, "mtvscr V%d",{VB16_20, 0, 0, 0 }}, { 0xFC0007FF, 0x1000040A, 3, "vmaxfp V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x1000044A, 3, "vminfp V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x100000C6, 3, "vcmpeqfp V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x100002C6, 3, "vcmpgtfp V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x100001C6, 3, "vcmpgefp V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x100003C6, 3, "vcmpbfp V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x100004C6, 3, "vcmpeqfp. V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x100006C6, 3, "vcmpgtfp. V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x100005C6, 3, "vcmpgefp. V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x100007C6, 3, "vcmpbfp. V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC00003F, 0x1000002E, 4, "vmaddfp V%d,V%d,V%d,V%d",{VT6_10,VA11_15,VC21_25,VB16_20 }}, { 0xFC00003F, 0x1000002F, 4, "vnmsubfp V%d,V%d,V%d,V%d",{VT6_10,VA11_15,VC21_25,VB16_20 }}, { 0xFC0007FF, 0x1000000A, 3, "vaddfp V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x1000004A, 3, "vsubfp V%d,V%d,V%d",{VT6_10,VA11_15,VB16_20, 0 }}, { 0xFC0007FF, 0x1000010A, 2, "vrefp V%d,V%d",{VT6_10,VB16_20, 0, 0 }}, { 0xFC0007FF, 0x1000014A, 2, "vrsqrefp V%d,V%d",{VT6_10,VB16_20, 0, 0 }}, { 0xFC0007FF, 0x1000018A, 2, "vexptefp V%d,V%d",{VT6_10,VB16_20, 0, 0 }}, { 0xFC0007FF, 0x100001CA, 2, "vlogefp V%d,V%d",{VT6_10,VB16_20, 0, 0 }}, { 0xFC0007FF, 0x1000020A, 2, "vrfin V%d,V%d",{VT6_10,VB16_20, 0, 0 }}, { 0xFC0007FF, 0x1000024A, 2, "vrfiz V%d,V%d",{VT6_10,VB16_20, 0, 0 }}, { 0xFC0007FF, 0x1000028A, 2, "vrfip V%d,V%d",{VT6_10,VB16_20, 0, 0 }}, { 0xFC0007FF, 0x100002CA, 2, "vrfim V%d,V%d",{VT6_10,VB16_20, 0, 0 }}, { 0xFC0007FF, 0x1000030A, 3, "vcfux V%d,V%d,0x%x",{VT6_10,VB16_20,IMM11_15, 0 }}, { 0xFC0007FF, 0x1000034A, 3, "vcfsx V%d,V%d,0x%x",{VT6_10,VB16_20,IMM11_15, 0 }}, { 0xFC0007FF, 0x1000038A, 3, "vctuxs V%d,V%d,0x%x",{VT6_10,VB16_20,IMM11_15, 0 }}, { 0xFC0007FF, 0x100003CA, 3, "vctsxs V%d,V%d,0x%x",{VT6_10,VB16_20,IMM11_15, 0 }}, { 0xFC0007FE, 0x7C00000E, 3, "lvebx V%d,R%d,R%d",{VT6_10,RA,RB, 0 }}, { 0xFC0007FE, 0x7C00004E, 3, "lvehx V%d,R%d,R%d",{VT6_10,RA,RB, 0 }}, { 0xFC0007FE, 0x7C00008E, 3, "lvewx V%d,R%d,R%d",{VT6_10,RA,RB, 0 }}, { 0xFC0007FE, 0x7C0000CE, 3, "lvx V%d,R%d,R%d",{VT6_10,RA,RB, 0 }}, { 0xFC0007FE, 0x7C0002CE, 3, "lvxl V%d,R%d,R%d",{VT6_10,RA,RB, 0 }}, { 0xFC0007FE, 0x7C00010E, 3, "stvebx V%d,R%d,R%d",{VT6_10,RA,RB, 0 }}, { 0xFC0007FE, 0x7C00014E, 3, "stvehx V%d,R%d,R%d",{VT6_10,RA,RB, 0 }}, { 0xFC0007FE, 0x7C00018E, 3, "stvewx V%d,R%d,R%d",{VT6_10,RA,RB, 0 }}, { 0xFC0007FE, 0x7C0001CE, 3, "stvx V%d,R%d,R%d",{VT6_10,RA,RB, 0 }}, { 0xFC0007FE, 0x7C0003CE, 3, "stvxl V%d,R%d,R%d",{VT6_10,RA,RB, 0 }}, { 0xFC0007FE, 0x7C00000C, 3, "lvsl V%d,R%d,R%d",{VT6_10,RA,RB, 0 }}, { 0xFC0007FE, 0x7C00004C, 3, "lvsr V%d,R%d,R%d",{VT6_10,RA,RB, 0 }}, { 0xFE0007FE, 0x7C0002AC, 3, "dst R%d,R%d,%d",{RA,RB,IMM9_10, 0 }}, { 0xFE0007FE, 0x7E0002AC, 3, "dstt R%d,R%d,%d",{RA,RB,IMM9_10, 0 }}, { 0xFE0007FE, 0x7C0002EC, 3, "dstst R%d,R%d,%d",{RA,RB,IMM9_10, 0 }}, { 0xFE0007FE, 0x7E0002EC, 3, "dststt R%d,R%d,%d",{RA,RB,IMM9_10, 0 }}, { 0xFE0007FE, 0x7C00066C, 1, "dss %d",{IMM9_10, 0, 0, 0}}, { 0xFE0007FE, 0x7E00066C, 0, "dssall", { 0, 0, 0, 0}}, { 0, 0, 0, { '\0',0 }, {0, 0, 0, 0 }}, }; /* File name: dsm.c Purpose: This file contains the "workhorse", or "toolbox" or "module" or whatever you want to call it. The functions in this file do the "guts" work of the disassembler. This function will validate the addresses and cycle through each address, calling "disassemble_an_opcode" for each. disassemble( start_address, ending_address ) This function does the actual decoding of an opcode (the work horse). disassemble_an_opcode( opcode_to_be_disassembled ) Initializes the data base containing all the mnemonics and opcodes. Big, but simple. init_ops_and_mnemonics() This does the disassemble for a simplified branch instruction...it was so wierd that putting it by itself made it easier. do_simplified_branch(opcode,index,current_add) This prints out the name of the SPR instead of just the number (MATT) GOPRINT_SPR(tmp_long) */ /******************************************************* * function: is_altvec * * description: return the index of altvec_tbl if the * a given 32-bit instruction is altvec * instruction. Otherwise return -1. * * note: ******************************************************/ static int is_altvec( unsigned long opcode ) { register int i; int j = -1; for ( i = 0; altvec_tbl[i].mask != 0; i++ ) { if ( ( opcode & altvec_tbl[i].mask ) == altvec_tbl[i].opcode ) { j = i; break; } } return j; } /****************************************************************** * function: disassemble_altvec * * description: disassemble an altvec instruction based on its * instruction format in the altvec_tbl * * note: *****************************************************************/ static void disassemble_altvec( unsigned long opcode, int altvec_idx ) { register int i; unsigned int opa[4]; for ( i = 0; i < altvec_tbl[altvec_idx].num_opa; i++ ) { if ( altvec_tbl[altvec_idx].opa_func[i] != 0 ) { opa[i] = (*(altvec_tbl[altvec_idx].opa_func[i]))( opcode ); } else { opa[i] = 0; } } switch ( altvec_tbl[altvec_idx].num_opa ) { case 0: PRINT( altvec_tbl[altvec_idx].fmt ); break; case 1: PRINT( altvec_tbl[altvec_idx].fmt, opa[0] ); break; case 2: PRINT( altvec_tbl[altvec_idx].fmt, opa[0],opa[1] ); break; case 3: PRINT( altvec_tbl[altvec_idx].fmt, opa[0], opa[1], opa[2] ); break; default: PRINT( altvec_tbl[altvec_idx].fmt, opa[0],opa[1],opa[2],opa[3] ); break; } } /* --------------------------------------------------------------------- */ /* function: disassemble purpose: This function will display a disassembled version of the memory space requested. inputs: Two parameters are sent in: start_addr and end_addr. The caller is telling us to display data at an adddress in memory and to format what we find there as a PowerPC mneumonic. start_addr: This is the starting address in memory where we will begin to disassemble. end_addr: This is the ending address in memory where we will stop disassembling. outputs: None. return: A virtual pluthera of status codes. Just kidding. I'll put the possible status codes up here when I've finished coding and decide what codes are appropriate. mod history: 6/1/93 MH Modified disassembler to recognize little- endian based opcodes. This is envoked by a "define" in asm_dsm.h. 2/2/93 MH */ STATUS disassemble( unsigned long start_addr, unsigned long end_addr ) { unsigned long opcode; short lines; STATUS status; int altvec_idx; // Get the opcodes from 'start_addr', which we will update as needed. lines = 1; while (start_addr <= end_addr) { // Get the opcode directly from memory. if ((status = read_from_memory( start_addr, &opcode )) != SUCCESS) return( status ); PRINT( "0x%08lx 0x%08lx ", start_addr, opcode ); /* Okay, I have an opcode that I've read from memory, now I need to call the guts function that actually does the work (as opposed to this function, which only takes the credit). */ /* test the upper 6 bits of opcode */ if ( ( ( (opcode >> 26) & 0x3F ) == 4 || ( (opcode >> 26) & 0x3F ) == 31 ) && ( altvec_idx = is_altvec( opcode ) ) >= 0 ) { /* new for VMX */ disassemble_altvec( opcode, altvec_idx ); } else disassemble_an_opcode( opcode, start_addr ); // Finish up. PRINT( "\n" ); // Find the next opcode. Aren't RISC machines nice? start_addr += 4; if (++lines >= 23) { if (!more()) return( SUCCESS ); lines = 1; } } return( SUCCESS ); } /* 1 2 3 4 5 6 7 8 01234567890123456789012345678901234567890123456789012345678901234567890123456789 */ /* --------------------------------------------------------------------- */ /* function: disassemble_an_opcode purpose: This function will disassemble an opcode that's sent in. It will print out the disassembled version of the opcode BUT will NOT print a carrage return at the end of line. It's up to the caller to do that. inputs: current add: This is the current address of the PC opcode: This is the 32-bit opcode that we will disassemble. outputs: None: return: None. mod history: 2/2/93 MH 10/1/95 MM added simplified mnemonics */ STATUS disassemble_an_opcode( opcode, current_add ) /* "opcode" is the 32-bit piece of data that I want to disassemble. It may be an unidentifiable opcode, in which case, I'll simply return a string with the original opcode in it. */ unsigned long opcode; unsigned long current_add; { /* Mnemonic holds the ASCII string which is the mnemonic of the instruction I'm decoding. */ char mnemonic[80]; /* This variable acts as a general-purpose index pointer... */ int index; /* This variable is used for when I need to pull out a field of the opcode. The macros that "pull out" a field are in the ".h" file. */ unsigned long tmp_long; /* The variable "status" will be used when I call other functions and they return status. I've typed it as "STATUS" because someone else will define that type. It will most likely be a long, but who really knows... */ STATUS status; /* An int to move thru label_table */ int count; /* used to call label routine */ char new_label[20]; /* Put a 0 in "index" since we want our search function to search for an opcode that matches the "opcode" parameter that we're sending in. */ index = 0; /* Call the search function sending in the appropriate values for "opcode" and "index". We don't care what's being sent in the "tmp_token" parameter. */ status = search_ops_and_mnemonics( opcode, mnemonic, &index ); /* Add the branch label if one pertains to this memory address! */ for(count=0;count<=MAXBRANCHLABEL;count++) { if (current_add == label_table[count].address) { PRINT("BRANCH LABEL %s:\n",label_table[count].name); PRINT("0x%08lx ",current_add); PRINT("0x%08lx ",opcode); break; } } /* PRINT("\n opcode=%x index=%d\n",opcode,index); */ if( status != SUCCESS ) { /* If I get here, then there was no match for the opcode. This must be a piece of data. We'll print it out as such. */ PRINT( "WORD 0x%08lx", opcode ); return( SUCCESS ); } else { /* If I get here, I have a match...now I need to determine if I have a simplified branch mnemonic or not...if not then skip the next chunk...else, I can't just take the first simplified mnemonic I get...I need to break it up a little bit and get a better simplified mnemonic. */ if( ops_and_mnemonics[index].form >= smBC && ops_and_mnemonics[index].form <= (smBCCTRL+4) ) { /* I've got a simplified branch mnemonic!! Now, look at bits 11-15 and make a call to search the mnemonic list again but this time search for a match on the NEW FORM AND the bits HEX opcode!! Call a new function (do_simplified_branch) to do the work!! */ do_simplified_branch( opcode, index, current_add); return( SUCCESS ); } /* If I get here, I have a match and the real work begins... First thing we need to do is print out the mnemonic of the instruction. */ PRINT( "%-12s", ops_and_mnemonics[index].mnemonic ); /* Now I need to pull some specific fields out of the opcode and decode them, print out the values that I pull out. What fields I pull out will depend on the "form" of the instruction. I don't like "switch" statements, so I'm going to use a series of "if-then-else". */ if( ops_and_mnemonics[index].form == I ) { /* We've got an "I" form instruction. Pull the appropriate fields and print the opcode. */ tmp_long = EXTRACT_LI( opcode ); /* PRINT("\n MATT tmplong going to test = %d ... %06lx\n",(int)tmp_long,tmp_long); */ /* MATT GOMER */ tmp_long = test_branch_label( opcode, current_add, tmp_long, &new_label[0] ); if (tmp_long == 0) { PRINT( "%s",new_label); for (count=0;count",label_table[count].address ); break; } } else PRINT( "0x%02lx",tmp_long); /* Print out the rest of the mnemonic */ /* PRINT( "0x%06lx", tmp_long ); */ } else if( ops_and_mnemonics[index].form == B ) { /* We've got a "B" form instruction. Pull the appropriate fields and print the opcode. */ PRINT("\nDIPSHIT!\n"); tmp_long = EXTRACT_BO( opcode ); PRINT( "0x%02lx, ", tmp_long ); tmp_long = EXTRACT_BI( opcode ); PRINT( "0x%02lx, ", tmp_long ); /* MATT HERE! */ tmp_long = EXTRACT_BD( opcode ); tmp_long = test_branch_label( opcode, current_add, tmp_long, &new_label[0] ); /* PRINT("\nMATT HERE! ... \n"); */ if (tmp_long == 0) { PRINT( "%s",new_label); for (count=0;count",label_table[count].address ); break; } } else PRINT( "0x%02lx",tmp_long); } else if( ops_and_mnemonics[index].form == SC ) { /* We've got a "SC" form instruction. Pull the appropriate fields and print the opcode. */ /* SC form instructions have no arguments */ PRINT( "" ); } else if( ops_and_mnemonics[index].form == D || ops_and_mnemonics[index].form == smD) { /* We've got a "D" form instruction or a simplified mnemonic that is simplified to a mnemonic with a "D" form. Pull the appropriate fields and print the opcode. */ /* This instruction set is such a %$#&ing KLUDGE! I need to test a few things on the primary opcode to determine what fields I need to pull out. That's right, the type of instruction doesn't do that for me! */ /* I'm going to break the D form instructions into 5 catagories, based on the operands in the mnemonic: 1. rt, ra, si 1a. bf, l, ra, si 1b. to, ra, si 1c. ra, rs, si 2. rt, d(ra) 2a. frt, d(ra) */ tmp_long = EXTRACT_PRIMARY( opcode ); if( ( tmp_long <= 29 ) && ( tmp_long >= 2 ) ) { /* We've got all the 1 and 1a catagories in here. Now we need to seperate those two catagories. */ /* if it's NOP instruction do nothing! */ if ( tmp_long == 24 && ops_and_mnemonics[index].form == smD && strncmp(&ops_and_mnemonics[index].mnemonic[0], "nop",3) == 0 ) { } else if( ( tmp_long == 11 ) || ( tmp_long == 10 ) ) { /* Now I've got the 1a. instructions. */ tmp_long = EXTRACT_BF( opcode ); if ( ops_and_mnemonics[index].form==smD) { PRINT( "cr%01d, ", (int)( tmp_long ) ); } else PRINT( "%01d, ",(int)(tmp_long)); /* MATT simplified mnemonic!... */ /* cmplwi/cmpwi */ if ( ops_and_mnemonics[index].form != smD ) { tmp_long = EXTRACT_L( opcode ); PRINT("%01d, ",(int)(tmp_long)); } tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); } else if( ( tmp_long == 2 ) || ( tmp_long == 3 ) ) { /* Now I've got the 1b. instructions. */ /* MATT simplified mnemonic... */ /* ALL of the trap mnemonics (tw...) */ if ( ops_and_mnemonics[index].form != smD ) { tmp_long = EXTRACT_TO( opcode ); PRINT( "0x%2lx, ", tmp_long ); } tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); } else if( ( tmp_long == 28 ) || ( tmp_long == 29 ) || ( tmp_long == 24 ) || ( tmp_long == 25 ) || ( tmp_long == 26 ) || ( tmp_long == 27 ) ) { /* Now I've isolated out the 1c instructions. */ tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RS( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); } else { /* Now I have to take care of the 1. instructions. */ tmp_long = EXTRACT_RT( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); if(ops_and_mnemonics[index].form == smD && ops_and_mnemonics[index].mnemonic[0] == 'l' ) { } else { tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); } } /* Now take care of the last operand of types 1, 1a, and 1b instructions. */ /* MATT simplified mnemonic!...*/ /* all smD forms!! */ tmp_long = EXTRACT_SI( opcode ); /* if it's NOP instruction do nothing! */ if ( EXTRACT_PRIMARY(opcode) == 24 && ops_and_mnemonics[index].form == smD && strncmp(&ops_and_mnemonics[index].mnemonic[0], "nop",3)==0 ) { } else if(ops_and_mnemonics[index].form == smD && EXTRACT_PRIMARY(opcode) >= 12 && EXTRACT_PRIMARY(opcode) <= 15 && ops_and_mnemonics[index].mnemonic[0] != 'l' ) { PRINT( "0x%x",( (-tmp_long)&0x00ffff) ); } else { PRINT( "0x%x", (tmp_long&0x00ffff) ); if(ops_and_mnemonics[index].form==smD && strncmp(& ops_and_mnemonics[index].mnemonic[0], "la",2)==0 ) { tmp_long = EXTRACT_RA(opcode); PRINT("(r%02d)",tmp_long); } } } else { /* By definition, if we get here, we're dealing with types 2, and 2a instructions. */ /* First thing we'll do is seperate out the type 2a instructions. */ if( ( tmp_long == 50 ) || ( tmp_long == 51 ) || ( tmp_long == 48 ) || ( tmp_long == 49 ) || ( tmp_long == 54 ) || ( tmp_long == 55 ) || ( tmp_long == 52 ) || ( tmp_long == 53 ) ) { /* Deal with getting the first operand of type 2a instructions. */ tmp_long = EXTRACT_FRT( opcode ); PRINT( "f%02d, ", (int)( tmp_long ) ); } else { /* If I get here, then by definition, I'm dealing with type 2 instructions. All I need to do here is get the first operand of these types of instructions. */ tmp_long = EXTRACT_RT( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); } /* Now I need to get the last 2 operands for types 2, and 2a instructions. */ tmp_long = EXTRACT_D( opcode ); PRINT( "0x%01lx( ", tmp_long ); tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d )", (int)( tmp_long ) ); } } else if( ops_and_mnemonics[index].form == DS ) { /* We've got a "DS" form instruction. Pull the appropriate fields and print the opcode. */ tmp_long = EXTRACT_RT( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_DS( opcode ); PRINT( "0x%04lx( ", tmp_long ); tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d )", (int)( tmp_long ) ); } else if( ops_and_mnemonics[index].form == X || ops_and_mnemonics[index].form == smX ) { /* We've got a "X" form instruction or a "smX" form. Pull the appropriate fields and print the opcode. */ /* Here are the 20 cases we need to check for inside the X Form definition. bits... # 0 6 11 16 21 31 1 OPCD RT RA RB XO RC 2 OPCD BF\L RA RB XO RC 3 OPCD RS RA \\\ XO RC 4 OPCD \\\ RA RB XO RC 5 OPCD \\\ \\\ \\\ XO RC 6 OPCD FRT \\\ FRB XO RC 7 OPCD BF \\ FRA FRB XO RC 8 OPCD FRT RA RB XO RC 9 OPCD RS RA NB XO RC 10 OPCD BF\\ BFA\\ \\\ XO RC 11 OPCD BF\\ \\\ \\\ XO RC 12 OPCD RS \\\ \\\ XO RC 13 OPCD FRT \\\ \\\ XO RC 14 OPCD RT BF \\\ XO RC 15 OPCD RT \\\ RB XO RC 16 OPCD BF \\\ \\\ XO RC 17 OPCD BF\\ \\\ U\ XO RC 18 OPCD \\\ \\\ RB XO RC 19 OPCD RT RA SH XO RC 20 OPCD TO RA RB XO RC */ /* The X form of instructions seems to be the "catch-all" form. There are actually quite a few different things thrown into this sack. For that reason, this section of code is way-sphagetti-like. Sorry, just couldn't be avoided... */ /* First, get the opcode. We'll have to do some comparisons on it. */ tmp_long = EXTRACT_PRIMARY( opcode ); if( tmp_long == 31 ) { tmp_long = EXTRACT_SECONDARY_X( opcode ); if( ( tmp_long == 0 ) || ( tmp_long == 32 ) ) { /* Take care of case 2 */ tmp_long = EXTRACT_BF( opcode ); PRINT( "cr%01d, ", (int)( tmp_long ) ); /* MATT simplified mnemonic!... */ /* cmpw/cmplw */ if (ops_and_mnemonics[index].form!=smX) { tmp_long = EXTRACT_L( opcode ); PRINT( "%01d, ", (int)( tmp_long ) ); } tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RB( opcode ); PRINT( "r%02d", (int)( tmp_long ) ); } else if( ( tmp_long == 58 ) || ( tmp_long == 26 ) || ( tmp_long == 954 ) || ( tmp_long == 922 ) || ( tmp_long == 986 ) ) { /* Take care of case 3 */ tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RS( opcode ); PRINT( "r%02d", (int)( tmp_long ) ); } else if( ( tmp_long == 86 ) || ( tmp_long == 470 ) || ( tmp_long == 54 ) || ( tmp_long == 278 ) || ( tmp_long == 246 ) || ( tmp_long == 1014 ) || ( tmp_long == 982 ) ) { /* Take care of case 4 */ tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RB( opcode ); PRINT( "r%02d", (int)( tmp_long ) ); } else if( ( tmp_long == 854 ) || ( tmp_long == 498 ) || ( tmp_long == 598 ) || ( tmp_long == 370 ) || ( tmp_long == 566 ) ) { /* Take care of case 5 */ /* Case 5 has no arguments, so print nothing. */ PRINT( "" ); } else if( ( tmp_long == 599 ) || ( tmp_long == 631 ) || ( tmp_long == 567 ) || ( tmp_long == 535 ) || ( tmp_long == 759 ) || ( tmp_long == 727 ) || ( tmp_long == 983 ) || ( tmp_long == 695 ) || ( tmp_long == 663 ) ) { /* take care of case 8 */ tmp_long = EXTRACT_FRT( opcode ); PRINT( "f%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RB( opcode ); PRINT( "r%02d", (int)( tmp_long ) ); } else if( ( tmp_long == 597 ) || ( tmp_long == 725 ) ) { /* Take care of case 9 */ tmp_long = EXTRACT_RS( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_NB( opcode ); PRINT( "0x%02lx", tmp_long ); } else if( ( tmp_long == 512 ) ) { /* Take care of case 11 */ tmp_long = EXTRACT_BF( opcode ); PRINT( "0x%01lx", tmp_long ); } else if( ( tmp_long == 19 ) || ( tmp_long == 83 ) || ( tmp_long == 146 ) ) { /* Take care of case 12 */ tmp_long = EXTRACT_RS( opcode ); PRINT( "r%02d", (int)( tmp_long ) ); } else if(( tmp_long == 210 )) /* mtsr SR, rx */ { /* Take care of case 14, part 1 */ tmp_long = EXTRACT_BI( opcode ); /* We need to make sure that the field I extracted is only 4 bits (bits 12-15). This case is only for the mtsr and mfsr instructions. */ tmp_long = tmp_long & 0xF; PRINT( "0x%01lx, ", tmp_long ); tmp_long = EXTRACT_RS( opcode ); PRINT( "r%02d", (int)( tmp_long ) ); } else if(( tmp_long == 595 )) /* mfsr rx, SR */ { /* Take care of case 14, part 2 */ tmp_long = EXTRACT_RS( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_BI( opcode ); /* We need to make sure that the field I extracted is only 4 bits (bits 12-15). This case is only for the mtsr and mfsr instructions. */ tmp_long = tmp_long & 0xF; PRINT( "0x%01lx", tmp_long ); } else if( ( tmp_long == 659 ) || ( tmp_long == 242 ) ) { /* Take care of case 15 */ tmp_long = EXTRACT_RS( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RB( opcode ); PRINT( "r%02d", (int)( tmp_long ) ); } else if( ( tmp_long == 434 ) || ( tmp_long == 466 ) || ( tmp_long == 306 ) || ( tmp_long == 338 ) ) { /* Take care of case 18 */ tmp_long = EXTRACT_RB( opcode ); PRINT( "r%02d", (int)( tmp_long ) ); } else if( ( tmp_long == 184 ) || ( tmp_long == 248 ) || ( tmp_long == 952 ) || ( tmp_long == 824 ) || ( tmp_long == 696 ) || ( tmp_long == 760 ) ) { /* Take care of case 19 */ tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RS( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_SH32( opcode ); PRINT( "0x%02lx", tmp_long ); } else if( ( tmp_long == 68 ) || ( tmp_long == 4 ) ) { /* Take care of case 20 */ tmp_long = EXTRACT_TO( opcode ); /* MATT simplifid mnemonic!...*/ /* All trap mnemonics! */ if(ops_and_mnemonics[index].form != smX) { PRINT( "0x%02lx, ", tmp_long ); } /* MATT special trap mnemonic!...*/ /* trap mnemonic gets nothing printed! */ if ( tmp_long == 31 && ops_and_mnemonics[index].form == smX ) {} else { tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RB( opcode ); PRINT( "r%02d", (int)( tmp_long ) ); } } else { /* Any other X form instructions that have 31 as their primary opcode, are in case 1. */ /* However... If it's a ld or st that's of the X form, are fit in this catagory, then the operands do not get switched, like they do for all other instructions that filter into this cubby hole. */ tmp_long = EXTRACT_SECONDARY_X(opcode); if( ( tmp_long == 119 ) || ( tmp_long == 87 ) || ( tmp_long == 279 ) || ( tmp_long == 311 ) || ( tmp_long == 343 ) || ( tmp_long == 375 ) || ( tmp_long == 23 ) || ( tmp_long == 55 ) || ( tmp_long == 341 ) || ( tmp_long == 373 ) || ( tmp_long == 21 ) || ( tmp_long == 53 ) || ( tmp_long == 215 ) || ( tmp_long == 247 ) || ( tmp_long == 407 ) || ( tmp_long == 439 ) || ( tmp_long == 311 ) || ( tmp_long == 151 ) || ( tmp_long == 183 ) || ( tmp_long == 149 ) || ( tmp_long == 181 ) || ( tmp_long == 790 ) || ( tmp_long == 534 ) || ( tmp_long == 918 ) || ( tmp_long == 662 ) || ( tmp_long == 533 ) || ( tmp_long == 661 ) || ( tmp_long == 20 ) || ( tmp_long == 84 ) || ( tmp_long == 150 ) || ( tmp_long == 214 ) || ( tmp_long == 310 ) || ( tmp_long == 438 ) || ( tmp_long == 7 ) || ( tmp_long == 39 ) || ( tmp_long == 71 ) || ( tmp_long == 6 ) || ( tmp_long == 38 ) || ( tmp_long == 103 ) || ( tmp_long == 359 ) || ( tmp_long == 135 ) || ( tmp_long == 167 ) || ( tmp_long == 199 ) || ( tmp_long == 231 ) || ( tmp_long == 487 ) ) { tmp_long = EXTRACT_RS( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RB( opcode ); PRINT( "r%02d", (int)( tmp_long ) ); } else { /* We're back to the few X form instructions that fit into this little catagory who have their arguments reversed. In other words, their arguments appear in the assembly as: RA,RS,RB and are encoded as RS,RA,RB. */ tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); /* MATT simplified mnemonics!...*/ /* not/mr */ if(ops_and_mnemonics[index].form != smX) { tmp_long = EXTRACT_RS( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RB( opcode ); PRINT( "r%02d", (int)( tmp_long ) ); } else { tmp_long = EXTRACT_RS( opcode ); PRINT( "r%02d", (int)( tmp_long ) ); } } } } else if( tmp_long == 63 ) { /* Take care of cases where primary opcode is 63. */ tmp_long = EXTRACT_SECONDARY_X( opcode ); if( ( tmp_long == 264 ) || ( tmp_long == 846 ) || ( tmp_long == 814 ) || ( tmp_long == 815 ) || ( tmp_long == 14 ) || ( tmp_long == 15 ) || ( tmp_long == 72 ) || ( tmp_long == 136 ) || ( tmp_long == 40 ) || ( tmp_long == 12 ) ) { /* take care of case 6 */ tmp_long = EXTRACT_FRT( opcode ); PRINT( "f%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_FRB( opcode ); PRINT( "f%02d", (int)( tmp_long ) ); } else if( ( tmp_long == 32 ) || ( tmp_long == 0 ) ) { /* take care of case 7 */ tmp_long = EXTRACT_BF( opcode ); PRINT( "0x%02lx, ", tmp_long ); tmp_long = EXTRACT_FRA( opcode ); PRINT( "f%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_FRB( opcode ); PRINT( "f%02d", (int)( tmp_long ) ); } else if( ( tmp_long == 64 ) ) { /* take care of case 10 */ tmp_long = EXTRACT_BF( opcode ); PRINT( "0x%01lx, ", tmp_long ); tmp_long = EXTRACT_BFA( opcode ); PRINT( "0x%01lx", tmp_long ); } else if( ( tmp_long == 583 ) ) { /* take care of case 13 */ tmp_long = EXTRACT_FRT( opcode ); PRINT( "f%02d", (int)( tmp_long ) ); } else if( ( tmp_long == 70 ) || ( tmp_long == 38 ) ) { /* take care of case 16 */ tmp_long = EXTRACT_BT( opcode ); PRINT( "0x%02lx", tmp_long ); } else if( ( tmp_long == 134 ) ) { /* take care of case 17 */ tmp_long = EXTRACT_BF( opcode ); PRINT( "0x%02lx, ", tmp_long ); tmp_long = EXTRACT_U( opcode ); PRINT( "0x%02lx", tmp_long ); } } } else if( ops_and_mnemonics[index].form == XL || ops_and_mnemonics[index].form == smXL ) { /* We've got a "XL" form instruction or a simplified mnemonic for XL instruction. Pull the appropriate fields and print the opcode. */ /* Yet again, we will have to do some checking on the opcodes to get this right. It turns out that all of the XL form instructions have a primary opcode of 19, so I don't have to even check that. All I need to do is look at the secondary opcode. */ tmp_long = EXTRACT_SECONDARY_XL( opcode ); if( ( tmp_long == 528 ) || ( tmp_long == 16 ) ) { /* Take care of the case where we have only 2 fields to read in, BO and BI. */ tmp_long = EXTRACT_BO( opcode ); PRINT( "0x%02lx, ", tmp_long ); tmp_long = EXTRACT_BI( opcode ); PRINT( "0x%02lx", tmp_long ); } else if( ( tmp_long == 150 ) || ( tmp_long == 50 ) ) { /* Take care of the case where there are no fields (all three are zeroed-out. An example would be the isync instruction. */ PRINT( "" ); } else if( ( tmp_long == 0 ) ) { /* Take care of cases where we have two bit fields from the CR as arguments. An example might be the mcrf instr. */ tmp_long = EXTRACT_BF( opcode ); PRINT( "0x%01lx, ", tmp_long ); tmp_long = EXTRACT_BFA( opcode ); PRINT( "0x%01lx", tmp_long ); } else { /* If we get here, then we are in the general case where we need to get 3 bit-fields. Or, if have smX, we only need one or 2 of those fields because they duplicate!! */ tmp_long = EXTRACT_BT( opcode ); PRINT( "0x%02lx", tmp_long ); if((EXTRACT_SECONDARY_XL(opcode)==449 || EXTRACT_SECONDARY_XL(opcode)==33) && ops_and_mnemonics[index].form == smXL ) { tmp_long = EXTRACT_BA( opcode ); PRINT( ", 0x%02lx", tmp_long ); } else if(ops_and_mnemonics[index].form!=smXL) { tmp_long = EXTRACT_BA( opcode ); PRINT( ", 0x%02lx, ", tmp_long ); tmp_long = EXTRACT_BB( opcode ); PRINT( "0x%02lx", tmp_long ); } } } else if( ops_and_mnemonics[index].form == XFX || ops_and_mnemonics[index].form == smXFX ) { /* We've got a "XFX" form instruction. Pull the appropriate fields and print the opcode. */ /* We'll have to do some massaging to see exactly what to do. */ tmp_long = EXTRACT_SECONDARY_XFX( opcode ); if( ( tmp_long == 339 ) || ( tmp_long == 371 ) ) { /* We have a mfspr instr, which has operands in the form of: RT,SPR */ tmp_long = EXTRACT_RT( opcode ); PRINT( "r%02d", (int)( tmp_long ) ); /* if NOT a sim. mnemonic print out the SPR...else skip it! MATT */ if (ops_and_mnemonics[index].form != smXFX || strncmp(&ops_and_mnemonics[index].mnemonic[0], "mfsprg",6)==0 || strncmp(&ops_and_mnemonics[index].mnemonic[0], "mfibatu",7)==0 || strncmp(&ops_and_mnemonics[index].mnemonic[0], "mfibatl",7)==0 || strncmp(&ops_and_mnemonics[index].mnemonic[0], "mfdbatu",7)==0 || strncmp(&ops_and_mnemonics[index].mnemonic[0], "mfdbatl",7)==0 ) { PRINT( ", " ); tmp_long = EXTRACT_SPR( opcode ); /* There's some wierd ones in the sim. mnemonics...mfsprg,mfibatu,mfibatl mfdbatu,mfdbatl...need the # of the prg register printed out. */ if (strncmp(& ops_and_mnemonics[index].mnemonic[0], "mfsprg",6)==0 ) { tmp_long = tmp_long - 272; } if (strncmp(& ops_and_mnemonics[index].mnemonic[0], "mfibatu",7)==0 ) { tmp_long = (tmp_long - 528)/2; } if (strncmp(& ops_and_mnemonics[index].mnemonic[0], "mfibatl",7)==0 ) { tmp_long = (tmp_long - 529)/2; } if (strncmp(& ops_and_mnemonics[index].mnemonic[0], "mfdbatu",7)==0 ) { tmp_long = (tmp_long - 536)/2; } if (strncmp(& ops_and_mnemonics[index].mnemonic[0], "mfdbatl",7)==0 ) { tmp_long = (tmp_long - 537)/2; } PRINT("%d",tmp_long); } } else if( tmp_long == 144 ) { /* We have an mtcrf instr which has arguments in the form of: FMX,RS */ tmp_long = EXTRACT_FXM( opcode ); PRINT( "0x%02lx, ", tmp_long ); tmp_long = EXTRACT_RS( opcode ); PRINT( "r%02d", (int)( tmp_long ) ); } else { /* Finally, we are at the last case, an mtspr instr, which as arguments in the form of: SPR,RS */ if (ops_and_mnemonics[index].form != smXFX || strncmp(& ops_and_mnemonics[index].mnemonic[0], "mtsprg",6)==0 || strncmp(& ops_and_mnemonics[index].mnemonic[0], "mtibatu",7)==0 || strncmp(& ops_and_mnemonics[index].mnemonic[0], "mtibatl",7)==0 || strncmp(& ops_and_mnemonics[index].mnemonic[0], "mtdbatu",7)==0 || strncmp(& ops_and_mnemonics[index].mnemonic[0], "mtdbatl",7)==0 ) { tmp_long = EXTRACT_SPR( opcode ); if (strncmp(& ops_and_mnemonics[index].mnemonic[0], "mtsprg",6)==0 ) { tmp_long = tmp_long - 272; PRINT("%d",tmp_long); } else if (strncmp(& ops_and_mnemonics[index].mnemonic[0], "mtibatu",7)==0 ) { tmp_long = (tmp_long - 528)/2; PRINT("%d",tmp_long); } else if (strncmp(& ops_and_mnemonics[index].mnemonic[0], "mtibatl",7)==0 ) { tmp_long = (tmp_long - 529)/2; PRINT("%d",tmp_long); } else if (strncmp(& ops_and_mnemonics[index].mnemonic[0], "mtdbatu",7)==0 ) { tmp_long = (tmp_long - 536)/2; PRINT("%d",tmp_long); } else if (strncmp(& ops_and_mnemonics[index].mnemonic[0], "mtdbatl",7)==0 ) { tmp_long = (tmp_long - 537)/2; PRINT("%d",tmp_long); } else GOPRINT_SPR(tmp_long); PRINT( ", " ); } tmp_long = EXTRACT_RS( opcode ); PRINT( "r%02d", (int)( tmp_long ) ); } } else if( ops_and_mnemonics[index].form == XFL ) { /* We've got a "XFL" form instruction. Pull the appropriate fields and print the opcode. */ tmp_long = EXTRACT_FLM( opcode ); PRINT( "0x%02lx, ", tmp_long ); tmp_long = EXTRACT_FRB( opcode ); PRINT( "f%02d", (int)( tmp_long ) ); } else if( ops_and_mnemonics[index].form == XS ) { /* We've got a "XS" form instruction. Pull the appropriate fields and print the opcode. */ tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RS( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_SH64( opcode ); PRINT( "0x%02lx", tmp_long ); } else if( ops_and_mnemonics[index].form == XO || ops_and_mnemonics[index].form == smXO ) { /* We've got a "XO" or "smXO" form instruction. Pull the appropriate fields and print the opcode. */ /* Yet again, we must do some comparisons to tell what to do. */ tmp_long = EXTRACT_SECONDARY_XO( opcode ); if( ( tmp_long == 234 ) || ( tmp_long == 232 ) || ( tmp_long == 202 ) || ( tmp_long == 200 ) || ( tmp_long == 104 ) || ( tmp_long == 360 ) || ( tmp_long == 488 ) ) { /* We have some instructions that have only 2 arguments. */ tmp_long = EXTRACT_RT( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d", (int)( tmp_long ) ); } else { /* We have some instructions that have 3 arguments. */ tmp_long = EXTRACT_RT( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); /* simplified mnemonic!! sub,subc MATT */ if(ops_and_mnemonics[index].form == XO) { tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RB( opcode ); PRINT( "r%02d", (int)( tmp_long ) ); } if(ops_and_mnemonics[index].form == smXO) { tmp_long = EXTRACT_RB( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d", (int)( tmp_long ) ); } } } else if( ops_and_mnemonics[index].form == A ) { /* We've got a "A" form instruction. Pull the appropriate fields and print the opcode. */ tmp_long = EXTRACT_FRT( opcode ); PRINT( "f%02d", (int)( tmp_long ) ); tmp_long = EXTRACT_SECONDARY_A( opcode ); if( ( tmp_long == 18 ) || ( tmp_long == 20 ) || ( tmp_long == 21 ) || ( tmp_long == 23 ) || ( tmp_long == 25 ) || ( tmp_long == 28 ) || ( tmp_long == 29 ) || ( tmp_long == 30 ) || ( tmp_long == 31 ) ) { /* Get FRA for these instructions */ tmp_long = EXTRACT_FRA( opcode ); PRINT( ", f%02d", (int)( tmp_long ) ); } else if( ( tmp_long == 28 ) || ( tmp_long == 29 ) || ( tmp_long == 30 ) || ( tmp_long == 31 ) ) { /* Get FRC first, then we will worry about getting FRB. These few instructions have the operands reversed. I HATE THIS OPCODE-MNEMONIC MAPPING!!! */ tmp_long = EXTRACT_FRC( opcode ); PRINT( ", f%02d", (int)( tmp_long ) ); } tmp_long = EXTRACT_SECONDARY_A( opcode ); if( ( tmp_long == 18 ) || ( tmp_long == 20 ) || ( tmp_long == 21 ) || ( tmp_long == 22 ) || ( tmp_long == 23 ) || ( tmp_long == 24 ) || ( tmp_long == 26 ) ) { /* Get FRB for these instructions */ tmp_long = EXTRACT_FRB( opcode ); PRINT( ", f%02d", (int)( tmp_long ) ); } else if( ( tmp_long == 28 ) || ( tmp_long == 29 ) || ( tmp_long == 30 ) || ( tmp_long == 31 ) ) { /* Get FRC first, then we will worry about getting FRB. These few instructions have the operands reversed. I HATE THIS OPCODE-MNEMONIC MAPPING!!! */ tmp_long = EXTRACT_FRC( opcode ); PRINT( ", f%02d", (int)( tmp_long ) ); } tmp_long = EXTRACT_SECONDARY_A( opcode ); if( ( tmp_long == 23 ) || ( tmp_long == 25 ) ) { /* Get FRC for these instructions */ tmp_long = EXTRACT_FRC( opcode ); PRINT( ", f%02d", (int)( tmp_long ) ); } else if( ( tmp_long == 28 ) || ( tmp_long == 29 ) || ( tmp_long == 30 ) || ( tmp_long == 31 ) ) { /* Get FRB as the last operand, eventhough this is located in the opcode as the 4th operand. Yet another kludge in the opcode mapping... */ tmp_long = EXTRACT_FRB( opcode ); PRINT( ", f%02d", (int)( tmp_long ) ); } } else if( ops_and_mnemonics[index].form == M ) { /* We've got a "M" form instruction. Pull the appropriate fields and print the opcode. */ tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RS( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_PRIMARY( opcode ); if( tmp_long == 23 ) { tmp_long = EXTRACT_RB( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); } else { tmp_long = EXTRACT_SH32( opcode ); PRINT( "0x%02lx, ", tmp_long ); } tmp_long = EXTRACT_MBE( opcode ); PRINT("0x%02lx, ", ( ( tmp_long & 0xFFFFFFE0 ) >> 5 )); PRINT( "0x%02lx", ( tmp_long & 0x1F ) ); } else if( ops_and_mnemonics[index].form == smM ) { /* We've got a smM form instruction. I only needed to do rotlwi,slwi,srwi, clrlwi,clrrwi,clrlslwi because they can be used to represent the rest!! */ /* All mnemonics have the RA and RS!! */ tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RS( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); /* Take care of smM rotlw,inslwi and insrwi... */ if(EXTRACT_PRIMARY(opcode) == 23) { tmp_long = EXTRACT_RB(opcode); PRINT( "r%02d",(int)(tmp_long)); } else if(EXTRACT_PRIMARY(opcode) == 20) { tmp_long = EXTRACT_MB_smM(opcode); tmp_long = 1-tmp_long+EXTRACT_ME_smM(opcode); PRINT( "%02d, ",(int)(tmp_long)); tmp_long = EXTRACT_MB_smM(opcode); PRINT( "%02d",(int)(tmp_long)); } if(strncmp(&ops_and_mnemonics[index].mnemonic[0], "clrlslwi",8)==0 ) { tmp_long = EXTRACT_MB_smM(opcode); PRINT("%02d, ",(EXTRACT_SH32(opcode)+tmp_long)); } if(strncmp(&ops_and_mnemonics[index].mnemonic[0], "rotlwi",6)==0 || strncmp(&ops_and_mnemonics[index].mnemonic[0], "slwi",4)==0 || strncmp(&ops_and_mnemonics[index].mnemonic[0], "clrlslwi",8)==0 ) { tmp_long = EXTRACT_SH32( opcode ); PRINT( "%02d", (int)( tmp_long ) ); } else if(strncmp(&ops_and_mnemonics[index].mnemonic[0], "srwi",4)==0 ) { tmp_long = EXTRACT_SH32( opcode ); PRINT( "%02d",(int)( 32 - tmp_long )); } else if(strncmp(&ops_and_mnemonics[index].mnemonic[0], "clrlwi",6)==0 ) { tmp_long = EXTRACT_MB_smM(opcode); PRINT( "%02d",(int)(tmp_long)); } else if(strncmp(&ops_and_mnemonics[index].mnemonic[0], "clrrwi",6)==0 ) { tmp_long = EXTRACT_ME_smM(opcode); PRINT( "%02d",(int)(31 - tmp_long )); } } else if( ops_and_mnemonics[index].form == MD ) { /* We've got a "MD" form instruction. Pull the appropriate fields and print the opcode. */ tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RS( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_SH64( opcode ); PRINT( "0x%02lx, ", tmp_long ); tmp_long = EXTRACT_MB( opcode ); PRINT( "0x%02lx", tmp_long ); } else if( ops_and_mnemonics[index].form == MDS ) { /* We've got a "MDS" form instruction. Pull the appropriate fields and print the opcode. */ tmp_long = EXTRACT_RA( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RS( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_RB( opcode ); PRINT( "r%02d, ", (int)( tmp_long ) ); tmp_long = EXTRACT_MB( opcode ); PRINT( "0x%02lx", tmp_long ); } return( SUCCESS ); } } /* --------------------------------------------------------------------- */ /* function: do_simplified_branch purpose: This function will handle all simplified branch disassemble steps and is called by the main disassemble function disassemble_opcode. inputs: opcode: This is the 32-bit opcode that we will disassemble. index: This is used if a 0x4200000 or 0x4240000 opcode is given...in which case, no more searching needs to be done. outputs: STATUS=SUCCESS return: None. mod history: 8/31/95 MM */ STATUS do_simplified_branch( opcode,index,current_add ) /* "opcode" is the 32-bit piece of data that I want to disassemble. It may be an unidentifiable opcode, in which case, I'll simply return a string with the original opcode in it. */ unsigned long opcode; /* This variable acts as a general-purpose index pointer... */ int index; unsigned long current_add; { /* This variable is used for when I need to pull out a field of the opcode. The macros that "pull out" a field are in the ".h" file. */ long tmp_long; /* THis will hold the match from the branch label table! */ char new_label[20]; /* The variable "status" will be used when I call other functions and they return status. I've typed it as "STATUS" because someone else will define that type. It will most likely be a long, but who really knows... */ STATUS status; /* First thing is to get bits 0:15....and then test to see if they are any of the special cases that don't need any work done...no operands! */ if(EXTRACT_SPECIAL(opcode) == EXTRACT_SPECIAL(0x42400000) || EXTRACT_SPECIAL(opcode) == EXTRACT_SPECIAL(0x42000000) || EXTRACT_SPECIAL(opcode) == EXTRACT_SPECIAL(0x4D800000) || EXTRACT_SPECIAL(opcode) == EXTRACT_SPECIAL(0x4C800000) || EXTRACT_SPECIAL(opcode) == EXTRACT_SPECIAL(0x4E000000) || EXTRACT_SPECIAL(opcode) == EXTRACT_SPECIAL(0x4E400000) ) { } else { tmp_long = EXTRACT_BI( opcode ); tmp_long = tmp_long - (( tmp_long/4 ) * 4 ); /* Now, tmp_long is 0-4 where 0-3 are offsets into the CR? and 4 is NO OFFSET...now search the list of mnemonics and get a better match! */ status = special_search_ops_and_mnemonics( opcode, &index, tmp_long ); if( status != SUCCESS ) { /* If I get here, then there was no match for the opcode. This SHOULD NOT HAPPEN because we got a good value once!! */ PRINT( "DINK ERROR!! MATT'S FAULT!\n"); return( SUCCESS ); } } /* At this point, I have A simplified branch mnemonic that is legit!! There may be more than one possiblity but I do have one that is correct! So print the stuff to the screen! */ /* Start by putting the mnemonic symbol to the screen! */ PRINT( "%-12s", ops_and_mnemonics[index].mnemonic ); /* If the mnemonic was NOT blr,bctr,blrl, bctrl then there's more work to do!! Else, done!! */ if ( ops_and_mnemonics[index].form != (smBCLR-1) && ops_and_mnemonics[index].form != (smBCCTR-1) && ops_and_mnemonics[index].form != (smBCLRL-1) && ops_and_mnemonics[index].form != (smBCCTRL-1) ) { if( (ops_and_mnemonics[index].form >= smBC && ops_and_mnemonics[index].form <= (smBCA+4)) || (ops_and_mnemonics[index].form >= smBCL && ops_and_mnemonics[index].form <= (smBCLA+4) ) ) { /* I have more work to do...like getting the BI from all instructions and then getting the offset for other instructions! */ /* Get the BI field and convert to a CR offset!! */ tmp_long = EXTRACT_BI( opcode ); if(strncmp(&ops_and_mnemonics[index].mnemonic[0], "bt",2)==0 || strncmp(&ops_and_mnemonics[index].mnemonic[0], "bf",2)==0 ) { PRINT( "%02d", (int)( tmp_long ) ); } else if(EXTRACT_SPECIAL(opcode) == EXTRACT_SPECIAL(0x42400000) || EXTRACT_SPECIAL(opcode) == EXTRACT_SPECIAL(0x42000000) ) { /* MATT HERE! */ tmp_long = EXTRACT_BD( opcode ); tmp_long = test_branch_label( opcode, current_add, tmp_long, &new_label[0] ); if (tmp_long == 0) PRINT( "%s",new_label); else PRINT( "0x%02lx",tmp_long); } else { tmp_long = tmp_long/4; PRINT( "CR%02d, ", (int)( tmp_long ) ); /* MATT HERE! */ tmp_long = EXTRACT_BD( opcode ); tmp_long = test_branch_label( opcode, current_add, tmp_long, &new_label[0] ); if (tmp_long == 0) PRINT( "%s",new_label); else PRINT( "0x%02lx",tmp_long); } } else { if(strncmp(& ops_and_mnemonics[index].mnemonic[0], "bdnzlr",6)==0 || strncmp(&ops_and_mnemonics[index].mnemonic[0], "bdzlr",5)==0 ) { } else { tmp_long = EXTRACT_BI( opcode ); tmp_long = tmp_long/4; PRINT( "CR%02d", (int)tmp_long ); } } } return( SUCCESS ); } /* --------------------------------------------------------------------- */ /* function: test_branch_label purpose: This function will see if we have a branch label that matches the address of the current instruction inputs: opcode: 32 bit opcode of current instruction current_add: the address of current execution tmp_long: current address taken from opcode label: the lable if we found one to match outputs: None. return: None. mod history: 03/14/96 MM */ int test_branch_label(opcode, current_add, tmp_long, label) unsigned long opcode; unsigned long current_add; unsigned long tmp_long; char* label; { int count = 0; /* PRINT("\n IN opcode = %x\n",opcode); PRINT("\n IN current_add = %x\n",current_add); PRINT("\n IN tmp_long = %x\n",tmp_long); */ if(EXTRACT_PRIMARY( opcode ) == 18 || EXTRACT_PRIMARY( opcode ) == 16) { if(EXTRACT_PRIMARY( opcode ) == 16) { if ((tmp_long & 0x00008000) == 0x00008000) { tmp_long = tmp_long | 0xFFFF0000; } else { tmp_long = tmp_long | 0x00000000; } } else if(EXTRACT_PRIMARY( opcode ) == 18) { /* PRINT("\n ANDING result = %x\n",(tmp_long & 0x02000000)); */ if ((tmp_long & 0x02000000) == 0x02000000) { tmp_long = tmp_long | 0xFD000000; } else { /* PRINT("\n HERE DORK!\n"); */ tmp_long = tmp_long | 0x00000000; } } /* PRINT("\n NEW TMPLONG=%x\n",tmp_long); */ if(EXTRACT_LK_AA( opcode ) == 0 || EXTRACT_LK_AA( opcode ) == 1) { tmp_long = current_add + tmp_long; } else { tmp_long = tmp_long; } for(count=0;count