disasssembler/debugger/...
Patch by Bill Pitts: 08 May 2001
* Added TQM8260 Configuration
* Patch for ERIC configuration and embedded flash environment
by Swen Anderson: 30 May 2001
* Fixed some DHCP problems
Modifications for 1.0.0:
======================================================================
+* Added bedbug (http://www.mindspring.com/~wlp/bedbug.html) embedded
+ disasssembler/debugger/...
+ Patch by Bill Pitts: 08 May 2001
+
+* Added TQM8260 Configuration
+
* Patch for ERIC configuration and embedded flash environment
by Swen Anderson: 30 May 2001
E: frank.morauf@salzbrenner.com
D: Support for Embedded Planet RPX Super Board
+N: Bill Pitts
+D: wlp@mindspring.com
+D: BedBug embedded debugger code
+
N: Stefan Roese
E: stefan.roese@esd-electronics.com
D: IBM PPC401/403/405GP Support; Windows environment support
#########################################################################
LIST="$LIST \
+ TQM8260 \
hymod \
cogent_mpc8260 \
rsdproto \
echo "CPU = mpc8260" >>config.mk ; \
echo "#include <config_$(@:_config=).h>" >config.h
+TQM8260_config: unconfig
+ @echo "Configuring for $(@:_config=) Board..." ; \
+ cd include ; \
+ echo "ARCH = ppc" > config.mk ; \
+ echo "BOARD = tqm8260" >>config.mk ; \
+ echo "CPU = mpc8260" >>config.mk ; \
+ echo "#include <config_$(@:_config=).h>" >config.h
+
#########################################################################
clean:
flash_get_offsets (FLASH_BASE0_PRELIM, &flash_info[0]);
/* Monitor protection ON by default */
+#if 0 /* sand: */
(void)flash_protect(FLAG_PROTECT_SET,
FLASH_BASE0_PRELIM-CFG_MONITOR_LEN+size_b0,
FLASH_BASE0_PRELIM-1+size_b0,
&flash_info[0]);
+#else
+ (void)flash_protect(FLAG_PROTECT_SET,
+ CFG_MONITOR_BASE,
+ CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+ &flash_info[0]);
+#endif
size_b1 = 0 ;
flash_info[0].size = size_b0;
}
flash_get_offsets (base_b0, &flash_info[0]);
/* monitor protection ON by default */
- (void)flash_protect(FLAG_PROTECT_SET,
- base_b0+size_b0-CFG_MONITOR_LEN+size_b1,
- base_b0+size_b0-1+size_b1,
+#if 0 /* sand: */
+ (void)flash_protect(FLAG_PROTECT_SET,
+ FLASH_BASE0_PRELIM-CFG_MONITOR_LEN+size_b0,
+ FLASH_BASE0_PRELIM-1+size_b0,
&flash_info[0]);
-
+#else
+ (void)flash_protect(FLAG_PROTECT_SET,
+ CFG_MONITOR_BASE,
+ CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+ &flash_info[0]);
+#endif
+
if (size_b1) {
/* Re-do sizing to get full correct info */
size_b1 = flash_get_size((volatile FLASH_WORD_SIZE *)base_b1, &flash_info[1]);
--- /dev/null
+#
+# (C) Copyright 2001
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = lib$(BOARD).a
+
+OBJS = $(BOARD).o flash.o
+
+$(LIB): .depend $(OBJS)
+ $(AR) crv $@ $^
+
+#########################################################################
+
+.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c)
+ $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@
+
+sinclude .depend
+
+#########################################################################
--- /dev/null
+#
+# (C) Copyright 2001
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+#
+
+#
+# TQM8260 boards
+#
+
+# This should be equal to the CFG_FLASH_BASE define in config_TQM8260.h
+# for the "final" configuration, with ppcboot in flash, or the address
+# in RAM where ppcboot is loaded at for debugging.
+#
+TEXT_BASE = 0x40000000
+
+PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -I$(TOPDIR)
--- /dev/null
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Flash Routines for AM29LV640U devices
+ *
+ *--------------------------------------------------------------------
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppcboot.h>
+#include <mpc8xx.h>
+
+#define V_ULONG(a) (*(volatile unsigned long *)( a ))
+#define V_BYTE(a) (*(volatile unsigned char *)( a ))
+
+
+flash_info_t flash_info[CFG_MAX_FLASH_BANKS];
+
+
+/*-----------------------------------------------------------------------
+ */
+void flash_reset(void)
+{
+ if( flash_info[0].flash_id != FLASH_UNKNOWN )
+ {
+ V_ULONG( flash_info[0].start[0] ) = 0x00F000F0;
+ V_ULONG( flash_info[0].start[0] + 4 ) = 0x00F000F0;
+ }
+}
+
+/*-----------------------------------------------------------------------
+ */
+ulong flash_get_size( ulong baseaddr, flash_info_t *info )
+{
+ short i;
+ unsigned long flashtest_h, flashtest_l;
+
+ /* Write auto select command sequence and test FLASH answer */
+ V_ULONG( baseaddr + ((ulong)0x0555 << 3)) = 0x00AA00AA;
+ V_ULONG( baseaddr + ((ulong)0x02AA << 3)) = 0x00550055;
+ V_ULONG( baseaddr + ((ulong)0x0555 << 3)) = 0x00900090;
+ V_ULONG( baseaddr + 4 + ((ulong)0x0555 << 3)) = 0x00AA00AA;
+ V_ULONG( baseaddr + 4 + ((ulong)0x02AA << 3)) = 0x00550055;
+ V_ULONG( baseaddr + 4 + ((ulong)0x0555 << 3)) = 0x00900090;
+
+ flashtest_h = V_ULONG( baseaddr ); /* manufacturer ID */
+ flashtest_l = V_ULONG( baseaddr + 4 );
+ if (flashtest_h != AMD_MANUFACT)
+ {
+ info->flash_id = FLASH_UNKNOWN;
+ info->sector_count = 0;
+ info->size = 0;
+ return( 0 ); /* no or unknown flash */
+ }
+
+ info->flash_id = AMD_MANUFACT << 16; /* set manufacturer offset */
+
+ flashtest_h = V_ULONG( baseaddr + 8 ); /* device ID */
+ flashtest_l = V_ULONG( baseaddr + 12 );
+ if( flashtest_h != flashtest_l )
+ info->flash_id = FLASH_UNKNOWN;
+ else
+ switch( flashtest_h )
+ {
+ case AMD_ID_LV640U:
+ info->flash_id += FLASH_AM640U;
+ info->sector_count = 128;
+ info->size = 0x02000000; break; /* 4 * 8 MB = 32 MB */
+ default:
+ info->flash_id = FLASH_UNKNOWN;
+ return( 0 ); /* no or unknown flash */
+ }
+
+ /* set up sector start adress table (uniform sector type!) */
+ for( i = 0; i < info->sector_count; i++ )
+ info->start[i] = baseaddr + (i * 0x00040000);
+
+ /* check for protected sectors */
+ for( i = 0; i < info->sector_count; i++ )
+ {
+ /* read sector protection at sector address, (A7 .. A0) = 0x02 */
+ if( (V_ULONG( info->start[i] + 16 ) & 0x00010001) ||
+ (V_ULONG( info->start[i] + 20 ) & 0x00010001) )
+ info->protect[i] = 1; /* D0 = 1 if protected */
+ else info->protect[i] = 0;
+ }
+
+ flash_reset();
+ return( info->size );
+}
+
+/*-----------------------------------------------------------------------
+ */
+unsigned long flash_init (void)
+{
+ unsigned long size_b0 = 0;
+ int i;
+
+ /* Init: no FLASHes known */
+ for (i=0; i<CFG_MAX_FLASH_BANKS; ++i)
+ {
+ flash_info[i].flash_id = FLASH_UNKNOWN;
+ }
+
+ /* Static FLASH Bank configuration here (only one bank) */
+
+ size_b0 = flash_get_size(CFG_FLASH0_BASE, &flash_info[0]);
+ if (flash_info[0].flash_id == FLASH_UNKNOWN)
+ {
+ printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n",
+ size_b0, size_b0>>20);
+ }
+ if (flash_info[0].size != (CFG_FLASH0_SIZE<<20))
+ {
+ printf ("## FLASH size on Bank 0 does not match CFG_FLASH0_SIZE: "
+ "0x%lx != 0x%x\n", flash_info[0].size,
+ CFG_FLASH0_SIZE<<20);
+ }
+
+ /*
+ * protect monitor and environment sectors
+ */
+
+#if CFG_MONITOR_BASE >= CFG_FLASH0_BASE
+ flash_protect(FLAG_PROTECT_SET,
+ CFG_MONITOR_BASE,
+ CFG_MONITOR_BASE+CFG_MONITOR_LEN-1,
+ &flash_info[0]);
+#endif
+
+#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR)
+# ifndef CFG_ENV_SIZE
+# define CFG_ENV_SIZE CFG_ENV_SECT_SIZE
+# endif
+ flash_protect(FLAG_PROTECT_SET,
+ CFG_ENV_ADDR,
+ CFG_ENV_ADDR + CFG_ENV_SIZE - 1,
+ &flash_info[0]);
+#endif
+
+ return (size_b0);
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_print_info (flash_info_t *info)
+{
+ int i;
+
+ if (info->flash_id == FLASH_UNKNOWN)
+ {
+ printf ("missing or unknown FLASH type\n");
+ return;
+ }
+
+ switch ((info->flash_id >> 16) & 0xff)
+ {
+ case 0x1:
+ printf ("AMD ");
+ break;
+ default:
+ printf ("Unknown Vendor ");
+ break;
+ }
+
+ switch (info->flash_id & FLASH_TYPEMASK)
+ {
+ case FLASH_AM640U:
+ printf ("29LV640D (64 M, uniform sector)\n");
+ break;
+ default:
+ printf ("Unknown Chip Type\n");
+ break;
+ }
+
+ printf (" Size: %ld MB in %d Sectors\n",
+ info->size >> 20, info->sector_count);
+
+ printf (" Sector Start Addresses:");
+ for (i=0; i<info->sector_count; ++i)
+ {
+ if ((i % 5) == 0)
+ printf ("\n ");
+ printf (" %08lX%s",
+ info->start[i],
+ info->protect[i] ? " (RO)" : " "
+ );
+ }
+ printf ("\n");
+}
+
+/*-----------------------------------------------------------------------
+ */
+void flash_erase (flash_info_t *info, int s_first, int s_last)
+{
+ int flag, prot, sect, l_sect;
+ ulong start, now, last;
+
+ if ((s_first < 0) || (s_first > s_last))
+ {
+ if (info->flash_id == FLASH_UNKNOWN)
+ {
+ printf ("- missing\n");
+ } else {
+ printf ("- no sectors to erase\n");
+ }
+ return;
+ }
+
+ prot = 0;
+ for (sect = s_first; sect <= s_last; sect++)
+ {
+ if (info->protect[sect])
+ prot++;
+ }
+
+ if (prot)
+ {
+ printf ("- Warning: %d protected sectors will not be erased!\n",
+ prot);
+ } else
+ {
+ printf ("\n");
+ }
+
+ l_sect = -1;
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00AA00AA;
+ V_ULONG( info->start[0] + (0x02AA << 3) ) = 0x00550055;
+ V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00800080;
+ V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00AA00AA;
+ V_ULONG( info->start[0] + (0x02AA << 3) ) = 0x00550055;
+ V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00AA00AA;
+ V_ULONG( info->start[0] + 4 + (0x02AA << 3) ) = 0x00550055;
+ V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00800080;
+ V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00AA00AA;
+ V_ULONG( info->start[0] + 4 + (0x02AA << 3) ) = 0x00550055;
+ udelay (1000);
+
+ /* Start erase on unprotected sectors */
+ for (sect = s_first; sect<=s_last; sect++)
+ {
+ if (info->protect[sect] == 0)
+ { /* not protected */
+ V_ULONG( info->start[sect] ) = 0x00300030;
+ V_ULONG( info->start[sect] + 4 ) = 0x00300030;
+ l_sect = sect;
+ }
+ }
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ /* wait at least 80us - let's wait 1 ms */
+ udelay (1000);
+
+ /*
+ * We wait for the last triggered sector
+ */
+ if (l_sect < 0)
+ goto DONE;
+
+ start = get_timer (0);
+ last = start;
+ while ((V_ULONG( info->start[l_sect] ) & 0x00800080) != 0x00800080 ||
+ (V_ULONG( info->start[l_sect] + 4 ) & 0x00800080) != 0x00800080)
+ {
+ if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT)
+ {
+ printf ("Timeout\n");
+ return;
+ }
+ /* show that we're waiting */
+ if ((now - last) > 1000)
+ { /* every second */
+ serial_putc ('.');
+ last = now;
+ }
+ }
+
+ DONE:
+ /* reset to read mode */
+ flash_reset ();
+
+ printf (" done\n");
+}
+
+static int write_dword (flash_info_t *, ulong, unsigned char *);
+
+/*-----------------------------------------------------------------------
+ * Copy memory to flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+
+int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt)
+{
+ ulong dp;
+ static unsigned char bb[8];
+ int i, l, rc, cc = cnt;
+
+ dp = (addr & ~7); /* get lower dword aligned address */
+
+ /*
+ * handle unaligned start bytes
+ */
+ if ((l = addr - dp) != 0)
+ {
+ for (i = 0; i < 8; i++)
+ bb[i] = (i < l || (i-l) >= cc) ? V_BYTE(dp+i) : *src++;
+ if ((rc = write_dword(info, dp, bb)) != 0)
+ {
+ return (rc);
+ }
+ dp += 8;
+ cc -= 8 - l;
+ }
+
+ /*
+ * handle word aligned part
+ */
+ while (cc >= 8)
+ {
+ if ((rc = write_dword(info, dp, src)) != 0)
+ {
+ return (rc);
+ }
+ dp += 8;
+ src += 8;
+ cc -= 8;
+ }
+
+ if (cc <= 0)
+ {
+ return (0);
+ }
+
+ /*
+ * handle unaligned tail bytes
+ */
+ for (i = 0; i < 8; i++)
+ {
+ bb[i] = (i < cc) ? *src++ : V_BYTE(dp+i);
+ }
+ return (write_dword(info, dp, bb));
+}
+
+/*-----------------------------------------------------------------------
+ * Write a dword to Flash, returns:
+ * 0 - OK
+ * 1 - write timeout
+ * 2 - Flash not erased
+ */
+static int write_dword (flash_info_t *info, ulong dest, unsigned char * pdata)
+{
+ ulong start, cl, ch;
+ int flag, i;
+
+ for (i = 0; i < 4; i++)
+ ch = (ch << 8) + *pdata++; /* high word */
+ for (i = 0; i < 4; i++)
+ cl = (cl << 8) + *pdata++; /* low word */
+
+ /* Check if Flash is (sufficiently) erased */
+ if ((*((vu_long *)dest) & ch) != ch
+ ||(*((vu_long *)(dest + 4)) & cl) != cl)
+ {
+ return (2);
+ }
+
+ /* Disable interrupts which might cause a timeout here */
+ flag = disable_interrupts();
+
+ V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00AA00AA;
+ V_ULONG( info->start[0] + (0x02AA << 3) ) = 0x00550055;
+ V_ULONG( info->start[0] + (0x0555 << 3) ) = 0x00A000A0;
+ V_ULONG( dest ) = ch;
+ V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00AA00AA;
+ V_ULONG( info->start[0] + 4 + (0x02AA << 3) ) = 0x00550055;
+ V_ULONG( info->start[0] + 4 + (0x0555 << 3) ) = 0x00A000A0;
+ V_ULONG( dest + 4 ) = cl;
+
+ /* re-enable interrupts if necessary */
+ if (flag)
+ enable_interrupts();
+
+ /* data polling for D7 */
+ start = get_timer (0);
+ while( ((V_ULONG( dest ) & 0x00800080) != (ch & 0x00800080)) ||
+ ((V_ULONG( dest + 4 ) & 0x00800080) != (cl & 0x00800080)) )
+ {
+ if (get_timer(start) > CFG_FLASH_WRITE_TOUT)
+ {
+ return (1);
+ }
+ }
+ return (0);
+}
+
--- /dev/null
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+OUTPUT_ARCH(powerpc)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib);
+/* Do we need any of these for elf?
+ __DYNAMIC = 0; */
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .rel.text : { *(.rel.text) }
+ .rela.text : { *(.rela.text) }
+ .rel.data : { *(.rel.data) }
+ .rela.data : { *(.rela.data) }
+ .rel.rodata : { *(.rel.rodata) }
+ .rela.rodata : { *(.rela.rodata) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ cpu/mpc8260/start.o (.text)
+ *(.text)
+ common/environment.o(.text)
+ *(.fixup)
+ *(.got1)
+ . = ALIGN(16);
+ *(.rodata)
+ *(.rodata1)
+ }
+ .fini : { *(.fini) } =0
+ .ctors : { *(.ctors) }
+ .dtors : { *(.dtors) }
+
+ /* Read-write section, merged into data segment: */
+ . = (. + 0x0FFF) & 0xFFFFF000;
+ _erotext = .;
+ PROVIDE (erotext = .);
+ .reloc :
+ {
+ *(.got)
+ _GOT2_TABLE_ = .;
+ *(.got2)
+ _FIXUP_TABLE_ = .;
+ *(.fixup)
+ }
+ __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >> 2;
+ __fixup_entries = (. - _FIXUP_TABLE_) >> 2;
+
+ .data :
+ {
+ *(.data)
+ *(.data1)
+ *(.sdata)
+ *(.sdata2)
+ *(.dynamic)
+ CONSTRUCTORS
+ }
+ _edata = .;
+ PROVIDE (edata = .);
+
+ __start___ex_table = .;
+ __ex_table : { *(__ex_table) }
+ __stop___ex_table = .;
+
+ . = ALIGN(4096);
+ __init_begin = .;
+ .text.init : { *(.text.init) }
+ .data.init : { *(.data.init) }
+ . = ALIGN(4096);
+ __init_end = .;
+
+ __bss_start = .;
+ .bss :
+ {
+ *(.sbss) *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+}
+
--- /dev/null
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppcboot.h>
+#include <ioports.h>
+#include <mpc8260.h>
+
+/*
+ * I/O Port configuration table
+ *
+ * if conf is 1, then that port pin will be configured at boot time
+ * according to the five values podr/pdir/ppar/psor/pdat for that entry
+ */
+
+const iop_conf_t iop_conf_tab[4][32] = {
+
+ /* Port A configuration */
+ { /* conf ppar psor pdir podr pdat */
+ /* PA31 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 *ATMTXEN */
+ /* PA30 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTCA */
+ /* PA29 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTSOC */
+ /* PA28 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 *ATMRXEN */
+ /* PA27 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRSOC */
+ /* PA26 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRCA */
+ /* PA25 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[0] */
+ /* PA24 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[1] */
+ /* PA23 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[2] */
+ /* PA22 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[3] */
+ /* PA21 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[4] */
+ /* PA20 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[5] */
+ /* PA19 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[6] */
+ /* PA18 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMTXD[7] */
+ /* PA17 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[7] */
+ /* PA16 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[6] */
+ /* PA15 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[5] */
+ /* PA14 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[4] */
+ /* PA13 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[3] */
+ /* PA12 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[2] */
+ /* PA11 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[1] */
+ /* PA10 */ { 0, 0, 0, 1, 0, 0 }, /* FCC1 ATMRXD[0] */
+ /* PA9 */ { 1, 1, 0, 1, 0, 0 }, /* SMC2 TXD */
+ /* PA8 */ { 1, 1, 0, 0, 0, 0 }, /* SMC2 RXD */
+ /* PA7 */ { 0, 0, 0, 1, 0, 0 }, /* PA7 */
+ /* PA6 */ { 0, 0, 0, 1, 0, 0 }, /* PA6 */
+ /* PA5 */ { 0, 0, 0, 1, 0, 0 }, /* PA5 */
+ /* PA4 */ { 0, 0, 0, 1, 0, 0 }, /* PA4 */
+ /* PA3 */ { 0, 0, 0, 1, 0, 0 }, /* PA3 */
+ /* PA2 */ { 0, 0, 0, 1, 0, 0 }, /* PA2 */
+ /* PA1 */ { 0, 0, 0, 1, 0, 0 }, /* PA1 */
+ /* PA0 */ { 0, 0, 0, 1, 0, 0 } /* PA0 */
+ },
+
+ /* Port B configuration */
+ { /* conf ppar psor pdir podr pdat */
+ /* PB31 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TX_ER */
+ /* PB30 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_DV */
+ /* PB29 */ { 1, 1, 1, 1, 0, 0 }, /* FCC2 MII TX_EN */
+ /* PB28 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_ER */
+ /* PB27 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII COL */
+ /* PB26 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII CRS */
+ /* PB25 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[3] */
+ /* PB24 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[2] */
+ /* PB23 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[1] */
+ /* PB22 */ { 1, 1, 0, 1, 0, 0 }, /* FCC2 MII TxD[0] */
+ /* PB21 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[0] */
+ /* PB20 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[1] */
+ /* PB19 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[2] */
+ /* PB18 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RxD[3] */
+ /* PB17 */ { 0, 0, 0, 0, 0, 0 }, /* PB17 */
+ /* PB16 */ { 0, 0, 0, 0, 0, 0 }, /* PB16 */
+ /* PB15 */ { 0, 0, 0, 0, 0, 0 }, /* PB15 */
+ /* PB14 */ { 0, 0, 0, 0, 0, 0 }, /* PB14 */
+ /* PB13 */ { 0, 0, 0, 0, 0, 0 }, /* PB13 */
+ /* PB12 */ { 0, 0, 0, 0, 0, 0 }, /* PB12 */
+ /* PB11 */ { 0, 0, 0, 0, 0, 0 }, /* PB11 */
+ /* PB10 */ { 0, 0, 0, 0, 0, 0 }, /* PB10 */
+ /* PB9 */ { 0, 0, 0, 0, 0, 0 }, /* PB9 */
+ /* PB8 */ { 0, 0, 0, 0, 0, 0 }, /* PB8 */
+ /* PB7 */ { 0, 0, 0, 0, 0, 0 }, /* PB7 */
+ /* PB6 */ { 0, 0, 0, 0, 0, 0 }, /* PB6 */
+ /* PB5 */ { 0, 0, 0, 0, 0, 0 }, /* PB5 */
+ /* PB4 */ { 0, 0, 0, 0, 0, 0 }, /* PB4 */
+ /* PB3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */
+ /* PB2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */
+ /* PB1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */
+ /* PB0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */
+ },
+
+ /* Port C */
+ { /* conf ppar psor pdir podr pdat */
+ /* PC31 */ { 0, 0, 0, 1, 0, 0 }, /* PC31 */
+ /* PC30 */ { 0, 0, 0, 1, 0, 0 }, /* PC30 */
+ /* PC29 */ { 1, 1, 1, 0, 0, 0 }, /* SCC1 EN *CLSN */
+ /* PC28 */ { 0, 0, 0, 1, 0, 0 }, /* PC28 */
+ /* PC27 */ { 0, 0, 0, 1, 0, 0 }, /* PC27 */
+ /* PC26 */ { 0, 0, 0, 1, 0, 0 }, /* PC26 */
+ /* PC25 */ { 0, 0, 0, 1, 0, 0 }, /* PC25 */
+ /* PC24 */ { 0, 0, 0, 1, 0, 0 }, /* PC24 */
+ /* PC23 */ { 0, 1, 0, 1, 0, 0 }, /* ATMTFCLK */
+ /* PC22 */ { 0, 1, 0, 0, 0, 0 }, /* ATMRFCLK */
+ /* PC21 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN RXCLK */
+ /* PC20 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN TXCLK */
+ /* PC19 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII RX_CLK */
+ /* PC18 */ { 1, 1, 0, 0, 0, 0 }, /* FCC2 MII TX_CLK */
+ /* PC17 */ { 0, 0, 0, 1, 0, 0 }, /* PC17 */
+ /* PC16 */ { 0, 0, 0, 1, 0, 0 }, /* PC16 */
+ /* PC15 */ { 0, 0, 0, 1, 0, 0 }, /* PC15 */
+ /* PC14 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN *CD */
+ /* PC13 */ { 0, 0, 0, 1, 0, 0 }, /* PC13 */
+ /* PC12 */ { 0, 0, 0, 1, 0, 0 }, /* PC12 */
+ /* PC11 */ { 0, 0, 0, 1, 0, 0 }, /* PC11 */
+ /* PC10 */ { 0, 0, 0, 1, 0, 0 }, /* FCC2 MDC */
+ /* PC9 */ { 0, 0, 0, 1, 0, 0 }, /* FCC2 MDIO */
+ /* PC8 */ { 0, 0, 0, 1, 0, 0 }, /* PC8 */
+ /* PC7 */ { 0, 0, 0, 1, 0, 0 }, /* PC7 */
+ /* PC6 */ { 0, 0, 0, 1, 0, 0 }, /* PC6 */
+ /* PC5 */ { 0, 0, 0, 1, 0, 0 }, /* PC5 */
+ /* PC4 */ { 0, 0, 0, 1, 0, 0 }, /* PC4 */
+ /* PC3 */ { 0, 0, 0, 1, 0, 0 }, /* PC3 */
+ /* PC2 */ { 0, 0, 0, 1, 0, 1 }, /* ENET FDE */
+ /* PC1 */ { 0, 0, 0, 1, 0, 0 }, /* ENET DSQE */
+ /* PC0 */ { 0, 0, 0, 1, 0, 0 }, /* ENET LBK */
+ },
+
+ /* Port D */
+ { /* conf ppar psor pdir podr pdat */
+ /* PD31 */ { 1, 1, 0, 0, 0, 0 }, /* SCC1 EN RxD */
+ /* PD30 */ { 1, 1, 1, 1, 0, 0 }, /* SCC1 EN TxD */
+ /* PD29 */ { 1, 1, 0, 1, 0, 0 }, /* SCC1 EN TENA */
+ /* PD28 */ { 0, 0, 0, 1, 0, 0 }, /* PD28 */
+ /* PD27 */ { 0, 0, 0, 1, 0, 0 }, /* PD27 */
+ /* PD26 */ { 0, 0, 0, 1, 0, 0 }, /* PD26 */
+ /* PD25 */ { 0, 0, 0, 1, 0, 0 }, /* PD25 */
+ /* PD24 */ { 0, 0, 0, 1, 0, 0 }, /* PD24 */
+ /* PD23 */ { 0, 0, 0, 1, 0, 0 }, /* PD23 */
+ /* PD22 */ { 0, 0, 0, 1, 0, 0 }, /* PD22 */
+ /* PD21 */ { 0, 0, 0, 1, 0, 0 }, /* PD21 */
+ /* PD20 */ { 0, 0, 0, 1, 0, 0 }, /* PD20 */
+ /* PD19 */ { 0, 0, 0, 1, 0, 0 }, /* PD19 */
+ /* PD18 */ { 0, 0, 0, 1, 0, 0 }, /* PD19 */
+ /* PD17 */ { 0, 1, 0, 0, 0, 0 }, /* FCC1 ATMRXPRTY */
+ /* PD16 */ { 0, 1, 0, 1, 0, 0 }, /* FCC1 ATMTXPRTY */
+ /* PD15 */ { 0, 1, 1, 0, 1, 0 }, /* I2C SDA */
+ /* PD14 */ { 0, 1, 1, 0, 1, 0 }, /* I2C SCL */
+ /* PD13 */ { 0, 0, 0, 0, 0, 0 }, /* PD13 */
+ /* PD12 */ { 0, 0, 0, 0, 0, 0 }, /* PD12 */
+ /* PD11 */ { 0, 0, 0, 0, 0, 0 }, /* PD11 */
+ /* PD10 */ { 0, 0, 0, 0, 0, 0 }, /* PD10 */
+ /* PD9 */ { 1, 1, 0, 1, 0, 0 }, /* SMC1 TXD */
+ /* PD8 */ { 1, 1, 0, 0, 0, 0 }, /* SMC1 RXD */
+ /* PD7 */ { 0, 0, 0, 1, 0, 1 }, /* PD7 */
+ /* PD6 */ { 0, 0, 0, 1, 0, 1 }, /* PD6 */
+ /* PD5 */ { 0, 0, 0, 1, 0, 1 }, /* PD5 */
+ /* PD4 */ { 0, 0, 0, 1, 0, 1 }, /* PD4 */
+ /* PD3 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */
+ /* PD2 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */
+ /* PD1 */ { 0, 0, 0, 0, 0, 0 }, /* pin doesn't exist */
+ /* PD0 */ { 0, 0, 0, 0, 0, 0 } /* pin doesn't exist */
+ }
+};
+
+/* ------------------------------------------------------------------------- */
+
+/* Check Board Identity:
+ */
+int checkboard(void)
+{
+ printf ("TQM8260\n");
+ return 1;
+}
+
+/* ------------------------------------------------------------------------- */
+
+/* Try SDRAM initialization with P/LSDMR=sdmr and ORx=orx
+ *
+ * This routine performs standard 8260 initialization sequence
+ * and calculates the available memory size. It may be called
+ * several times to try different SDRAM configurations on both
+ * 60x and local buses.
+ */
+long int try_init(volatile memctl8260_t *memctl, ulong sdmr, ulong orx,
+ volatile uchar * base)
+{
+ volatile uchar c = 0xff;
+ ulong cnt, val;
+ volatile ulong * addr;
+ volatile uint * sdmr_ptr;
+ volatile uint * orx_ptr;
+ int i;
+
+ /* Since CFG_SDRAM_BASE is always 0 (??), we assume that
+ * we are configuring CS1 if base != 0
+ */
+ sdmr_ptr = base ? &memctl->memc_lsdmr : &memctl->memc_psdmr;
+ orx_ptr = base ? &memctl->memc_or2 : &memctl->memc_or1;
+
+ *orx_ptr = orx;
+
+ /*
+ * Quote from 8260 UM (10.4.2 SDRAM Power-On Initialization, 10-35):
+ *
+ * "At system reset, initialization software must set up the
+ * programmable parameters in the memory controller banks registers
+ * (ORx, BRx, P/LSDMR). After all memory parameters are configured,
+ * system software should execute the following initialization sequence
+ * for each SDRAM device.
+ *
+ * 1. Issue a PRECHARGE-ALL-BANKS command
+ * 2. Issue eight CBR REFRESH commands
+ * 3. Issue a MODE-SET command to initialize the mode register
+ *
+ * The initial commands are executed by setting P/LSDMR[OP] and
+ * accessing the SDRAM with a single-byte transaction."
+ *
+ * The appropriate BRx/ORx registers have already been set when we
+ * get here. The SDRAM can be accessed at the address CFG_SDRAM_BASE.
+ */
+
+ *sdmr_ptr = sdmr | PSDMR_OP_PREA;
+ *base = c;
+
+ *sdmr_ptr = sdmr | PSDMR_OP_CBRR;
+ for (i = 0; i < 8; i++)
+ *base = c;
+
+ *sdmr_ptr = sdmr | PSDMR_OP_MRW;
+ *(base + CFG_MRS_OFFS) = c; /* setting MR on address lines */
+
+ *sdmr_ptr = sdmr | PSDMR_OP_NORM | PSDMR_RFEN;
+ *base = c;
+
+ /*
+ * Check memory range for valid RAM. A simple memory test determines
+ * the actually available RAM size between addresses `base' and
+ * `base + maxsize'. Some (not all) hardware errors are detected:
+ * - short between address lines
+ * - short between data lines
+ */
+ for (cnt = 0x04000000/sizeof(long); cnt > 0; cnt >>= 1)
+ {
+ addr = (volatile ulong *)base + cnt; /* pointer arith! */
+ *addr = ~cnt;
+ }
+
+ addr = (volatile ulong *)base;
+ *addr = 0;
+
+ if ((val = *addr) != 0)
+ {
+ return (0);
+ }
+
+ for (cnt = 1; ; cnt <<=1)
+ {
+ addr = (volatile ulong *)base + cnt; /* pointer arith! */
+ val = *addr;
+ if (val != ~cnt)
+ {
+ /* Write the actual size to ORx
+ */
+ *orx_ptr = orx | ~(cnt * sizeof(long) - 1);
+ return (cnt * sizeof(long));
+ }
+ }
+ /* NOTREACHED */
+}
+
+long int initdram(int board_type)
+{
+ volatile immap_t *immap = (immap_t *)CFG_IMMR;
+ volatile memctl8260_t *memctl = &immap->im_memctl;
+#ifndef CFG_RAMBOOT
+ long size8, size9;
+#endif
+ long psize, lsize;
+
+ psize = 16 * 1024 * 1024;
+ lsize = 0;
+
+ memctl->memc_psrt = CFG_PSRT;
+ memctl->memc_mptpr = CFG_MPTPR;
+
+#ifndef CFG_RAMBOOT
+ /* 60x SDRAM setup:
+ */
+ size8 = try_init(memctl, CFG_PSDMR_8COL, CFG_OR1_8COL,
+ (uchar *) CFG_SDRAM_BASE);
+ size9 = try_init(memctl, CFG_PSDMR_9COL, CFG_OR1_9COL,
+ (uchar *) CFG_SDRAM_BASE);
+
+ if (size8 < size9)
+ {
+ psize = size9;
+ printf("(60x:9COL - %ld MB, ", psize >> 20);
+ }
+ else
+ {
+ psize = try_init(memctl, CFG_PSDMR_8COL, CFG_OR1_8COL,
+ (uchar *) CFG_SDRAM_BASE);
+ printf("(60x:8COL - %ld MB, ", psize >> 20);
+ }
+
+ /* Local SDRAM setup:
+ */
+#ifdef CFG_INIT_LOCAL_SDRAM
+ memctl->memc_lsrt = CFG_LSRT;
+ size8 = try_init(memctl, CFG_LSDMR_8COL, CFG_OR2_8COL,
+ (uchar *) SDRAM_BASE2_PRELIM);
+ size9 = try_init(memctl, CFG_LSDMR_9COL, CFG_OR2_9COL,
+ (uchar *) SDRAM_BASE2_PRELIM);
+
+ if (size8 < size9)
+ {
+ lsize = size9;
+ printf("Local:9COL - %ld MB) using ", lsize >> 20);
+ }
+ else
+ {
+ lsize = try_init(memctl, CFG_LSDMR_8COL, CFG_OR2_8COL,
+ (uchar *) SDRAM_BASE2_PRELIM);
+ printf("Local:8COL - %ld MB) using ", lsize >> 20);
+ }
+
+#if 0
+ /* Set up BR2 so that the local SDRAM goes
+ * right after the 60x SDRAM
+ */
+ memctl->memc_br2 = (CFG_BR2_PRELIM & ~BRx_BA_MSK) |
+ (CFG_SDRAM_BASE + psize);
+#endif
+#endif /* CFG_INIT_LOCAL_SDRAM */
+#endif /* CFG_RAMBOOT */
+
+ return (psize);
+}
+
cmd_console.o cmd_date.o cmd_eeprom.o \
cmd_flash.o cmd_ide.o cmd_mem.o cmd_net.o \
cmd_nvedit.o cmd_pcmcia.o cmd_reginfo.o \
- s_record.o dlmalloc.o \
+ cmd_bedbug.o bedbug.o s_record.o dlmalloc.o \
kgdb.o console.o lists.o devices.o flash.o cmd_i2c.o cmd_immap.o
OBJS = $(AOBJS) $(COBJS)
--- /dev/null
+/* $Id: bedbug.c,v 1.1 2001/05/31 22:12:25 wd Exp $ */
+
+#include <ppcboot.h>
+#include <linux/ctype.h>
+#include <bedbug/bedbug.h>
+#include <bedbug/ppc.h>
+#include <bedbug/regs.h>
+#include <bedbug/tables.h>
+
+#define Elf32_Word unsigned long
+
+/* USE_SOURCE_CODE enables some symbolic debugging functions of this
+ code. This is only useful if the program will have access to the
+ source code for the binary being examined.
+*/
+
+/* #define USE_SOURCE_CODE 1 */
+
+#ifdef USE_SOURCE_CODE
+extern int line_info_from_addr __P((Elf32_Word, char *, char *, int *));
+extern struct symreflist *symByAddr;
+extern char *symbol_name_from_addr __P((Elf32_Word,int,int *));
+#endif /* USE_SOURCE_CODE */
+
+int print_operands __P((struct ppc_ctx *));
+int get_operand_value __P(( struct opcode *, unsigned long,
+ enum OP_FIELD, unsigned long * ));
+struct opcode * find_opcode __P((unsigned long));
+struct opcode * find_opcode_by_name __P((char *));
+char * spr_name __P((int));
+int spr_value __P((char *));
+char * tbr_name __P((int));
+int tbr_value __P((char *));
+int parse_operand __P((unsigned long,struct opcode *,
+ struct operand *,char *,int *));
+int get_word __P((char**,char*));
+long read_number __P((char *));
+int downstring __P((char*));
+
+\f
+/*======================================================================
+ * Entry point for the PPC disassembler.
+ *
+ * Arguments:
+ * memaddr The address to start disassembling from.
+ *
+ * virtual If this value is non-zero, then this will be
+ * used as the base address for the output and
+ * symbol lookups. If this value is zero then
+ * memaddr is used as the absolute address.
+ *
+ * num_instr The number of instructions to disassemble. Since
+ * each instruction is 32 bits long, this can be
+ * computed if you know the total size of the region.
+ *
+ * pfunc The address of a function that is called to print
+ * each line of output. The function should take a
+ * single character pointer as its parameters a la puts.
+ *
+ * flags Sets options for the output. This is a
+ * bitwise-inclusive-OR of the following
+ * values. Note that only one of the radix
+ * options may be set.
+ *
+ * F_RADOCTAL - output radix is unsigned base 8.
+ * F_RADUDECIMAL - output radix is unsigned base 10.
+ * F_RADSDECIMAL - output radix is signed base 10.
+ * F_RADHEX - output radix is unsigned base 16.
+ * F_SIMPLE - use simplified mnemonics.
+ * F_SYMBOL - lookup symbols for addresses.
+ * F_INSTR - output raw instruction.
+ * F_LINENO - show line # info if available.
+ *
+ * Returns TRUE if the area was successfully disassembled or FALSE if
+ * a problem was encountered with accessing the memory.
+ */
+
+int disppc( unsigned char *memaddr, unsigned char *virtual, int num_instr,
+ int (*pfunc)(const char *), unsigned long flags )
+{
+ int i;
+ struct ppc_ctx ctx;
+#ifdef USE_SOURCE_CODE
+ int line_no = 0;
+ int last_line_no = 0;
+ char funcname[ 128 ] = {0};
+ char filename[ 256 ] = {0};
+ char last_funcname[ 128 ] = {0};
+ int symoffset;
+ char * symname;
+ char * cursym = (char *)0;
+#endif /* USE_SOURCE_CODE */
+ /*------------------------------------------------------------*/
+
+ ctx.flags = flags;
+ ctx.virtual = virtual;
+
+ /* Figure out the output radix before we go any further */
+
+ if( ctx.flags & F_RADOCTAL )
+ {
+ /* Unsigned octal output */
+ strcpy( ctx.radix_fmt, "O%o" );
+ }
+ else if( ctx.flags & F_RADUDECIMAL )
+ {
+ /* Unsigned decimal output */
+ strcpy( ctx.radix_fmt, "%u" );
+ }
+ else if( ctx.flags & F_RADSDECIMAL )
+ {
+ /* Signed decimal output */
+ strcpy( ctx.radix_fmt, "%d" );
+ }
+ else
+ {
+ /* Unsigned hex output */
+ strcpy( ctx.radix_fmt, "0x%x" );
+ }
+
+ if( ctx.virtual == 0 )
+ {
+ ctx.virtual = memaddr;
+ }
+
+#ifdef USE_SOURCE_CODE
+ if( ctx.flags & F_SYMBOL )
+ {
+ if( symByAddr == 0 ) /* no symbols loaded */
+ ctx.flags &= ~F_SYMBOL;
+ else
+ {
+ cursym = (char *)0;
+ symoffset = 0;
+ }
+ }
+#endif /* USE_SOURCE_CODE */
+
+ /* format each line as "XXXXXXXX: <symbol> IIIIIIII disassembly" where,
+ XXXXXXXX is the memory address in hex,
+ <symbol> is the symbolic location if F_SYMBOL is set.
+ IIIIIIII is the raw machine code in hex if F_INSTR is set,
+ and disassembly is the disassembled machine code with numbers
+ formatted according to the 'radix' parameter */
+
+ for( i = 0; i < num_instr; ++i, memaddr += 4, ctx.virtual += 4 )
+ {
+#ifdef USE_SOURCE_CODE
+ if( ctx.flags & F_LINENO )
+ {
+ if(( line_info_from_addr( (Elf32_Word) ctx.virtual, filename,
+ funcname, &line_no ) == TRUE ) &&
+ (( line_no != last_line_no ) ||
+ ( strcmp( last_funcname, funcname ) != 0 )))
+ {
+ print_source_line( filename, funcname, line_no, pfunc );
+ }
+ last_line_no = line_no;
+ strcpy( last_funcname, funcname );
+ }
+#endif /* USE_SOURCE_CODE */
+
+ sprintf( ctx.data, "%08lx: ", (unsigned long)ctx.virtual );
+ ctx.datalen = 10;
+
+#ifdef USE_SOURCE_CODE
+ if( ctx.flags & F_SYMBOL )
+ {
+ if(( symname =
+ symbol_name_from_addr( (Elf32_Word)ctx.virtual,
+ TRUE, 0 )) != 0 )
+ {
+ cursym = symname;
+ symoffset = 0;
+ }
+ else
+ {
+ if( (cursym == 0) &&
+ ((symname =
+ symbol_name_from_addr( (Elf32_Word)ctx.virtual,
+ FALSE, &symoffset )) != 0 ))
+ {
+ cursym = symname;
+ }
+ else
+ {
+ symoffset += 4;
+ }
+ }
+
+ if( cursym != 0 )
+ {
+ sprintf( &ctx.data[ ctx.datalen ], "<%s+", cursym );
+ ctx.datalen = strlen( ctx.data );
+ sprintf( &ctx.data[ ctx.datalen ], ctx.radix_fmt, symoffset );
+ strcat( ctx.data, ">" );
+ ctx.datalen = strlen( ctx.data );
+ }
+ }
+#endif /* USE_SOURCE_CODE */
+
+ ctx.instr = INSTRUCTION( memaddr );
+
+ if( ctx.flags & F_INSTR )
+ {
+ /* Find the opcode structure for this opcode. If one is not found
+ then it must be an illegal instruction */
+ sprintf( &ctx.data[ ctx.datalen ], " %02lx %02lx %02lx %02lx ",
+ ((ctx.instr >> 24) & 0xff), ((ctx.instr >> 16) & 0xff),
+ ((ctx.instr >> 8) & 0xff), (ctx.instr & 0xff));
+ ctx.datalen += 18;
+ }
+ else
+ {
+ strcat( ctx.data, " " );
+ ctx.datalen += 3;
+ }
+
+ if(( ctx.op = find_opcode( ctx.instr )) == 0 )
+ {
+ /* Illegal Opcode */
+ sprintf( &ctx.data[ ctx.datalen ], " .long 0x%08lx",
+ ctx.instr );
+ ctx.datalen += 24;
+ (*pfunc)( ctx.data );
+ continue;
+ }
+
+ if((( ctx.flags & F_SIMPLE ) == 0 ) ||
+ ( ctx.op->hfunc == 0 ) ||
+ ((*ctx.op->hfunc)( &ctx ) == FALSE ))
+ {
+ sprintf( &ctx.data[ ctx.datalen ], "%-7s ", ctx.op->name );
+ ctx.datalen += 8;
+ print_operands( &ctx );
+ }
+
+ (*pfunc)( ctx.data );
+ }
+
+ return TRUE;
+} /* disppc */
+
+
+\f
+/*======================================================================
+ * Called by the disassembler to print the operands for an instruction.
+ *
+ * Arguments:
+ * ctx A pointer to the disassembler context record.
+ *
+ * always returns 0.
+ */
+
+int print_operands( struct ppc_ctx *ctx )
+{
+ int open_parens = 0;
+ int field;
+ unsigned long operand;
+ struct operand * opr;
+#ifdef USE_SOURCE_CODE
+ char * symname;
+ int offset;
+#endif /* USE_SOURCE_CODE */
+ /*------------------------------------------------------------*/
+
+ /* Walk through the operands and list each in order */
+ for( field = 0; ctx->op->fields[ field ] != 0; ++field )
+ {
+ if( ctx->op->fields[ field ] > n_operands )
+ {
+ continue; /* bad operand ?! */
+ }
+
+ opr = &operands[ ctx->op->fields[ field ] - 1 ];
+
+ if( opr->hint & OH_SILENT )
+ {
+ continue;
+ }
+
+ if(( field > 0 ) && !open_parens )
+ {
+ strcat( ctx->data, "," );
+ ctx->datalen++;
+ }
+
+ operand = (ctx->instr >> opr->shift) & ((1 << opr->bits)-1);
+
+ if( opr->hint & OH_ADDR )
+ {
+ if(( operand & (1 << (opr->bits-1))) != 0 )
+ {
+ operand = operand - (1 << opr->bits);
+ }
+
+ if( ctx->op->hint & H_RELATIVE )
+ operand = (operand << 2) + (unsigned long)ctx->virtual;
+ else
+ operand = (operand << 2);
+
+
+ sprintf( &ctx->data[ ctx->datalen ], "0x%lx", operand );
+ ctx->datalen = strlen( ctx->data );
+
+#ifdef USE_SOURCE_CODE
+ if(( ctx->flags & F_SYMBOL ) &&
+ (( symname = symbol_name_from_addr( operand, 0, &offset )) != 0 ))
+ {
+ sprintf( &ctx->data[ ctx->datalen ], " <%s", symname );
+ if( offset != 0 )
+ {
+ strcat( ctx->data, "+" );
+ ctx->datalen = strlen( ctx->data );
+ sprintf( &ctx->data[ ctx->datalen ], ctx->radix_fmt,
+ offset );
+ }
+ strcat( ctx->data, ">" );
+ }
+#endif /* USE_SOURCE_CODE */
+ }
+
+ else if( opr->hint & OH_REG )
+ {
+ if(( operand == 0 ) &&
+ ( opr->field == O_rA ) &&
+ ( ctx->op->hint & H_RA0_IS_0 ))
+ {
+ strcat( ctx->data, "0" );
+ }
+ else
+ {
+ sprintf( &ctx->data[ ctx->datalen ], "r%d", (short)operand );
+ }
+
+ if( open_parens )
+ {
+ strcat( ctx->data, ")" );
+ open_parens--;
+ }
+ }
+
+ else if( opr->hint & OH_SPR )
+ {
+ strcat( ctx->data, spr_name( operand ));
+ }
+
+ else if( opr->hint & OH_TBR )
+ {
+ strcat( ctx->data, tbr_name( operand ));
+ }
+
+ else if( opr->hint & OH_LITERAL )
+ {
+ switch( opr->field )
+ {
+ case O_cr2:
+ strcat( ctx->data, "cr2" );
+ ctx->datalen += 3;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ else
+ {
+ sprintf( &ctx->data[ ctx->datalen ], ctx->radix_fmt,
+ (unsigned short)operand );
+
+ if( open_parens )
+ {
+ strcat( ctx->data, ")" );
+ open_parens--;
+ }
+
+ else if( opr->hint & OH_OFFSET )
+ {
+ strcat( ctx->data, "(" );
+ open_parens++;
+ }
+ }
+
+ ctx->datalen = strlen( ctx->data );
+ }
+
+ return 0;
+} /* print_operands */
+
+
+\f
+/*======================================================================
+ * Called to get the value of an arbitrary operand with in an instruction.
+ *
+ * Arguments:
+ * op The pointer to the opcode structure to which
+ * the operands belong.
+ *
+ * instr The instruction (32 bits) containing the opcode
+ * and the operands to print. By the time that
+ * this routine is called the operand has already
+ * been added to the output.
+ *
+ * field The field (operand) to get the value of.
+ *
+ * value The address of an unsigned long to be filled in
+ * with the value of the operand if it is found. This
+ * will only be filled in if the function returns
+ * TRUE. This may be passed as 0 if the value is
+ * not required.
+ *
+ * Returns TRUE if the operand was found or FALSE if it was not.
+ */
+
+int get_operand_value( struct opcode *op, unsigned long instr,
+ enum OP_FIELD field, unsigned long *value )
+{
+ int i;
+ struct operand * opr;
+ /*------------------------------------------------------------*/
+
+ if( field > n_operands )
+ {
+ return FALSE; /* bad operand ?! */
+ }
+
+ /* Walk through the operands and list each in order */
+ for( i = 0; op->fields[ i ] != 0; ++i )
+ {
+ if( op->fields[ i ] != field )
+ {
+ continue;
+ }
+
+ opr = &operands[ op->fields[ i ] - 1 ];
+
+ if( value )
+ {
+ *value = (instr >> opr->shift) & ((1 << opr->bits)-1);
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+} /* operand_value */
+
+
+\f
+/*======================================================================
+ * Called by the disassembler to match an opcode value to an opcode structure.
+ *
+ * Arguments:
+ * instr The instruction (32 bits) to match. This value
+ * may contain operand values as well as the opcode
+ * since they will be masked out anyway for this
+ * search.
+ *
+ * Returns the address of an opcode struct (from the opcode table) if the
+ * operand successfully matched an entry, or 0 if no match was found.
+ */
+
+struct opcode *find_opcode( unsigned long instr )
+{
+ struct opcode * ptr;
+ int top = 0;
+ int bottom = n_opcodes - 1;
+ int idx;
+ /*------------------------------------------------------------*/
+
+ while( top <= bottom )
+ {
+ idx = (top + bottom) >> 1;
+ ptr = &opcodes[ idx ];
+
+ if(( instr & ptr->mask ) < ptr->opcode )
+ {
+ bottom = idx - 1;
+ }
+ else if(( instr & ptr->mask ) > ptr->opcode )
+ {
+ top = idx + 1;
+ }
+ else
+ {
+ return ptr;
+ }
+ }
+
+ return (struct opcode *)0;
+} /* find_opcode */
+
+
+\f
+/*======================================================================
+ * Called by the assembler to match an opcode name to an opcode structure.
+ *
+ * Arguments:
+ * name The text name of the opcode, e.g. "b", "mtspr", etc.
+ *
+ * The opcodes are sorted numerically by their instruction binary code
+ * so a search for the name cannot use the binary search used by the
+ * other find routine.
+ *
+ * Returns the address of an opcode struct (from the opcode table) if the
+ * name successfully matched an entry, or 0 if no match was found.
+ */
+
+struct opcode *find_opcode_by_name( char *name )
+{
+ int idx;
+ /*------------------------------------------------------------*/
+
+ downstring( name );
+
+ for( idx = 0; idx < n_opcodes; ++idx )
+ {
+ if( !strcmp( name, opcodes[ idx ].name ))
+ return &opcodes[ idx ];
+ }
+
+ return (struct opcode *)0;
+} /* find_opcode_by_name */
+
+
+\f
+/*======================================================================
+ * Convert the 'spr' operand from its numeric value to its symbolic name.
+ *
+ * Arguments:
+ * value The value of the 'spr' operand. This value should
+ * be unmodified from its encoding in the instruction.
+ * the split-field computations will be performed
+ * here before the switch.
+ *
+ * Returns the address of a character array containing the name of the
+ * special purpose register defined by the 'value' parameter, or the
+ * address of a character array containing "???" if no match was found.
+ */
+
+char *spr_name( int value )
+{
+ unsigned short spr;
+ static char other[ 10 ];
+ int i;
+ /*------------------------------------------------------------*/
+
+ /* spr is a 10 bit field whose interpretation has the high and low
+ five-bit fields reversed from their encoding in the operand */
+
+ spr = (( value >> 5 ) & 0x1f ) | (( value & 0x1f ) << 5 );
+
+ for( i = 0; i < n_sprs; ++i ){
+ if( spr == spr_map[ i ].spr_val )
+ return spr_map[ i ].spr_name;
+ }
+
+ sprintf( other, "%d", spr );
+ return other;
+} /* spr_name */
+
+
+\f
+/*======================================================================
+ * Convert the 'spr' operand from its symbolic name to its numeric value
+ *
+ * Arguments:
+ * name The symbolic name of the 'spr' operand. The
+ * split-field encoding will be done by this routine.
+ * NOTE: name can be a number.
+ *
+ * Returns the numeric value for the spr appropriate for encoding a machine
+ * instruction. Returns 0 if unable to find the SPR.
+ */
+
+int spr_value( char *name )
+{
+ struct spr_info * sprp;
+ int spr;
+ int i;
+ /*------------------------------------------------------------*/
+
+ if( !name || !*name )
+ return 0;
+
+ if( isdigit((int)name[ 0 ])) {
+ i = htonl( read_number( name ));
+ spr = (( i >> 5 ) & 0x1f ) | (( i & 0x1f ) << 5 );
+ return spr;
+ }
+
+ downstring( name );
+
+ for( i = 0; i < n_sprs; ++i ) {
+ sprp = &spr_map[ i ];
+
+ if( strcmp( name, sprp->spr_name ) == 0 ) {
+ /* spr is a 10 bit field whose interpretation has the high and low
+ five-bit fields reversed from their encoding in the operand */
+ i = htonl( sprp->spr_val );
+ spr = (( i >> 5 ) & 0x1f ) | (( i & 0x1f ) << 5 );
+
+ return spr;
+ }
+ }
+
+ return 0;
+} /* spr_value */
+
+
+\f
+/*======================================================================
+ * Convert the 'tbr' operand from its numeric value to its symbolic name.
+ *
+ * Arguments:
+ * value The value of the 'tbr' operand. This value should
+ * be unmodified from its encoding in the instruction.
+ * the split-field computations will be performed
+ * here before the switch.
+ *
+ * Returns the address of a character array containing the name of the
+ * time base register defined by the 'value' parameter, or the address
+ * of a character array containing "???" if no match was found.
+ */
+
+char *tbr_name( int value )
+{
+ unsigned short tbr;
+ /*------------------------------------------------------------*/
+
+ /* tbr is a 10 bit field whose interpretation has the high and low
+ five-bit fields reversed from their encoding in the operand */
+
+ tbr = (( value >> 5 ) & 0x1f ) | (( value & 0x1f ) << 5 );
+
+ if( tbr == 268 )
+ return "TBL";
+
+ else if( tbr == 269 )
+ return "TBU";
+
+
+ return "???";
+} /* tbr_name */
+
+
+\f
+/*======================================================================
+ * Convert the 'tbr' operand from its symbolic name to its numeric value.
+ *
+ * Arguments:
+ * name The symbolic name of the 'tbr' operand. The
+ * split-field encoding will be done by this routine.
+ *
+ * Returns the numeric value for the spr appropriate for encoding a machine
+ * instruction. Returns 0 if unable to find the TBR.
+ */
+
+int tbr_value( char *name )
+{
+ int tbr;
+ int val;
+ /*------------------------------------------------------------*/
+
+ if( !name || !*name )
+ return 0;
+
+ downstring( name );
+
+ if( isdigit((int)name[ 0 ])) {
+ val = read_number( name );
+
+ if( val != 268 && val != 269 )
+ return 0;
+ }
+ else if( strcmp( name, "tbl" ) == 0 )
+ val = 268;
+ else if( strcmp( name, "tbu" ) == 0 )
+ val = 269;
+ else
+ return 0;
+
+ /* tbr is a 10 bit field whose interpretation has the high and low
+ five-bit fields reversed from their encoding in the operand */
+
+ val = htonl( val );
+ tbr = (( val >> 5 ) & 0x1f ) | (( val & 0x1f ) << 5 );
+ return tbr;
+} /* tbr_name */
+
+
+\f
+/*======================================================================
+ * The next several functions (handle_xxx) are the routines that handle
+ * disassembling the opcodes with simplified mnemonics.
+ *
+ * Arguments:
+ * ctx A pointer to the disassembler context record.
+ *
+ * Returns TRUE if the simpler form was printed or FALSE if it was not.
+ */
+
+int handle_bc( struct ppc_ctx *ctx )
+{
+ unsigned long bo;
+ unsigned long bi;
+ struct opcode blt = {B_OPCODE(16,0,0), B_MASK, {O_BD, 0},
+ 0, "blt", H_RELATIVE};
+ struct opcode bne = {B_OPCODE(16,0,0), B_MASK, {O_cr2, O_BD, 0},
+ 0, "bne", H_RELATIVE};
+ struct opcode bdnz = {B_OPCODE(16,0,0), B_MASK, {O_BD, 0},
+ 0, "bdnz", H_RELATIVE};
+ /*------------------------------------------------------------*/
+
+ if( get_operand_value( ctx->op, ctx->instr, O_BO, &bo ) == FALSE )
+ return FALSE;
+
+ if( get_operand_value( ctx->op, ctx->instr, O_BI, &bi ) == FALSE )
+ return FALSE;
+
+ if(( bo == 12 ) && ( bi == 0 ))
+ {
+ ctx->op = &blt;
+ sprintf( &ctx->data[ ctx->datalen ], "%-7s ", ctx->op->name );
+ ctx->datalen += 8;
+ print_operands( ctx );
+ return TRUE;
+ }
+ else if(( bo == 4 ) && ( bi == 10 ))
+ {
+ ctx->op = =⃥
+ sprintf( &ctx->data[ ctx->datalen ], "%-7s ", ctx->op->name );
+ ctx->datalen += 8;
+ print_operands( ctx );
+ return TRUE;
+ }
+ else if(( bo == 16 ) && ( bi == 0 ))
+ {
+ ctx->op = &bdnz;
+ sprintf( &ctx->data[ ctx->datalen ], "%-7s ", ctx->op->name );
+ ctx->datalen += 8;
+ print_operands( ctx );
+ return TRUE;
+ }
+
+ return FALSE;
+} /* handle_blt */
+
+
+\f
+/*======================================================================
+ * Outputs source line information for the disassembler. This should
+ * be modified in the future to lookup the actual line of source code
+ * from the file, but for now this will do.
+ *
+ * Arguments:
+ * filename The address of a character array containing the
+ * absolute path and file name of the source file.
+ *
+ * funcname The address of a character array containing the
+ * name of the function (not C++ demangled (yet))
+ * to which this code belongs.
+ *
+ * line_no An integer specifying the source line number that
+ * generated this code.
+ *
+ * pfunc The address of a function to call to print the output.
+ *
+ *
+ * Returns TRUE if it was able to output the line info, or false if it was
+ * not.
+ */
+
+int print_source_line( char *filename, char *funcname,
+ int line_no, int (*pfunc)(const char *))
+{
+ char out_buf[ 256 ];
+ /*------------------------------------------------------------*/
+
+ (*pfunc)( "" ); /* output a newline */
+ sprintf( out_buf, "%s %s(): line %d", filename, funcname, line_no );
+ (*pfunc)( out_buf );
+
+ return TRUE;
+} /* print_source_line */
+
+
+\f
+/*======================================================================
+ * Entry point for the PPC assembler.
+ *
+ * Arguments:
+ * asm_buf An array of characters containing the assembly opcode
+ * and operands to convert to a POWERPC machine
+ * instruction.
+ *
+ * Returns the machine instruction or zero.
+ */
+
+unsigned long asmppc( unsigned long memaddr, char *asm_buf, int *err )
+{
+ struct opcode * opc;
+ struct operand * oper[ MAX_OPERANDS ];
+ unsigned long instr;
+ unsigned long param;
+ char * ptr = asm_buf;
+ char scratch[ 20 ];
+ int i;
+ int w_operands = 0; /* wanted # of operands */
+ int n_operands = 0; /* # of operands read */
+ int asm_debug = 0;
+ /*------------------------------------------------------------*/
+
+ if( err )
+ *err = 0;
+
+ if( get_word( &ptr, scratch ) == 0 )
+ return 0;
+
+ /* Lookup the opcode structure based on the opcode name */
+ if(( opc = find_opcode_by_name( scratch )) == (struct opcode *)0 ) {
+ if( err ) *err = E_ASM_BAD_OPCODE;
+ return 0;
+ }
+
+ if( asm_debug ) {
+ printf( "asmppc: Opcode = \"%s\"\n", opc->name );
+ }
+
+ for( i = 0; i < 8; ++i ) {
+ if( opc->fields[ i ] == 0 )
+ break;
+ ++w_operands;
+ }
+
+ if( asm_debug ) {
+ printf( "asmppc: Expecting %d operands\n", w_operands );
+ }
+
+ instr = opc->opcode;
+
+ /* read each operand */
+ while( n_operands < w_operands ) {
+
+ oper[ n_operands ] = &operands[ opc->fields[ n_operands ] - 1 ];
+
+ if( oper[ n_operands ]->hint & OH_SILENT ) {
+ /* Skip silent operands, they are covered in opc->opcode */
+
+ if( asm_debug ) {
+ printf( "asmppc: Operand %d \"%s\" SILENT\n", n_operands,
+ oper[ n_operands ]->name );
+ }
+
+ ++n_operands;
+ continue;
+ }
+
+ if( get_word( &ptr, scratch ) == 0 )
+ break;
+
+ if( asm_debug ) {
+ printf( "asmppc: Operand %d \"%s\" : \"%s\"\n", n_operands,
+ oper[ n_operands ]->name, scratch );
+ }
+
+ if(( param = parse_operand( memaddr, opc, oper[ n_operands ],
+ scratch, err )) == 0 )
+ return 0;
+
+ instr |= param;
+ ++n_operands;
+ }
+
+ if( n_operands < w_operands ) {
+ if( err ) *err = E_ASM_NUM_OPERANDS;
+ return 0;
+ }
+
+ if( asm_debug ) {
+ printf( "asmppc: Instruction = 0x%08lx\n", instr );
+ }
+
+ return instr;
+} /* asmppc */
+
+
+\f
+/*======================================================================
+ * Called by the assembler to interpret a single operand
+ *
+ * Arguments:
+ * ctx A pointer to the disassembler context record.
+ *
+ * Returns 0 if the operand is ok, or -1 if it is bad.
+ */
+
+int parse_operand( unsigned long memaddr, struct opcode *opc,
+ struct operand *oper, char *txt, int *err )
+{
+ long data;
+ long mask;
+ int is_neg = 0;
+ /*------------------------------------------------------------*/
+
+ mask = (1 << oper->bits) - 1;
+
+ if( oper->hint & OH_ADDR ) {
+ data = read_number( txt );
+
+ if( opc->hint & H_RELATIVE )
+ data = data - memaddr;
+
+ if( data < 0 )
+ is_neg = 1;
+
+ data >>= 2;
+ data &= (mask >> 1);
+
+ if( is_neg )
+ data |= 1 << (oper->bits - 1);
+ }
+
+ else if( oper->hint & OH_REG ) {
+ if( txt[ 0 ] == 'r' || txt[ 0 ] == 'R' )
+ txt++;
+ else if( txt[ 0 ] == '%' && ( txt[ 1 ] == 'r' || txt[ 1 ] == 'R' ))
+ txt += 2;
+
+ data = read_number( txt );
+ if( data > 31 ) {
+ if( err ) *err = E_ASM_BAD_REGISTER;
+ return 0;
+ }
+
+ data = htonl( data );
+ }
+
+ else if( oper->hint & OH_SPR ) {
+ if(( data = spr_value( txt )) == 0 ) {
+ if( err ) *err = E_ASM_BAD_SPR;
+ return 0;
+ }
+ }
+
+ else if( oper->hint & OH_TBR ) {
+ if(( data = tbr_value( txt )) == 0 ) {
+ if( err ) *err = E_ASM_BAD_TBR;
+ return 0;
+ }
+ }
+
+ else {
+ data = htonl( read_number( txt ));
+ }
+
+ return (data & mask) << oper->shift;
+} /* parse_operand */
+
+
+char *asm_error_str( int err )
+{
+ switch( err ) {
+ case E_ASM_BAD_OPCODE: return "Bad opcode";
+ case E_ASM_NUM_OPERANDS: return "Bad number of operands";
+ case E_ASM_BAD_REGISTER: return "Bad register number";
+ case E_ASM_BAD_SPR: return "Bad SPR name or number";
+ case E_ASM_BAD_TBR: return "Bad TBR name or number";
+ }
+
+ return "";
+} /* asm_error_str */
+
+
+\f
+/*======================================================================
+ * Copy a word from one buffer to another, ignores leading white spaces.
+ *
+ * Arguments:
+ * src The address of a character pointer to the
+ * source buffer.
+ * dest A pointer to a character buffer to write the word
+ * into.
+ *
+ * Returns the number of non-white space characters copied, or zero.
+ */
+
+int get_word( char **src, char *dest )
+{
+ char * ptr = *src;
+ int nchars = 0;
+ /*------------------------------------------------------------*/
+
+ /* Eat white spaces */
+ while( *ptr && isblank( *ptr ))
+ ptr++;
+
+ if( *ptr == 0 ) {
+ *src = ptr;
+ return 0;
+ }
+
+ /* Find the text of the word */
+ while( *ptr && !isblank( *ptr ))
+ dest[ nchars++ ] = *ptr++;
+ dest[ nchars ] = 0;
+
+ *src = ptr;
+ return nchars;
+} /* get_word */
+
+
+\f
+/*======================================================================
+ * Convert a numeric string to a number, be aware of base notations.
+ *
+ * Arguments:
+ * txt The numeric string.
+ *
+ * Returns the converted numeric value.
+ */
+
+long read_number( char *txt )
+{
+ long val;
+ int is_neg = 0;
+ /*------------------------------------------------------------*/
+
+ if( txt == 0 || *txt == 0 )
+ return 0;
+
+ if( *txt == '-' ){
+ is_neg = 1;
+ ++txt;
+ }
+
+ if( txt[ 0 ] == '0' && ( txt[ 1 ] == 'x' || txt[ 1 ] == 'X' )) /* hex */
+ val = simple_strtoul( &txt[2], NULL, 16 );
+ else /* decimal */
+ val = simple_strtoul( txt, NULL, 10 );
+
+ if( is_neg )
+ val = -val;
+
+ return val;
+} /* read_number */
+
+
+int downstring( char *s )
+{
+ if( !s || !*s )
+ return 0;
+
+ while( *s ) {
+ if( isupper( *s ))
+ *s = tolower( *s );
+ s++;
+ }
+
+ return 0;
+} /* downstring */
+
+
+\f
+/*======================================================================
+ * Examines the instruction at the current address and determines the
+ * next address to be executed. This will take into account branches
+ * of different types so that a "step" and "next" operations can be
+ * supported.
+ *
+ * Arguments:
+ * nextaddr The address (to be filled in) of the next
+ * instruction to execute. This will only be a valid
+ * address if TRUE is returned.
+ *
+ * step_over A flag indicating how to compute addresses for
+ * branch statements:
+ * TRUE = Step over the branch (next)
+ * FALSE = step into the branch (step)
+ *
+ * Returns TRUE if it was able to compute the address. Returns FALSE if
+ * it has a problem reading the current instruction or one of the registers.
+ */
+
+int find_next_address( unsigned char *nextaddr, int step_over,
+ struct pt_regs *regs )
+{
+ unsigned long pc; /* SRR0 register from PPC */
+ unsigned long ctr; /* CTR register from PPC */
+ unsigned long cr; /* CR register from PPC */
+ unsigned long lr; /* LR register from PPC */
+ unsigned long instr; /* instruction at SRR0 */
+ unsigned long next; /* computed instruction for 'next' */
+ unsigned long step; /* computed instruction for 'step' */
+ unsigned long addr = 0; /* target address operand */
+ unsigned long aa = 0; /* AA operand */
+ unsigned long lk = 0; /* LK operand */
+ unsigned long bo = 0; /* BO operand */
+ unsigned long bi = 0; /* BI operand */
+ struct opcode * op = 0; /* opcode structure for 'instr' */
+ int ctr_ok = 0;
+ int cond_ok = 0;
+ int conditional = 0;
+ int branch = 0;
+ /*------------------------------------------------------------*/
+
+ if( nextaddr == 0 || regs == 0 )
+ {
+ printf( "find_next_address: bad args" );
+ return FALSE;
+ }
+
+ pc = regs->nip & 0xfffffffc;
+ instr = INSTRUCTION( pc );
+
+ if(( op = find_opcode( instr )) == (struct opcode *)0 )
+ {
+ printf( "find_next_address: can't parse opcode 0x%lx", instr );
+ return FALSE;
+ }
+
+ ctr = regs->ctr;
+ cr = regs->ccr;
+ lr = regs->link;
+
+ switch( op->opcode )
+ {
+ case B_OPCODE(16,0,0): /* bc */
+ case B_OPCODE(16,0,1): /* bcl */
+ case B_OPCODE(16,1,0): /* bca */
+ case B_OPCODE(16,1,1): /* bcla */
+ if( !get_operand_value( op, instr, O_BD, &addr ) ||
+ !get_operand_value( op, instr, O_BO, &bo ) ||
+ !get_operand_value( op, instr, O_BI, &bi ) ||
+ !get_operand_value( op, instr, O_AA, &aa ) ||
+ !get_operand_value( op, instr, O_LK, &lk ))
+ return FALSE;
+
+ if(( addr & (1 << 13)) != 0 )
+ addr = addr - (1 << 14);
+ addr <<= 2;
+ conditional = 1;
+ branch = 1;
+ break;
+
+ case I_OPCODE(18,0,0): /* b */
+ case I_OPCODE(18,0,1): /* bl */
+ case I_OPCODE(18,1,0): /* ba */
+ case I_OPCODE(18,1,1): /* bla */
+ if( !get_operand_value( op, instr, O_LI, &addr ) ||
+ !get_operand_value( op, instr, O_AA, &aa ) ||
+ !get_operand_value( op, instr, O_LK, &lk ))
+ return FALSE;
+
+ if(( addr & (1 << 23)) != 0 )
+ addr = addr - (1 << 24);
+ addr <<= 2;
+ conditional = 0;
+ branch = 1;
+ break;
+
+ case XL_OPCODE(19,528,0): /* bcctr */
+ case XL_OPCODE(19,528,1): /* bcctrl */
+ if( !get_operand_value( op, instr, O_BO, &bo ) ||
+ !get_operand_value( op, instr, O_BI, &bi ) ||
+ !get_operand_value( op, instr, O_LK, &lk ))
+ return FALSE;
+
+ addr = ctr;
+ aa = 1;
+ conditional = 1;
+ branch = 1;
+ break;
+
+ case XL_OPCODE(19,16,0): /* bclr */
+ case XL_OPCODE(19,16,1): /* bclrl */
+ if( !get_operand_value( op, instr, O_BO, &bo ) ||
+ !get_operand_value( op, instr, O_BI, &bi ) ||
+ !get_operand_value( op, instr, O_LK, &lk ))
+ return FALSE;
+
+ addr = lr;
+ aa = 1;
+ conditional = 1;
+ branch = 1;
+ break;
+
+ default:
+ conditional = 0;
+ branch = 0;
+ break;
+ }
+
+ if( conditional )
+ {
+ switch((bo & 0x1e) >> 1 )
+ {
+ case 0: /* 0000y */
+ if( --ctr != 0 )
+ ctr_ok = 1;
+
+ cond_ok = !(cr & (1 << (31 - bi)));
+ break;
+
+ case 1: /* 0001y */
+ if( --ctr == 0 )
+ ctr_ok = 1;
+
+ cond_ok = !(cr & (1 << (31 - bi)));
+ break;
+
+ case 2: /* 001zy */
+ ctr_ok = 1;
+ cond_ok = !(cr & (1 << (31 - bi)));
+ break;
+
+ case 4: /* 0100y */
+ if( --ctr != 0 )
+ ctr_ok = 1;
+
+ cond_ok = cr & (1 << (31 - bi));
+ break;
+
+ case 5: /* 0101y */
+ if( --ctr == 0 )
+ ctr_ok = 1;
+
+ cond_ok = cr & (1 << (31 - bi));
+ break;
+
+ case 6: /* 011zy */
+ ctr_ok = 1;
+ cond_ok = cr & (1 << (31 - bi));
+ break;
+
+ case 8: /* 1z00y */
+ if( --ctr != 0 )
+ ctr_ok = cond_ok = 1;
+ break;
+
+ case 9: /* 1z01y */
+ if( --ctr == 0 )
+ ctr_ok = cond_ok = 1;
+ break;
+
+ case 10: /* 1z1zz */
+ ctr_ok = cond_ok = 1;
+ break;
+ }
+ }
+
+ if( branch && (!conditional || (ctr_ok && cond_ok)))
+ {
+ if( aa )
+ step = addr;
+ else
+ step = addr + pc;
+
+ if( lk )
+ next = pc + 4;
+ else
+ next = step;
+ }
+ else
+ {
+ step = next = pc + 4;
+ }
+
+ if( step_over == TRUE )
+ *(unsigned long *)nextaddr = next;
+ else
+ *(unsigned long *)nextaddr = step;
+
+ return TRUE;
+} /* find_next_address */
+
+
+/*
+ * Copyright (c) 2000 William L. Pitts and W. Gerald Hicks
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
#if (CONFIG_COMMANDS & CFG_CMD_NET)
#include <net.h>
#endif
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+#include <cmd_bedbug.h>
+#endif
#ifdef CFG_ALLOC_DPRAM
#include <commproc.h>
#endif
ide_init(bd);
#endif /* CFG_CMD_IDE */
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+ bedbug_init();
+#endif
+
/** LEAVE THIS HERE **/
/* Initialize devices */
devices_init (reloc_off);
--- /dev/null
+/*
+ * BedBug Functions
+ */
+
+#include <ppcboot.h>
+#include <command.h>
+#include <linux/ctype.h>
+#include <net.h>
+
+#include <cmd_bedbug.h>
+#include <bedbug/bedbug.h>
+#include <bedbug/regs.h>
+#include <bedbug/ppc.h>
+#include <bedbug/elf.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+
+#ifndef MAX
+#define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
+
+extern void show_regs __P((struct pt_regs*));
+extern int run_command __P((const char*,bd_t*,int));
+extern char console_buffer[];
+
+ulong dis_last_addr = 0; /* Last address disassembled */
+ulong dis_last_len = 20; /* Default disassembler length */
+CPU_DEBUG_CTX bug_ctx; /* Bedbug context structure */
+
+\f
+/* ======================================================================
+ * PPCBOOT's puts function does not append a newline, so the bedbug stuff
+ * will use this for the output of the dis/assembler.
+ * ====================================================================== */
+
+int bedbug_puts(const char *str)
+{
+ /* -------------------------------------------------- */
+
+ printf( "%s\r\n", str );
+ return 0;
+} /* bedbug_puts */
+
+
+\f
+/* ======================================================================
+ * Initialize the bug_ctx structure used by the bedbug debugger. This is
+ * specific to the CPU since each has different debug registers and
+ * settings.
+ * ====================================================================== */
+
+void bedbug_init( void )
+{
+ /* -------------------------------------------------- */
+
+#if defined(CONFIG_PPC405)
+ void bedbug405_init( void );
+
+ bedbug405_init();
+#endif
+
+ return;
+} /* bedbug_init */
+
+
+\f
+/* ======================================================================
+ * Entry point from the interpreter to the disassembler. Repeated calls
+ * will resume from the last disassembled address.
+ * ====================================================================== */
+
+void do_bedbug_dis (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+ char *argv[])
+{
+ ulong addr; /* Address to start disassembly from */
+ ulong len; /* # of instructions to disassemble */
+ /* -------------------------------------------------- */
+
+ /* Setup to go from the last address if none is given */
+ addr = dis_last_addr;
+ len = dis_last_len;
+
+ if (argc < 2)
+ {
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return;
+ }
+
+ if(( flag & CMD_FLAG_REPEAT ) == 0 )
+ {
+ /* New command */
+ addr = simple_strtoul( argv[1], NULL, 16 );
+
+ /* If an extra param is given then it is the length */
+ if( argc > 2 )
+ len = simple_strtoul( argv[2], NULL, 16 );
+ }
+
+ /* Run the disassembler */
+ disppc( (unsigned char *)addr, 0, len, bedbug_puts, F_RADHEX );
+
+ dis_last_addr = addr + (len * 4);
+ dis_last_len = len;
+} /* do_bedbug_dis */
+
+
+\f
+/* ======================================================================
+ * Entry point from the interpreter to the assembler. Assembles
+ * instructions in consecutive memory locations until a '.' (period) is
+ * entered on a line by itself.
+ * ====================================================================== */
+
+void do_bedbug_asm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+ char *argv[])
+{
+ long mem_addr; /* Address to assemble into */
+ unsigned long instr; /* Machine code for text */
+ char prompt[ 15 ]; /* Prompt string for user input */
+ int asm_err; /* Error code from the assembler*/
+ /* -------------------------------------------------- */
+
+ if (argc < 2)
+ {
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return;
+ }
+
+ printf( "\nEnter '.' when done\n" );
+ mem_addr = simple_strtoul( argv[ 1 ], NULL, 16 );
+
+ while( 1 )
+ {
+ putc( '\n' );
+ disppc( (unsigned char *)mem_addr, 0, 1, bedbug_puts, F_RADHEX );
+
+ sprintf( prompt, "%08lx: ", mem_addr );
+ readline( prompt );
+
+ if( console_buffer[ 0 ] && strcmp( console_buffer, "." ))
+ {
+ if(( instr = asmppc( mem_addr, console_buffer, &asm_err )) != 0 )
+ {
+ *(unsigned long *)mem_addr = instr;
+ mem_addr += 4;
+ }
+ else
+ {
+ printf( "*** Error: %s ***\n", asm_error_str( asm_err ));
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+} /* do_bedbug_asm */
+
+
+\f
+/* ======================================================================
+ * Used to set a break point from the interpreter. Simply calls into the
+ * CPU-specific break point set routine.
+ * ====================================================================== */
+
+void do_bedbug_break (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+ char *argv[])
+{
+ /* -------------------------------------------------- */
+
+ if( bug_ctx.do_break )
+ (*bug_ctx.do_break)( cmdtp, bd, flag, argc, argv );
+} /* do_bedbug_break */
+
+
+\f
+/* ======================================================================
+ * Called from the debug interrupt routine. Simply calls the CPU-specific
+ * breakpoint handling routine.
+ * ====================================================================== */
+
+void do_bedbug_breakpoint( struct pt_regs *regs )
+{
+ /* -------------------------------------------------- */
+
+ if( bug_ctx.break_isr )
+ (*bug_ctx.break_isr)( regs );
+} /* do_bedbug_breakpoint */
+
+
+\f
+/* ======================================================================
+ * Called from the CPU-specific breakpoint handling routine. Enter a
+ * mini main loop until the stopped flag is cleared from the breakpoint
+ * context.
+ *
+ * This handles the parts of the debugger that are common to all CPU's.
+ * ====================================================================== */
+
+void bedbug_main_loop( unsigned long addr, struct pt_regs *regs )
+{
+ int len; /* Length of command line */
+ int flag; /* Command flags */
+ int rc; /* Result from run_command*/
+ char prompt_str[ 20 ]; /* Prompt string */
+ static char lastcommand[ CFG_CBSIZE ] = {0}; /* previous command */
+ /* -------------------------------------------------- */
+
+ if( bug_ctx.clear )
+ (*bug_ctx.clear)( bug_ctx.current_bp );
+
+ printf( "Breakpoint %d: ", bug_ctx.current_bp );
+ disppc( (unsigned char *)addr, 0, 1, bedbug_puts, F_RADHEX );
+
+ bug_ctx.stopped = 1;
+ bug_ctx.regs = regs;
+
+ sprintf( prompt_str, "BEDBUG.%d =>", bug_ctx.current_bp );
+
+ /* A miniature main loop */
+ while( bug_ctx.stopped )
+ {
+ len = readline( prompt_str );
+
+ flag = 0; /* assume no special flags for now */
+
+ if (len > 0)
+ strcpy( lastcommand, console_buffer );
+ else if( len == 0 )
+ flag |= CMD_FLAG_REPEAT;
+
+ if (len == -1)
+ printf ("<INTERRUPT>\n");
+ else
+ rc = run_command( lastcommand, bug_ctx.bd, flag );
+
+ if (rc <= 0) {
+ /* invalid command or not repeatable, forget it */
+ lastcommand[0] = 0;
+ }
+ }
+
+ bug_ctx.regs = NULL;
+ bug_ctx.current_bp = 0;
+
+ return;
+} /* bedbug_main_loop */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to continue from a breakpoint. Just clears the
+ * stopped flag in the context so that the breakpoint routine will
+ * return.
+ * ====================================================================== */
+
+void do_bedbug_continue (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+ char *argv[])
+{
+ /* -------------------------------------------------- */
+
+ if( ! bug_ctx.stopped )
+ {
+ printf( "Not at a breakpoint\n" );
+ return;
+ }
+
+ bug_ctx.stopped = 0;
+ return;
+} /* do_bedbug_continue */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to continue to the next instruction, stepping into
+ * subroutines. Works by calling the find_next_addr() routine to compute
+ * the address passes control to the CPU-specific set breakpoint routine
+ * for the current breakpoint number.
+ * ====================================================================== */
+
+void do_bedbug_step (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+ char *argv[])
+{
+ unsigned long addr; /* Address to stop at */
+ /* -------------------------------------------------- */
+
+ if( ! bug_ctx.stopped )
+ {
+ printf( "Not at a breakpoint\n" );
+ return;
+ }
+
+ if( !find_next_address( (unsigned char *)&addr, FALSE, bug_ctx.regs ))
+ return;
+
+ if( bug_ctx.set )
+ (*bug_ctx.set)( bug_ctx.current_bp, addr );
+
+ bug_ctx.stopped = 0;
+ return;
+} /* do_bedbug_step */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to continue to the next instruction, stepping over
+ * subroutines. Works by calling the find_next_addr() routine to compute
+ * the address passes control to the CPU-specific set breakpoint routine
+ * for the current breakpoint number.
+ * ====================================================================== */
+
+void do_bedbug_next (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+ char *argv[])
+{
+ unsigned long addr; /* Address to stop at */
+ /* -------------------------------------------------- */
+
+ if( ! bug_ctx.stopped )
+ {
+ printf( "Not at a breakpoint\n" );
+ return;
+ }
+
+ if( !find_next_address( (unsigned char *)&addr, TRUE, bug_ctx.regs ))
+ return;
+
+ if( bug_ctx.set )
+ (*bug_ctx.set)( bug_ctx.current_bp, addr );
+
+ bug_ctx.stopped = 0;
+ return;
+} /* do_bedbug_next */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to print the current stack. This assumes an EABI
+ * architecture, so it starts with GPR R1 and works back up the stack.
+ * ====================================================================== */
+
+void do_bedbug_stack (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+ char *argv[])
+{
+ unsigned long sp; /* Stack pointer */
+ unsigned long func; /* LR from stack */
+ int depth; /* Stack iteration level */
+ int skip = 1; /* Flag to skip the first entry */
+ unsigned long top; /* Top of memory address */
+ /* -------------------------------------------------- */
+
+ if( ! bug_ctx.stopped )
+ {
+ printf( "Not at a breakpoint\n" );
+ return;
+ }
+
+ top = bd->bi_memstart + bd->bi_memsize;
+ depth = 0;
+
+ printf( "Depth PC\n" );
+ printf( "----- --------\n" );
+ printf( "%5d %08lx\n", depth++, bug_ctx.regs->nip );
+
+ sp = bug_ctx.regs->gpr[ 1 ];
+ func = *(unsigned long *)(sp+4);
+
+ while(( func < top ) && ( sp < top ))
+ {
+ if( !skip )
+ printf( "%5d %08lx\n", depth++, func );
+ else
+ --skip;
+
+ sp = *(unsigned long *)sp;
+ func = *(unsigned long *)(sp+4);
+ }
+
+ return;
+} /* do_bedbug_stack */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to dump the registers. Calls the CPU-specific
+ * show registers routine.
+ * ====================================================================== */
+
+void do_bedbug_rdump (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+ char *argv[])
+{
+ /* -------------------------------------------------- */
+
+ if( ! bug_ctx.stopped )
+ {
+ printf( "Not at a breakpoint\n" );
+ return;
+ }
+
+ show_regs( bug_ctx.regs );
+ return;
+} /* do_bedbug_rdump */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to boot an arbitrary ELF image from memory.
+ * ====================================================================== */
+
+void do_bootelf( cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[] )
+{
+ unsigned long addr; /* Address of the ELF image */
+ unsigned long rc; /* Return value from user code */
+ /* -------------------------------------------------- */
+
+ if (argc < 2)
+ addr = load_addr;
+ else
+ addr = simple_strtoul( argv[ 1 ], NULL, 16 );
+
+ if( ! valid_elf_image( addr ))
+ return;
+
+ addr = load_elf_image( addr );
+
+ printf ("## Starting application at 0x%08lx ...\n", addr);
+
+ /*
+ * pass address parameter as argv[0] (aka command name),
+ * and all remaining args
+ */
+ rc = ((ulong (*)(bd_t *, int, char *[]))addr) (bd, --argc, &argv[1]);
+
+ printf ("## Application terminated, rc = 0x%lx\n", rc);
+} /* do_bootelf */
+
+
+\f
+/* ======================================================================
+ * Interpreter command to boot VxWorks from a memory image. The image can
+ * be either an ELF image or a raw binary. Will attempt to setup the
+ * bootline and other parameters correctly.
+ * ====================================================================== */
+
+void do_bootvx( cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[] )
+{
+ unsigned long addr; /* Address of image */
+ unsigned long bootaddr; /* Address to put the bootline */
+ char * bootline; /* Text of the bootline */
+ char * tmp; /* Temporary char pointer */
+#if defined(CONFIG_PPC405)
+ char build_buf[ 80 ]; /* Buffer for building the bootline */
+#endif
+ /* -------------------------------------------------- */
+
+ /* Check the loadaddr variable. If we don't know where the image is
+ then we're done. */
+
+ if(( tmp = getenv( "loadaddr" )) != NULL )
+ {
+ addr = simple_strtoul( tmp, NULL, 16 );
+ }
+ else
+ {
+ printf( "No load address provided\n" );
+ return;
+ }
+
+ /* Check to see if we need to tftp the image ourselves before starting */
+
+ if(( argc == 2 ) && ( strcmp( argv[ 1 ], "tftp" ) == 0 ))
+ {
+ if( NetLoop( bd, TFTP ) == 0 )
+ return;
+
+ printf( "Automatic boot of VxWorks image at address 0x%08lx ... \n",
+ addr );
+ }
+
+ /* This should equate to NV_RAM_ADRS + NV_BOOT_OFFSET + NV_ENET_OFFSET
+ from the VxWorks BSP header files. This will vary from board to board */
+
+#if defined(CONFIG_WALNUT405)
+ tmp = (char *)CFG_NVRAM_BASE_ADDR + 0x500;
+ memcpy( (char *)tmp, (char *)&bd->bi_enetaddr[3], 3 );
+#else
+ printf( "## Ethernet MAC address not copied to NV RAM\n" );
+#endif
+
+ /* Use bootaddr to find the location in memory that VxWorks will
+ look for the bootline string. The default value for PowerPC
+ is LOCAL_MEM_LOCAL_ADRS + BOOT_LINE_OFFSET which defaults
+ to 0x4200 */
+
+ if(( tmp = getenv( "bootaddr" )) == NULL )
+ bootaddr = 0x4200;
+ else
+ bootaddr = simple_strtoul( tmp, NULL, 16 );
+
+ /* Check to see if the bootline is defined in the 'bootargs' parameter.
+ If it is not defined, we may be able to construct the info */
+
+ if(( bootline = getenv( "bootargs" )) != NULL )
+ {
+ memcpy( (void *)bootaddr, bootline, MAX( strlen( bootline ), 255 ));
+ }
+ else
+ {
+#if defined(CONFIG_PPC405)
+ sprintf( build_buf, "ibmEmac(0,0)" );
+
+ if(( tmp = getenv( "hostname" )) != NULL )
+ {
+ sprintf( &build_buf[ strlen( build_buf - 1 ) ], "host:%s ", tmp );
+ }
+ else
+ {
+ sprintf( &build_buf[ strlen( build_buf - 1 ) ], ": " );
+ }
+
+ if(( tmp = getenv( "ipaddr" )) != NULL )
+ {
+ sprintf( &build_buf[ strlen( build_buf - 1 ) ], "e=%s ", tmp );
+ }
+#else
+
+ /* I'm not sure what the device should be for other
+ PPC flavors, the hostname and ipaddr should be ok to just copy */
+
+ printf( "No bootargs defined\n" );
+ return;
+#endif
+ }
+
+ /* If the data at the load address is an elf image, then treat it like
+ an elf image. Otherwise, assume that it is a binary image */
+
+ if( valid_elf_image( addr ))
+ {
+ addr = load_elf_image( addr );
+ }
+ else
+ {
+ printf( "## Not an ELF image, assuming binary\n" );
+ /* leave addr as load_addr */
+ }
+
+ printf ("## Starting vxWorks at 0x%08lx ...\n", addr);
+
+ ((void (*)(void))addr)();
+
+ printf ("## vxWorks terminated\n" );
+} /* do_bootvx */
+
+
+\f
+/* ======================================================================
+ * Determine if a valid ELF image exists at the given memory location.
+ * First looks at the ELF header magic field, the makes sure that it is
+ * executable and makes sure that it is for a PowerPC.
+ * ====================================================================== */
+
+int valid_elf_image( unsigned long addr )
+{
+ Elf32_Ehdr * ehdr; /* Elf header structure pointer */
+ /* -------------------------------------------------- */
+
+ ehdr = (Elf32_Ehdr *)addr;
+
+ if( ! IS_ELF( *ehdr )) {
+ printf( "## No elf image at address 0x%08lx\n", addr );
+ return 0;
+ }
+
+ if( ehdr->e_type != ET_EXEC ) {
+ printf( "## Not a 32-bit elf image at address 0x%08lx\n", addr );
+ return 0;
+ }
+
+ if( ehdr->e_machine != EM_PPC ) {
+ printf( "## Not a PowerPC elf image at address 0x%08lx\n", addr );
+ return 0;
+ }
+
+ return 1;
+} /* valid_elf_image */
+
+
+\f
+/* ======================================================================
+ * A very simple elf loader, assumes the image is valid, returns the
+ * entry point address.
+ * ====================================================================== */
+
+unsigned long load_elf_image( unsigned long addr )
+{
+ Elf32_Ehdr * ehdr; /* Elf header structure pointer */
+ Elf32_Shdr * shdr; /* Section header structure pointer */
+ unsigned char * strtab = 0; /* String table pointer */
+ unsigned char * image; /* Binary image pointer */
+ int i; /* Loop counter */
+ /* -------------------------------------------------- */
+
+ ehdr = (Elf32_Ehdr *)addr;
+
+ /* Find the section header string table for output info */
+ shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff +
+ (ehdr->e_shstrndx * sizeof( Elf32_Shdr )));
+
+ if( shdr->sh_type == SHT_STRTAB )
+ strtab = ( unsigned char *)(addr + shdr->sh_offset);
+
+ /* Load each appropriate section */
+ for( i = 0; i < ehdr->e_shnum; ++i ) {
+ shdr = (Elf32_Shdr *)(addr + ehdr->e_shoff + (i * sizeof( Elf32_Shdr )));
+
+ if( !( shdr->sh_flags & SHF_ALLOC )
+ || shdr->sh_type == SHT_NOBITS
+ || shdr->sh_addr == 0
+ || shdr->sh_size == 0 )
+ continue;
+
+ if( strtab ) {
+ printf( "Loading %s @ 0x%08lx (%ld bytes)\n",
+ &strtab[ shdr->sh_name ], (unsigned long)shdr->sh_addr,
+ (long)shdr->sh_size );
+ }
+
+ image = (unsigned char *)addr + shdr->sh_offset;
+ memcpy( (void *)shdr->sh_addr, (const void *)image, shdr->sh_size );
+ }
+
+ return ehdr->e_entry;
+} /* load_elf_image */
+
+
+/* ====================================================================== */
+#endif /* CFG_CMD_BEDBUG */
+
+
+/*
+ * Copyright (c) 2001 William L. Pitts
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
/*
- * (C) Copyright 2000
+ * (C) Copyright 2000, 2001
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
unsigned char i2c_addr, sec_addr, *data_addr;
unsigned short size;
int speed;
+
+
+
+#if !defined(CONFIG_CPCI405) && !defined(CONFIG_AR405) && \
+ !defined (CONFIG_WALNUT405) && !defined (CONFIG_ERIC)
+
i2c_state_t state;
+#endif
+
int rc;
switch (argc) {
case 2:
if (strncmp (argv[1], "res", 3) == 0) {
printf ("I2C reset 50kHz ... ");
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+ i2c_init ();
+#else
i2c_init (50000, 0xfe); /* use all one's as slave address */
+#endif
printf ("DONE\n");
return;
}
printf ("I2C reset %d.%03dkHz ... ", speed/1000, speed%1000);
else
printf ("I2C reset %dkHz ... ", speed/1000);
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+ i2c_init ();
+#else
i2c_init (speed, 0xfe); /* use all one's as slave address */
+#endif
printf ("DONE\n");
return;
}
break;
case 5:
- if (strcmp(argv[1], "recv") == 0) {
+ if (strncmp(argv[1], "recv", 4) == 0) {
i2c_addr = (unsigned char)simple_strtoul(argv[2], NULL, 16);
data_addr = (unsigned char *)simple_strtoul(argv[3], NULL, 16);
size = (unsigned short)simple_strtoul(argv[4], NULL, 16);
#endif
, i2c_addr, (ulong)data_addr, size);
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+#else
i2c_newio (&state);
+#endif
+
+
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+ rc = i2c_receive (i2c_addr, size, data_addr);
+#else
rc = i2c_receive (&state, i2c_addr, 0,
I2CF_START_COND|I2CF_STOP_COND,
size, data_addr);
+#endif
+
+
if (rc) {
printf ("i2c_receive FAILED rc=%d\n", rc);
return;
}
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+#else
+
rc = i2c_doio (&state);
+#endif
+
if (rc) {
printf ("i2c_doio FAILED rc=%d\n", rc);
return;
printf ("DONE\n");
return;
- } else if (strcmp(argv[1], "send") == 0) {
+ } else if (strncmp(argv[1], "send",4) == 0) {
i2c_addr = (unsigned char)simple_strtoul(argv[2], NULL, 16);
data_addr = (unsigned char *)simple_strtoul(argv[3], NULL, 16);
size = (unsigned short)simple_strtoul(argv[4], NULL, 16);
printf ("I2C send: i2c_addr 0x%02x, data_addr 0x%08lx, "
"size %u ... ", i2c_addr, (ulong)data_addr, size);
+
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+#else
i2c_newio (&state);
+#endif
+
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+ rc = i2c_send (i2c_addr, size, data_addr);
+#else
rc = i2c_send (&state, i2c_addr, 0,
I2CF_START_COND|I2CF_STOP_COND, size, data_addr);
+#endif
if (rc) {
printf ("i2c_receive FAILED rc=%d\n", rc);
return;
}
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+#else
+
rc = i2c_doio (&state);
+#endif
+
if (rc) {
printf ("i2c_doio FAILED rc=%d\n", rc);
return;
break;
case 6:
- if (strcmp(argv[1], "rcvs") == 0) {
+ if (strncmp(argv[1], "rcvs", 4) == 0) {
i2c_addr = (unsigned char)simple_strtoul(argv[2], NULL, 16);
sec_addr = (unsigned char)simple_strtoul(argv[3], NULL, 16);
data_addr = (unsigned char *)simple_strtoul(argv[4], NULL, 16);
"data_addr 0x%08lx, size %u ... ",
i2c_addr, sec_addr, (ulong)data_addr, size);
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+#else
i2c_newio (&state);
+#endif
+
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+ rc = i2c_receive (i2c_addr, size, data_addr);
+#else
rc = i2c_receive (&state, i2c_addr, sec_addr,
I2CF_ENABLE_SECONDARY|I2CF_START_COND|I2CF_STOP_COND,
size, data_addr);
+#endif
+
if (rc) {
printf ("i2c_receive FAILED rc=%d\n", rc);
return;
}
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+#else
+
rc = i2c_doio (&state);
+#endif
+
if (rc) {
printf ("i2c_doio FAILED rc=%d\n", rc);
return;
printf ("DONE\n");
return;
}
- else if (strcmp(argv[1], "snds") == 0) {
+ else if (strncmp(argv[1], "snds",4) == 0) {
i2c_addr = (unsigned char)simple_strtoul(argv[2], NULL, 16);
sec_addr = (unsigned char)simple_strtoul(argv[3], NULL, 16);
data_addr = (unsigned char *)simple_strtoul(argv[4], NULL, 16);
"data_addr 0x%08lx, size %u ... ",
i2c_addr, sec_addr, (ulong)data_addr, size);
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+#else
i2c_newio (&state);
+#endif
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+ rc = i2c_send (i2c_addr, size, data_addr);
+#else
rc = i2c_send (&state, i2c_addr, sec_addr,
I2CF_ENABLE_SECONDARY|I2CF_START_COND|I2CF_STOP_COND,
size, data_addr);
+#endif
+
if (rc) {
printf ("i2c_send FAILED rc=%d\n", rc);
return;
}
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
+
+#else
+
rc = i2c_doio (&state);
+#endif
+
if (rc) {
printf ("i2c_doio FAILED rc=%d\n", rc);
return;
{
int len, rc;
ulong end_addr;
- uchar *flash_offset;
uchar *flash_sect_addr;
#if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE)
-
- uchar env_buffer[CFG_ENV_SECT_SIZE];
+ uchar *flash_offset;
+ uchar env_buffer[CFG_ENV_SECT_SIZE];
#else
uchar *env_buffer = (char *)env_ptr;
#endif /* CFG_ENV_SECT_SIZE */
- flash_offset = (uchar *)(((unsigned long)flash_addr) & (CFG_ENV_SECT_SIZE-1));
- flash_sect_addr = (uchar *)(((unsigned long)flash_addr) & ~(CFG_ENV_SECT_SIZE-1));
#if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE)
+ flash_offset = (uchar *)(((ulong)flash_addr) & (CFG_ENV_SECT_SIZE-1));
+ flash_sect_addr = (uchar *)(((ulong)flash_addr) & ~(CFG_ENV_SECT_SIZE-1));
+
/* copy old contents to temporary buffer */
- memcpy(env_buffer, flash_sect_addr, CFG_ENV_SECT_SIZE);
+ memcpy (env_buffer, flash_sect_addr, CFG_ENV_SECT_SIZE);
/* copy current environment to temporary buffer */
- memcpy((uchar *)((unsigned long)env_buffer + (unsigned long)flash_offset), env_ptr, CFG_ENV_SIZE);
+ memcpy ((uchar *)((unsigned long)env_buffer + (unsigned long)flash_offset),
+ env_ptr,
+ CFG_ENV_SIZE);
len = CFG_ENV_SECT_SIZE;
#else
+ flash_sect_addr = flash_addr;
len = CFG_ENV_SIZE;
# endif /* CFG_ENV_SECT_SIZE */
#include <board/hymod/cmd_fpga.h>
#endif
+#include <cmd_bedbug.h>
+
/*
* HELP command
*/
cmd_tbl_t cmd_tbl[] = {
CMD_TBL_GO
CMD_TBL_RUN
+
+ CMD_TBL_BOOTELF
+ CMD_TBL_BOOTVX
+
CMD_TBL_BOOTM
CMD_TBL_BOOTP
CMD_TBL_TFTPB
CMD_TBL_HELP
CMD_TBL_QUES
+ CMD_TBL_DIS
+ CMD_TBL_ASM
+ CMD_TBL_BREAK
+ CMD_TBL_STACK
+ CMD_TBL_CONTINUE
+ CMD_TBL_STEP
+ CMD_TBL_NEXT
+ CMD_TBL_RDUMP
+
/* the following entry terminates this table */
MK_CMD_TBL_ENTRY( NULL, 0, 0, 0, NULL, NULL, NULL )
};
START = start.o kgdb.o
OBJS = traps.o serial_smc.o serial_scc.o cpu.o cpu_init.o speed.o \
- interrupts.o ether_scc.o ether_fcc.o i2c.o commproc.o
+ interrupts.o ether_scc.o ether_fcc.o i2c.o commproc.o soft_i2c.o
all: .depend $(START) $(LIB)
#if defined(CONFIG_RPXSUPER)
#error "on RPX Super ethernet must be FCC3"
#endif
-
#elif (CONFIG_ETHER_INDEX == 2)
#define PROFF_ENET PROFF_FCC2
#if defined(CONFIG_RPXSUPER)
#error "on RPX Super ethernet must be FCC3"
#endif
+#if defined(CONFIG_TQM8260)
+/*
+ * Attention: this is board-specific
+ * - Rx-CLK is CLK13
+ * - Tx-CLK is CLK14
+ * - RAM for BD/Buffers is on the 60x Bus (see 28-13)
+ * - Enable Full Duplex in FSMR
+ */
+#define CMXFCR_MASK (CMXFCR_FC2|CMXFCR_RF2CS_MSK|CMXFCR_TF2CS_MSK)
+#define CMXFCR_VALUE (CMXFCR_RF2CS_CLK13|CMXFCR_TF2CS_CLK14)
+#define CPMFCR_RAMTYPE 0
+#define FCC_PSMR (FCC_PSMR_FDE|FCC_PSMR_LPB)
+#endif
#elif (CONFIG_ETHER_INDEX == 3)
CMXSCR_TS1CS_CLK12)
# endif
+# if defined(CONFIG_TQM8260)
+/*
+ * Attention: This is board specific
+ * - RX clk is CLK11
+ * - TX clk is CLK12
+ */
+# define CMXSCR_VALUE (CMXSCR_RS1CS_CLK11 |\
+ CMXSCR_TS1CS_CLK12)
+# endif
+
#elif (CONFIG_ETHER_INDEX == 2)
# define PROFF_ENET PROFF_SCC2
# define CPM_CR_ENET_PAGE CPM_CR_SCC2_PAGE
/* 24.21 - (4,5): connect SCC's tx and rx clocks, use NMSI for SCC */
immr->im_cpmux.cmx_uar = 0;
- immr->im_cpmux.cmx_scr = ( (immr->im_cpmux.cmx_fcr & ~CMXSCR_MASK) |
+ immr->im_cpmux.cmx_scr = ( (immr->im_cpmux.cmx_scr & ~CMXSCR_MASK) |
CMXSCR_VALUE);
--- /dev/null
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <ppcboot.h>
+#include <asm/cpm_8260.h>
+#include <i2c.h>
+
+#if defined(CONFIG_SOFT_I2C)
+
+/*-----------------------------------------------------------------------
+ * Set default values
+ */
+#ifndef CFG_I2C_SPEED
+#define CFG_I2C_SPEED 50000
+#endif
+
+#ifndef CFG_I2C_SLAVE
+#define CFG_I2C_SLAVE 0xFE
+#endif
+
+/*-----------------------------------------------------------------------
+ * Definitions
+ */
+
+/* TQM8260 Rev.100 has the clock and data pins swapped (!!!) on EEPROM
+ */
+#if CONFIG_TQM8260<=100
+#define PD_SCL 0x00010000 /* PD 15 */
+#define PD_SDA 0x00020000 /* PD 14 */
+#else
+#define PD_SCL 0x00020000 /* PD 14 */
+#define PD_SDA 0x00010000 /* PD 15 */
+#endif
+
+#define I2C_ACK 0 /* PD_SDA level to ack a byte */
+#define I2C_NOACK 1 /* PD_SDA level to noack a byte */
+
+#define SET_PD_BIT(bit) do { \
+ immr->im_ioport.iop_pdird |= bit;/* output */ \
+ immr->im_ioport.iop_pdatd |= bit;/* set 1 */ \
+ udelay (5); \
+ } while (0)
+
+#define RESET_PD_BIT(bit) do { \
+ immr->im_ioport.iop_pdird |= bit;/* output */ \
+ immr->im_ioport.iop_pdatd &= ~bit;/* set 0 */ \
+ udelay (5); \
+ } while (0)
+
+#define RESET_PD_BIT1(bit) do { \
+ immr->im_ioport.iop_pdird |= bit;/* output */ \
+ immr->im_ioport.iop_pdatd &= ~bit;/* set 0 */ \
+ udelay (1); \
+ } while (0)
+
+/*-----------------------------------------------------------------------
+ * Functions
+ */
+static void send_start (void);
+static void send_stop (void);
+static void send_ack (int);
+static void rcv_ack (void);
+static void send_data_1 (void);
+static void send_data_0 (void);
+static void read_addr (uchar addr);
+static void write_addr (uchar addr);
+static int read_bit (void);
+static uchar read_byte (int);
+static void write_byte (uchar byte);
+
+/*-----------------------------------------------------------------------
+ * START: High -> Low on SDA while SCL is High
+ */
+static void send_start (void)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+ SET_PD_BIT (PD_SCL);
+ RESET_PD_BIT (PD_SDA);
+}
+
+/*-----------------------------------------------------------------------
+ * STOP: Low -> High on SDA while SCL is High
+ */
+static void send_stop (void)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+ RESET_PD_BIT (PD_SDA);
+ SET_PD_BIT (PD_SCL);
+ SET_PD_BIT (PD_SDA);
+ udelay (5);
+}
+
+/*-----------------------------------------------------------------------
+ * ack should be I2C_ACK or I2C_NOACK
+ */
+static void send_ack (int ack)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+ RESET_PD_BIT (PD_SCL);
+ if (ack == I2C_ACK)
+ RESET_PD_BIT (PD_SDA);
+ else
+ SET_PD_BIT (PD_SDA);
+ SET_PD_BIT (PD_SCL);
+ udelay (5);
+ RESET_PD_BIT (PD_SCL);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void rcv_ack (void)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+ RESET_PD_BIT (PD_SCL);
+
+ immr->im_ioport.iop_pdird &= ~PD_SDA; /* input */
+ udelay (10);
+ while (immr->im_ioport.iop_pdatd & PD_SDA)
+ ;
+ udelay (5);
+ SET_PD_BIT (PD_SCL);
+ RESET_PD_BIT (PD_SCL);
+ SET_PD_BIT (PD_SDA);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void send_data_1 (void)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+ RESET_PD_BIT1(PD_SCL);
+ SET_PD_BIT (PD_SDA);
+ SET_PD_BIT (PD_SCL);
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void send_data_0 (void)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+ RESET_PD_BIT1(PD_SCL);
+ RESET_PD_BIT (PD_SDA);
+ SET_PD_BIT (PD_SCL);
+}
+
+
+/*-----------------------------------------------------------------------
+ */
+static void read_addr (uchar addr)
+{
+ int i;
+
+ addr = (addr << 1) | 0x01;
+
+ for (i=0; i<8; ++i) {
+ if (addr & 0x80) {
+ send_data_1 ();
+ } else {
+ send_data_0 ();
+ }
+ addr <<= 1;
+ }
+
+ rcv_ack ();
+}
+
+/*-----------------------------------------------------------------------
+ * addr & 0xF0 -> Device Identifier
+ * addr & 0x0E -> bank_num or device address << 1
+ * addr & 0x01 -> 1 = read, 0 = write
+ */
+static void write_addr (uchar addr)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+ addr <<= 1;
+
+ for (;;) {
+ uchar a = addr;
+ uint i;
+
+ send_start ();
+
+ for (i=0; i<8; ++i) {
+ if (a & 0x80) {
+ send_data_1 ();
+ } else {
+ send_data_0 ();
+ }
+ a <<= 1;
+ }
+
+ RESET_PD_BIT (PD_SCL);
+
+ immr->im_ioport.iop_pdird &= ~PD_SDA; /* input */
+ udelay (10);
+
+ i = immr->im_ioport.iop_pdatd;
+ udelay (5);
+ SET_PD_BIT (PD_SCL);
+ RESET_PD_BIT (PD_SCL);
+ SET_PD_BIT (PD_SDA);
+
+ if ((i & PD_SDA) == 0)
+ break;
+
+ send_stop();
+ }
+}
+
+/*-----------------------------------------------------------------------
+ */
+static int read_bit (void)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ int bit;
+
+ RESET_PD_BIT (PD_SCL);
+ SET_PD_BIT (PD_SCL);
+ bit = (immr->im_ioport.iop_pdatd & PD_SDA) ? 1 : 0;
+ return (bit);
+}
+
+/*-----------------------------------------------------------------------
+ * if last == 0, ACK the byte so can continue reading
+ * else NO ACK to end the read
+ */
+static uchar read_byte (int last)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ uchar byte = 0;
+ int i;
+
+ immr->im_ioport.iop_pdird &= ~PD_SDA; /* input */
+ udelay (5);
+
+ for (i=0; i<8; ++i) {
+ byte = (byte << 1) | read_bit();
+ }
+ send_ack (last ? I2C_NOACK : I2C_ACK);
+
+ return byte;
+}
+
+/*-----------------------------------------------------------------------
+ */
+static void write_byte (uchar byte)
+{
+ int i;
+ for (i=0; i<8; ++i) {
+ if (byte & 0x80) {
+ send_data_1 ();
+ } else {
+ send_data_0 ();
+ }
+ byte <<= 1;
+ }
+ rcv_ack();
+}
+
+/*=====================================================================*/
+/*=====================================================================*/
+
+/*-----------------------------------------------------------------------
+ * `speed' and `slaveaddr' not implemented
+ */
+void i2c_init (int speed, int slaveaddr)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+ immr->im_ioport.iop_ppard &= ~(PD_SCL | PD_SDA);/* GPIO */
+ immr->im_ioport.iop_podrd |= (PD_SCL | PD_SDA);/* Open Drain Output */
+
+ RESET_PD_BIT (PD_SCL);
+ RESET_PD_BIT (PD_SDA);
+ SET_PD_BIT (PD_SCL);
+ SET_PD_BIT (PD_SDA); /* stop condition */
+ udelay (25);
+}
+
+/*-----------------------------------------------------------------------
+ *
+ * addr: Array of address bytes; for instance, to read from
+ * EEPROM with 8 bit page addresses you have to write 2
+ * address bytes: the block number, and the block
+ * offset.
+ * alen: Number of address bytes in "addr"
+ * buffer: where to store the read data in
+ * len: number of bytes to read
+ * Warning: it is expected that the device is really
+ * capable of reading `len' sequential bytes; no
+ * checking is doen here
+ */
+void i2c_read (uchar *addr, int alen, uchar *buffer, int len)
+{
+ uchar *ap = addr;
+
+ write_addr (*ap);
+ while (--alen > 0) {
+ write_byte (*++ap);
+ }
+ send_start ();
+
+ read_addr (*addr);
+ while (len-- > 0) {
+ *buffer++ = read_byte (len==0);
+ }
+ send_stop ();
+}
+
+void i2c_write (uchar *addr, int alen, uchar *buffer, int len)
+{
+ uchar *ap = addr;
+
+ write_addr (*ap);
+ while (--alen > 0) {
+ write_byte (*++ap);
+ }
+
+ while (len-- > 0) {
+ write_byte (*buffer++);
+ }
+ send_stop ();
+}
+
+uchar i2c_reg_read (uchar i2c_addr, uchar reg)
+{
+ char addr[2];
+ char buf [1];
+
+ i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
+
+ addr[0] = i2c_addr;
+ addr[1] = reg;
+
+ i2c_read (addr, 2, buf, 1);
+
+ return (buf[0]);
+}
+
+void i2c_reg_write (uchar i2c_addr, uchar reg, uchar val)
+{
+ char addr[2];
+
+ i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE);
+
+ addr[0] = i2c_addr;
+ addr[1] = reg;
+
+ i2c_write (addr, 2, &val, 1);
+}
+
+#endif /* CONFIG_SOFT_I2C */
+/*-----------------------------------------------------------------------
+ */
/*
* Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
* Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
- * Copyright (C) 2000 Wolfgang Denk <wd@denx.de>
+ * Copyright (C) 2000, 2001 Wolfgang Denk <wd@denx.de>
*
* See file CREDITS for list of people who contributed to this
* project.
* boot ROM appears in memory, the memory controller setup when access
* boot ROM, etc. The HRCW is *extremely* important.
*
- * The HRCW is read from the bus during reset. One CPU on the bus will be
+ * The HRCW is read from the bus during reset. One CPU on the bus will
* be a hard reset configuration master, any others will be hard reset
* configuration slaves. The master reads eight HRCWs from flash during
* reset - the first it uses for itself, the other 7 it communicates to
START = start.o resetvec.o kgdb.o
OBJS = traps.o serial.o cpu.o cpu_init.o speed.o interrupts.o \
- 405gp_pci.o 405gp_enet.o miiphy.o i2c.o
+ 405gp_pci.o 405gp_enet.o miiphy.o i2c.o bedbug_405.o
all: .depend $(START) $(LIB)
--- /dev/null
+/*
+ * Bedbug Functions specific to the PPC405 chip
+ */
+
+#include <ppcboot.h>
+#include <command.h>
+#include <linux/ctype.h>
+
+#include <cmd_bedbug.h>
+#include <bedbug/bedbug.h>
+#include <bedbug/regs.h>
+#include <bedbug/ppc.h>
+
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG) && defined(CONFIG_PPC405)
+
+#define MAX_BREAK_POINTS 4
+
+extern CPU_DEBUG_CTX bug_ctx;
+
+void bedbug405_init __P((void));
+void bedbug405_do_break __P((cmd_tbl_t*,bd_t*,int,int,char*[]));
+void bedbug405_break_isr __P((struct pt_regs*));
+int bedbug405_find_empty __P((void));
+int bedbug405_set __P((int,unsigned long));
+int bedbug405_clear __P((int));
+
+\f
+/* ======================================================================
+ * Initialize the global bug_ctx structure for the IBM PPC405. Clear all
+ * of the breakpoints.
+ * ====================================================================== */
+
+void bedbug405_init( void )
+{
+ int i;
+ /* -------------------------------------------------- */
+
+ bug_ctx.hw_debug_enabled = 0;
+ bug_ctx.stopped = 0;
+ bug_ctx.current_bp = 0;
+ bug_ctx.regs = NULL;
+
+ bug_ctx.do_break = bedbug405_do_break;
+ bug_ctx.break_isr = bedbug405_break_isr;
+ bug_ctx.find_empty = bedbug405_find_empty;
+ bug_ctx.set = bedbug405_set;
+ bug_ctx.clear = bedbug405_clear;
+
+ for( i = 1; i <= MAX_BREAK_POINTS; ++i )
+ (*bug_ctx.clear)( i );
+
+ printf( " BEDBUG Ready\n" );
+ return;
+} /* bedbug_init_breakpoints */
+
+
+\f
+/* ======================================================================
+ * Set/clear/show one of the hardware breakpoints for the 405. The "off"
+ * string will disable a specific breakpoint. The "show" string will
+ * display the current breakpoints. Otherwise an address will set a
+ * breakpoint at that address. Setting a breakpoint uses the CPU-specific
+ * set routine which will assign a breakpoint number.
+ * ====================================================================== */
+
+void bedbug405_do_break (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc,
+ char *argv[])
+{
+ long addr; /* Address to break at */
+ int which_bp; /* Breakpoint number */
+ /* -------------------------------------------------- */
+
+ if (argc < 2)
+ {
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return;
+ }
+
+ /* Turn off a breakpoint */
+
+ if( strcmp( argv[ 1 ], "off" ) == 0 )
+ {
+ if( bug_ctx.hw_debug_enabled == 0 )
+ {
+ printf( "No breakpoints enabled\n" );
+ return;
+ }
+
+ which_bp = simple_strtoul( argv[ 2 ], NULL, 10 );
+
+ if( bug_ctx.clear )
+ (*bug_ctx.clear)( which_bp );
+
+ printf( "Breakpoint %d removed\n", which_bp );
+ return;
+ }
+
+ /* Show a list of breakpoints */
+
+ if( strcmp( argv[ 1 ], "show" ) == 0 )
+ {
+ for( which_bp = 1; which_bp <= MAX_BREAK_POINTS; ++which_bp )
+ {
+
+ switch( which_bp )
+ {
+ case 1: addr = GET_IAC1(); break;
+ case 2: addr = GET_IAC2(); break;
+ case 3: addr = GET_IAC3(); break;
+ case 4: addr = GET_IAC4(); break;
+ }
+
+ printf( "Breakpoint [%d]: ", which_bp );
+ if( addr == 0 )
+ printf( "NOT SET\n" );
+ else
+ disppc( (unsigned char *)addr, 0, 1, bedbug_puts, F_RADHEX );
+ }
+ return;
+ }
+
+ /* Set a breakpoint at the address */
+
+ if( !isdigit( argv[ 1 ][ 0 ]))
+ {
+ printf ("Usage:\n%s\n", cmdtp->usage);
+ return;
+ }
+
+ addr = simple_strtoul( argv[ 1 ], NULL, 16 ) & 0xfffffffc;
+
+ if(( bug_ctx.set ) && ( which_bp = (*bug_ctx.set)( 0, addr )) > 0 )
+ {
+ printf( "Breakpoint [%d]: ", which_bp );
+ disppc( (unsigned char *)addr, 0, 1, bedbug_puts, F_RADHEX );
+ }
+
+ bug_ctx.bd = bd;
+ return;
+} /* bedbug405_do_break */
+
+
+\f
+/* ======================================================================
+ * Handle a breakpoint. First determine which breakpoint was hit by
+ * looking at the DeBug Status Register (DBSR), clear the breakpoint
+ * and enter a mini main loop. Stay in the loop until the stopped flag
+ * in the debug context is cleared.
+ * ====================================================================== */
+
+void bedbug405_break_isr( struct pt_regs *regs )
+{
+ unsigned long dbsr_val; /* Value of the DBSR */
+ unsigned long addr; /* Address stopped at */
+ /* -------------------------------------------------- */
+
+ dbsr_val = GET_DBSR();
+
+ if( dbsr_val & DBSR_IA1 )
+ {
+ bug_ctx.current_bp = 1;
+ addr = GET_IAC1();
+ SET_DBSR( DBSR_IA1 ); /* Write a 1 to clear */
+ }
+ else if( dbsr_val & DBSR_IA2 )
+ {
+ bug_ctx.current_bp = 2;
+ addr = GET_IAC2();
+ SET_DBSR( DBSR_IA2 ); /* Write a 1 to clear */
+ }
+ else if( dbsr_val & DBSR_IA3 )
+ {
+ bug_ctx.current_bp = 3;
+ addr = GET_IAC3();
+ SET_DBSR( DBSR_IA3 ); /* Write a 1 to clear */
+ }
+ else if( dbsr_val & DBSR_IA4 )
+ {
+ bug_ctx.current_bp = 4;
+ addr = GET_IAC4();
+ SET_DBSR( DBSR_IA4 ); /* Write a 1 to clear */
+ }
+
+ bedbug_main_loop( addr, regs );
+ return;
+} /* bedbug405_break_isr */
+
+
+\f
+/* ======================================================================
+ * Look through all of the hardware breakpoints available to see if one
+ * is unused.
+ * ====================================================================== */
+
+int bedbug405_find_empty( void )
+{
+ /* -------------------------------------------------- */
+
+ if( GET_IAC1() == 0 )
+ return 1;
+
+ if( GET_IAC2() == 0 )
+ return 2;
+
+ if( GET_IAC3() == 0 )
+ return 3;
+
+ if( GET_IAC4() == 0 )
+ return 4;
+
+ return 0;
+} /* bedbug405_find_empty */
+
+
+\f
+/* ======================================================================
+ * Set a breakpoint. If 'which_bp' is zero then find an unused breakpoint
+ * number, otherwise reassign the given breakpoint. If hardware debugging
+ * is not enabled, then turn it on via the MSR and DBCR0. Set the break
+ * address in the appropriate IACx register and enable proper address
+ * beakpoint in DBCR0.
+ * ====================================================================== */
+
+int bedbug405_set( int which_bp, unsigned long addr )
+{
+ /* -------------------------------------------------- */
+
+ /* Only look if which_bp == 0, else use which_bp */
+ if(( bug_ctx.find_empty ) && ( !which_bp ) &&
+ ( which_bp = (*bug_ctx.find_empty)()) == 0 )
+ {
+ printf( "All breakpoints in use\n" );
+ return 0;
+ }
+
+ if( which_bp < 1 || which_bp > MAX_BREAK_POINTS )
+ {
+ printf( "Invalid break point # %d\n", which_bp );
+ return 0;
+ }
+
+ if( ! bug_ctx.hw_debug_enabled )
+ {
+ SET_MSR( GET_MSR() | 0x200 ); /* set MSR[ DE ] */
+ SET_DBCR0( GET_DBCR0() | DBCR0_IDM );
+ bug_ctx.hw_debug_enabled = 1;
+ }
+
+ switch( which_bp )
+ {
+ case 1:
+ SET_IAC1( addr );
+ SET_DBCR0( GET_DBCR0() | DBCR0_IA1 );
+ break;
+
+ case 2:
+ SET_IAC2( addr );
+ SET_DBCR0( GET_DBCR0() | DBCR0_IA2 );
+ break;
+
+ case 3:
+ SET_IAC3( addr );
+ SET_DBCR0( GET_DBCR0() | DBCR0_IA3 );
+ break;
+
+ case 4:
+ SET_IAC4( addr );
+ SET_DBCR0( GET_DBCR0() | DBCR0_IA4 );
+ break;
+ }
+
+ return which_bp;
+} /* bedbug405_set */
+
+
+\f
+/* ======================================================================
+ * Disable a specific breakoint by setting the appropriate IACx register
+ * to zero and claring the instruction address breakpoint in DBCR0.
+ * ====================================================================== */
+
+int bedbug405_clear( int which_bp )
+{
+ /* -------------------------------------------------- */
+
+ if( which_bp < 1 || which_bp > MAX_BREAK_POINTS )
+ {
+ printf( "Invalid break point # (%d)\n", which_bp );
+ return -1;
+ }
+
+ switch( which_bp )
+ {
+ case 1:
+ SET_IAC1( 0 );
+ SET_DBCR0( GET_DBCR0() & ~DBCR0_IA1 );
+ break;
+
+ case 2:
+ SET_IAC2( 0 );
+ SET_DBCR0( GET_DBCR0() & ~DBCR0_IA2 );
+ break;
+
+ case 3:
+ SET_IAC3( 0 );
+ SET_DBCR0( GET_DBCR0() & ~DBCR0_IA3 );
+ break;
+
+ case 4:
+ SET_IAC4( 0 );
+ SET_DBCR0( GET_DBCR0() & ~DBCR0_IA4 );
+ break;
+ }
+
+ return 0;
+} /* bedbug405_clear */
+
+
+/* ====================================================================== */
+#endif
+
STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException)
STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException)
+ CRIT_EXCEPTION(0x2000, DebugBreakpoint, DebugException )
.globl _end_of_vectors
_end_of_vectors:
- . = 0x2000
+ . = 0x2100
/*
* This code finishes saving the registers to the exception frame
SYNC
rfi
+crit_return:
+ mfmsr r29 /* Disable interrupts */
+ li r4,0
+ ori r4,r4,MSR_EE
+ andc r29,r29,r4
+ SYNC /* Some chip revs need this... */
+ mtmsr r29
+ SYNC
+ lwz r2,_CTR(r1)
+ lwz r0,_LINK(r1)
+ mtctr r2
+ mtlr r0
+ lwz r2,_XER(r1)
+ lwz r0,_CCR(r1)
+ mtspr XER,r2
+ mtcrf 0xFF,r0
+ REST_10GPRS(3, r1)
+ REST_10GPRS(13, r1)
+ REST_8GPRS(23, r1)
+ REST_GPR(31, r1)
+ lwz r2,_NIP(r1) /* Restore environment */
+ lwz r0,_MSR(r1)
+ mtspr 990,r2 /* SRR2 */
+ mtspr 991,r0 /* SRR3 */
+ lwz r0,GPR0(r1)
+ lwz r2,GPR2(r1)
+ lwz r1,GPR1(r1)
+ SYNC
+ rfci
+
/* Cache functions.
*/
invalidate_icache:
asm volatile("mttsr %0" : : "r" (val));
}
+static __inline__ unsigned long get_esr(void)
+{
+ unsigned long val;
+
+ asm volatile("mfesr %0" : "=r" (val) :);
+ return val;
+}
+
+#define ESR_MCI 0x80000000
+#define ESR_PIL 0x08000000
+#define ESR_PPR 0x04000000
+#define ESR_PTR 0x02000000
+#define ESR_DST 0x00800000
+#define ESR_DIZ 0x00400000
+#define ESR_U0F 0x00008000
+
+extern void do_bedbug_breakpoint(struct pt_regs *);
/*
* Trap & Exception support
void
ProgramCheckException(struct pt_regs *regs)
{
+ long esr_val;
+
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
show_regs(regs);
+
+ esr_val = get_esr();
+ if( esr_val & ESR_PIL )
+ printf( "** Illegal Instruction **\n" );
+ else if( esr_val & ESR_PPR )
+ printf( "** Privileged Instruction **\n" );
+ else if( esr_val & ESR_PTR )
+ printf( "** Trap Instruction **\n" );
+
print_backtrace((unsigned long *)regs->gpr[1]);
panic("Program Check Exception");
}
_exception(0, regs);
}
+void
+DebugException(struct pt_regs *regs)
+{
+ printf("Debugger trap at @ %lx\n", regs->nip );
+ show_regs(regs);
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+ do_bedbug_breakpoint( regs );
+#endif
+}
+
/* Probe an address by reading. If not present, return -1, otherwise
* return 0.
*/
--- /dev/null
+BEDBUG Support for PPCBoot
+--------------------------
+
+These changes implement the bedbug (emBEDded deBUGger) debugger in ppcboot.
+A specific implementation is made for the IBM405 processor but other flavors
+can be easily implemented.
+
+#####################
+### Modifications ###
+#####################
+
+./common/Makefile
+ Included cmd_bedbug.c and bedbug.c in the Makefile.
+
+./common/command.c
+ Added bedbug commands to command table.
+
+./common/board.c
+ Added call to initialize debugger on startup.
+
+./cpu/ppc4xx/Makefile
+ Added bedbug_405.c to the Makefile.
+
+./cpu/ppc4xx/start.S
+ Added code to handle the debug exception (0x2000) on the 405.
+ Also added code to handle critical exceptions since the debug
+ is treated as critical on the 405.
+
+./cpu/ppc4xx/traps.c
+ Added more detailed output for the program exception to tell
+ if it is an illegal instruction, privileged instruction or
+ a trap. Also added debug trap handler.
+
+./include/cmd_confdefs.h
+ Added definition of CFG_CMD_BEDBUG.
+
+./include/config_WALNUT405.h
+ Added CFG_CMD_BEDBUG to the CONFIG_COMMANDS for the WALNUT.
+
+./include/ppc_asm.tmpl
+ Added code to handle critical exceptions
+
+#################
+### New Stuff ###
+#################
+
+./include/bedbug/ppc.h
+./include/bedbug/regs.h
+./include/bedbug/bedbug.h
+./include/bedbug/elf.h
+./include/bedbug/tables.h
+./include/cmd_bedbug.h
+./common/cmd_bedbug.c
+./common/bedbug.c
+ Bedbug library includes code for assembling and disassembling
+ PowerPC instructions to/from memory as well as handling
+ hardware breakpoints and stepping through code. These
+ routines are common to all PowerPC processors.
+
+./cpu/ppc4xx/bedbug_405.c
+ IBM PPC405 specific debugger routines.
+
--- /dev/null
+/* $Id: bedbug.h,v 1.1 2001/05/31 22:12:27 wd Exp $ */
+
+#ifndef _BEDBUG_H
+#define _BEDBUG_H
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define _USE_PROTOTYPES
+
+#ifndef isblank
+#define isblank(c) isspace((int)(c))
+#endif
+
+#ifndef __P
+#if defined(_USE_PROTOTYPES) && (defined(__STDC__) || defined(__cplusplus))
+#define __P(protos) protos /* full-blown ANSI C */
+#else
+#define __P(protos) () /* traditional C preprocessor */
+#endif
+#endif
+
+#define assert( condition ) if( (condition) ) _exit(0)
+
+#endif /* _BEDBUG_H */
+
+
+/*
+ * Copyright (c) 2001 William L. Pitts
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
--- /dev/null
+/* $OpenBSD: exec_elf.h,v 1.27 2001/01/23 16:58:06 drahn Exp $ */
+/*
+ * Copyright (c) 1995, 1996 Erik Theisen. 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. 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.
+ */
+
+/*
+ * This is the ELF ABI header file
+ * formerly known as "elf_abi.h".
+ */
+
+#ifndef _SYS_EXEC_ELF_H_
+#define _SYS_EXEC_ELF_H_
+
+/* #include <machine/types.h> */
+/* #include <machine/exec.h> */
+
+typedef u_int8_t Elf_Byte;
+
+typedef u_int32_t Elf32_Addr; /* Unsigned program address */
+typedef u_int32_t Elf32_Off; /* Unsigned file offset */
+typedef int32_t Elf32_Sword; /* Signed large integer */
+typedef u_int32_t Elf32_Word; /* Unsigned large integer */
+typedef u_int16_t Elf32_Half; /* Unsigned medium integer */
+
+typedef u_int64_t Elf64_Addr;
+typedef u_int64_t Elf64_Off;
+typedef int64_t Elf64_Sword;
+typedef int32_t Elf64_Shalf;
+typedef u_int64_t Elf64_Word;
+typedef u_int32_t Elf64_Half;
+typedef u_int16_t Elf64_Quarter;
+
+/* e_ident[] identification indexes */
+#define EI_MAG0 0 /* file ID */
+#define EI_MAG1 1 /* file ID */
+#define EI_MAG2 2 /* file ID */
+#define EI_MAG3 3 /* file ID */
+#define EI_CLASS 4 /* file class */
+#define EI_DATA 5 /* data encoding */
+#define EI_VERSION 6 /* ELF header version */
+#define EI_PAD 7 /* start of pad bytes */
+#define EI_BRAND 8 /* brand */
+#define EI_NIDENT 16 /* Size of e_ident[] */
+
+/* e_ident[] magic number */
+#define ELFMAG0 0x7f /* e_ident[EI_MAG0] */
+#define ELFMAG1 'E' /* e_ident[EI_MAG1] */
+#define ELFMAG2 'L' /* e_ident[EI_MAG2] */
+#define ELFMAG3 'F' /* e_ident[EI_MAG3] */
+#define ELFMAG "\177ELF" /* magic */
+#define SELFMAG 4 /* size of magic */
+
+/* e_ident[] file class */
+#define ELFCLASSNONE 0 /* invalid */
+#define ELFCLASS32 1 /* 32-bit objs */
+#define ELFCLASS64 2 /* 64-bit objs */
+#define ELFCLASSNUM 3 /* number of classes */
+
+/* e_ident[] data encoding */
+#define ELFDATANONE 0 /* invalid */
+#define ELFDATA2LSB 1 /* Little-Endian */
+#define ELFDATA2MSB 2 /* Big-Endian */
+#define ELFDATANUM 3 /* number of data encode defines */
+
+/* e_ident */
+#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \
+ (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \
+ (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
+ (ehdr).e_ident[EI_MAG3] == ELFMAG3)
+
+/* ELF Header */
+typedef struct elfhdr{
+ unsigned char e_ident[EI_NIDENT]; /* ELF Identification */
+ Elf32_Half e_type; /* object file type */
+ Elf32_Half e_machine; /* machine */
+ Elf32_Word e_version; /* object file version */
+ Elf32_Addr e_entry; /* virtual entry point */
+ Elf32_Off e_phoff; /* program header table offset */
+ Elf32_Off e_shoff; /* section header table offset */
+ Elf32_Word e_flags; /* processor-specific flags */
+ Elf32_Half e_ehsize; /* ELF header size */
+ Elf32_Half e_phentsize; /* program header entry size */
+ Elf32_Half e_phnum; /* number of program header entries */
+ Elf32_Half e_shentsize; /* section header entry size */
+ Elf32_Half e_shnum; /* number of section header entries */
+ Elf32_Half e_shstrndx; /* section header table's "section
+ header string table" entry offset */
+} Elf32_Ehdr;
+
+typedef struct {
+ unsigned char e_ident[EI_NIDENT]; /* Id bytes */
+ Elf64_Quarter e_type; /* file type */
+ Elf64_Quarter e_machine; /* machine type */
+ Elf64_Half e_version; /* version number */
+ Elf64_Addr e_entry; /* entry point */
+ Elf64_Off e_phoff; /* Program hdr offset */
+ Elf64_Off e_shoff; /* Section hdr offset */
+ Elf64_Half e_flags; /* Processor flags */
+ Elf64_Quarter e_ehsize; /* sizeof ehdr */
+ Elf64_Quarter e_phentsize; /* Program header entry size */
+ Elf64_Quarter e_phnum; /* Number of program headers */
+ Elf64_Quarter e_shentsize; /* Section header entry size */
+ Elf64_Quarter e_shnum; /* Number of section headers */
+ Elf64_Quarter e_shstrndx; /* String table index */
+} Elf64_Ehdr;
+
+/* e_type */
+#define ET_NONE 0 /* No file type */
+#define ET_REL 1 /* relocatable file */
+#define ET_EXEC 2 /* executable file */
+#define ET_DYN 3 /* shared object file */
+#define ET_CORE 4 /* core file */
+#define ET_NUM 5 /* number of types */
+#define ET_LOPROC 0xff00 /* reserved range for processor */
+#define ET_HIPROC 0xffff /* specific e_type */
+
+/* e_machine */
+#define EM_NONE 0 /* No Machine */
+#define EM_M32 1 /* AT&T WE 32100 */
+#define EM_SPARC 2 /* SPARC */
+#define EM_386 3 /* Intel 80386 */
+#define EM_68K 4 /* Motorola 68000 */
+#define EM_88K 5 /* Motorola 88000 */
+#define EM_486 6 /* Intel 80486 - unused? */
+#define EM_860 7 /* Intel 80860 */
+#define EM_MIPS 8 /* MIPS R3000 Big-Endian only */
+
+/*
+ * Don't know if EM_MIPS_RS4_BE,
+ * EM_SPARC64, EM_PARISC,
+ * or EM_PPC are ABI compliant
+ */
+#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */
+#define EM_SPARC64 11 /* SPARC v9 64-bit unoffical */
+#define EM_PARISC 15 /* HPPA */
+#define EM_PPC 20 /* PowerPC */
+#define EM_ALPHA 41 /* DEC ALPHA */
+#define EM_ALPHA_EXP 0x9026 /* DEC ALPHA */
+#define EM_NUM 15 /* number of machine types */
+
+/* Version */
+#define EV_NONE 0 /* Invalid */
+#define EV_CURRENT 1 /* Current */
+#define EV_NUM 2 /* number of versions */
+
+/* Section Header */
+typedef struct {
+ Elf32_Word sh_name; /* name - index into section header
+ string table section */
+ Elf32_Word sh_type; /* type */
+ Elf32_Word sh_flags; /* flags */
+ Elf32_Addr sh_addr; /* address */
+ Elf32_Off sh_offset; /* file offset */
+ Elf32_Word sh_size; /* section size */
+ Elf32_Word sh_link; /* section header table index link */
+ Elf32_Word sh_info; /* extra information */
+ Elf32_Word sh_addralign; /* address alignment */
+ Elf32_Word sh_entsize; /* section entry size */
+} Elf32_Shdr;
+
+typedef struct {
+ Elf64_Half sh_name; /* section name */
+ Elf64_Half sh_type; /* section type */
+ Elf64_Word sh_flags; /* section flags */
+ Elf64_Addr sh_addr; /* virtual address */
+ Elf64_Off sh_offset; /* file offset */
+ Elf64_Word sh_size; /* section size */
+ Elf64_Half sh_link; /* link to another */
+ Elf64_Half sh_info; /* misc info */
+ Elf64_Word sh_addralign; /* memory alignment */
+ Elf64_Word sh_entsize; /* table entry size */
+} Elf64_Shdr;
+
+/* Special Section Indexes */
+#define SHN_UNDEF 0 /* undefined */
+#define SHN_LORESERVE 0xff00 /* lower bounds of reserved indexes */
+#define SHN_LOPROC 0xff00 /* reserved range for processor */
+#define SHN_HIPROC 0xff1f /* specific section indexes */
+#define SHN_ABS 0xfff1 /* absolute value */
+#define SHN_COMMON 0xfff2 /* common symbol */
+#define SHN_HIRESERVE 0xffff /* upper bounds of reserved indexes */
+
+/* sh_type */
+#define SHT_NULL 0 /* inactive */
+#define SHT_PROGBITS 1 /* program defined information */
+#define SHT_SYMTAB 2 /* symbol table section */
+#define SHT_STRTAB 3 /* string table section */
+#define SHT_RELA 4 /* relocation section with addends*/
+#define SHT_HASH 5 /* symbol hash table section */
+#define SHT_DYNAMIC 6 /* dynamic section */
+#define SHT_NOTE 7 /* note section */
+#define SHT_NOBITS 8 /* no space section */
+#define SHT_REL 9 /* relation section without addends */
+#define SHT_SHLIB 10 /* reserved - purpose unknown */
+#define SHT_DYNSYM 11 /* dynamic symbol table section */
+#define SHT_NUM 12 /* number of section types */
+#define SHT_LOPROC 0x70000000 /* reserved range for processor */
+#define SHT_HIPROC 0x7fffffff /* specific section header types */
+#define SHT_LOUSER 0x80000000 /* reserved range for application */
+#define SHT_HIUSER 0xffffffff /* specific indexes */
+
+/* Section names */
+#define ELF_BSS ".bss" /* uninitialized data */
+#define ELF_DATA ".data" /* initialized data */
+#define ELF_DEBUG ".debug" /* debug */
+#define ELF_DYNAMIC ".dynamic" /* dynamic linking information */
+#define ELF_DYNSTR ".dynstr" /* dynamic string table */
+#define ELF_DYNSYM ".dynsym" /* dynamic symbol table */
+#define ELF_FINI ".fini" /* termination code */
+#define ELF_GOT ".got" /* global offset table */
+#define ELF_HASH ".hash" /* symbol hash table */
+#define ELF_INIT ".init" /* initialization code */
+#define ELF_REL_DATA ".rel.data" /* relocation data */
+#define ELF_REL_FINI ".rel.fini" /* relocation termination code */
+#define ELF_REL_INIT ".rel.init" /* relocation initialization code */
+#define ELF_REL_DYN ".rel.dyn" /* relocaltion dynamic link info */
+#define ELF_REL_RODATA ".rel.rodata" /* relocation read-only data */
+#define ELF_REL_TEXT ".rel.text" /* relocation code */
+#define ELF_RODATA ".rodata" /* read-only data */
+#define ELF_SHSTRTAB ".shstrtab" /* section header string table */
+#define ELF_STRTAB ".strtab" /* string table */
+#define ELF_SYMTAB ".symtab" /* symbol table */
+#define ELF_TEXT ".text" /* code */
+
+
+/* Section Attribute Flags - sh_flags */
+#define SHF_WRITE 0x1 /* Writable */
+#define SHF_ALLOC 0x2 /* occupies memory */
+#define SHF_EXECINSTR 0x4 /* executable */
+#define SHF_MASKPROC 0xf0000000 /* reserved bits for processor */
+ /* specific section attributes */
+
+/* Symbol Table Entry */
+typedef struct elf32_sym {
+ Elf32_Word st_name; /* name - index into string table */
+ Elf32_Addr st_value; /* symbol value */
+ Elf32_Word st_size; /* symbol size */
+ unsigned char st_info; /* type and binding */
+ unsigned char st_other; /* 0 - no defined meaning */
+ Elf32_Half st_shndx; /* section header index */
+} Elf32_Sym;
+
+typedef struct {
+ Elf64_Half st_name; /* Symbol name index in str table */
+ Elf_Byte st_info; /* type / binding attrs */
+ Elf_Byte st_other; /* unused */
+ Elf64_Quarter st_shndx; /* section index of symbol */
+ Elf64_Word st_value; /* value of symbol */
+ Elf64_Word st_size; /* size of symbol */
+} Elf64_Sym;
+
+/* Symbol table index */
+#define STN_UNDEF 0 /* undefined */
+
+/* Extract symbol info - st_info */
+#define ELF32_ST_BIND(x) ((x) >> 4)
+#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf)
+#define ELF32_ST_INFO(b,t) (((b) << 4) + ((t) & 0xf))
+
+#define ELF64_ST_BIND(x) ((x) >> 4)
+#define ELF64_ST_TYPE(x) (((unsigned int) x) & 0xf)
+#define ELF64_ST_INFO(b,t) (((b) << 4) + ((t) & 0xf))
+
+/* Symbol Binding - ELF32_ST_BIND - st_info */
+#define STB_LOCAL 0 /* Local symbol */
+#define STB_GLOBAL 1 /* Global symbol */
+#define STB_WEAK 2 /* like global - lower precedence */
+#define STB_NUM 3 /* number of symbol bindings */
+#define STB_LOPROC 13 /* reserved range for processor */
+#define STB_HIPROC 15 /* specific symbol bindings */
+
+/* Symbol type - ELF32_ST_TYPE - st_info */
+#define STT_NOTYPE 0 /* not specified */
+#define STT_OBJECT 1 /* data object */
+#define STT_FUNC 2 /* function */
+#define STT_SECTION 3 /* section */
+#define STT_FILE 4 /* file */
+#define STT_NUM 5 /* number of symbol types */
+#define STT_LOPROC 13 /* reserved range for processor */
+#define STT_HIPROC 15 /* specific symbol types */
+
+/* Relocation entry with implicit addend */
+typedef struct
+{
+ Elf32_Addr r_offset; /* offset of relocation */
+ Elf32_Word r_info; /* symbol table index and type */
+} Elf32_Rel;
+
+/* Relocation entry with explicit addend */
+typedef struct
+{
+ Elf32_Addr r_offset; /* offset of relocation */
+ Elf32_Word r_info; /* symbol table index and type */
+ Elf32_Sword r_addend;
+} Elf32_Rela;
+
+/* Extract relocation info - r_info */
+#define ELF32_R_SYM(i) ((i) >> 8)
+#define ELF32_R_TYPE(i) ((unsigned char) (i))
+#define ELF32_R_INFO(s,t) (((s) << 8) + (unsigned char)(t))
+
+typedef struct {
+ Elf64_Word r_offset; /* where to do it */
+ Elf64_Word r_info; /* index & type of relocation */
+} Elf64_Rel;
+
+typedef struct {
+ Elf64_Word r_offset; /* where to do it */
+ Elf64_Word r_info; /* index & type of relocation */
+ Elf64_Word r_addend; /* adjustment value */
+} Elf64_Rela;
+
+#define ELF64_R_SYM(info) ((info) >> 32)
+#define ELF64_R_TYPE(info) ((info) & 0xFFFFFFFF)
+#define ELF64_R_INFO(s,t) (((s) << 32) + (u_int32_t)(t))
+
+/* Program Header */
+typedef struct {
+ Elf32_Word p_type; /* segment type */
+ Elf32_Off p_offset; /* segment offset */
+ Elf32_Addr p_vaddr; /* virtual address of segment */
+ Elf32_Addr p_paddr; /* physical address - ignored? */
+ Elf32_Word p_filesz; /* number of bytes in file for seg. */
+ Elf32_Word p_memsz; /* number of bytes in mem. for seg. */
+ Elf32_Word p_flags; /* flags */
+ Elf32_Word p_align; /* memory alignment */
+} Elf32_Phdr;
+
+typedef struct {
+ Elf64_Half p_type; /* entry type */
+ Elf64_Half p_flags; /* flags */
+ Elf64_Off p_offset; /* offset */
+ Elf64_Addr p_vaddr; /* virtual address */
+ Elf64_Addr p_paddr; /* physical address */
+ Elf64_Word p_filesz; /* file size */
+ Elf64_Word p_memsz; /* memory size */
+ Elf64_Word p_align; /* memory & file alignment */
+} Elf64_Phdr;
+
+/* Segment types - p_type */
+#define PT_NULL 0 /* unused */
+#define PT_LOAD 1 /* loadable segment */
+#define PT_DYNAMIC 2 /* dynamic linking section */
+#define PT_INTERP 3 /* the RTLD */
+#define PT_NOTE 4 /* auxiliary information */
+#define PT_SHLIB 5 /* reserved - purpose undefined */
+#define PT_PHDR 6 /* program header */
+#define PT_NUM 7 /* Number of segment types */
+#define PT_LOPROC 0x70000000 /* reserved range for processor */
+#define PT_HIPROC 0x7fffffff /* specific segment types */
+
+/* Segment flags - p_flags */
+#define PF_X 0x1 /* Executable */
+#define PF_W 0x2 /* Writable */
+#define PF_R 0x4 /* Readable */
+#define PF_MASKPROC 0xf0000000 /* reserved bits for processor */
+ /* specific segment flags */
+
+/* Dynamic structure */
+typedef struct {
+ Elf32_Sword d_tag; /* controls meaning of d_val */
+ union {
+ Elf32_Word d_val; /* Multiple meanings - see d_tag */
+ Elf32_Addr d_ptr; /* program virtual address */
+ } d_un;
+} Elf32_Dyn;
+
+extern Elf32_Dyn _DYNAMIC[]; /* XXX not 64-bit clean */
+
+typedef struct {
+ Elf64_Word d_tag; /* controls meaning of d_val */
+ union {
+ Elf64_Addr d_ptr;
+ Elf64_Word d_val;
+ } d_un;
+} Elf64_Dyn;
+
+/* Dynamic Array Tags - d_tag */
+#define DT_NULL 0 /* marks end of _DYNAMIC array */
+#define DT_NEEDED 1 /* string table offset of needed lib */
+#define DT_PLTRELSZ 2 /* size of relocation entries in PLT */
+#define DT_PLTGOT 3 /* address PLT/GOT */
+#define DT_HASH 4 /* address of symbol hash table */
+#define DT_STRTAB 5 /* address of string table */
+#define DT_SYMTAB 6 /* address of symbol table */
+#define DT_RELA 7 /* address of relocation table */
+#define DT_RELASZ 8 /* size of relocation table */
+#define DT_RELAENT 9 /* size of relocation entry */
+#define DT_STRSZ 10 /* size of string table */
+#define DT_SYMENT 11 /* size of symbol table entry */
+#define DT_INIT 12 /* address of initialization func. */
+#define DT_FINI 13 /* address of termination function */
+#define DT_SONAME 14 /* string table offset of shared obj */
+#define DT_RPATH 15 /* string table offset of library
+ search path */
+#define DT_SYMBOLIC 16 /* start sym search in shared obj. */
+#define DT_REL 17 /* address of rel. tbl. w addends */
+#define DT_RELSZ 18 /* size of DT_REL relocation table */
+#define DT_RELENT 19 /* size of DT_REL relocation entry */
+#define DT_PLTREL 20 /* PLT referenced relocation entry */
+#define DT_DEBUG 21 /* bugger */
+#define DT_TEXTREL 22 /* Allow rel. mod. to unwritable seg */
+#define DT_JMPREL 23 /* add. of PLT's relocation entries */
+#define DT_BIND_NOW 24 /* Bind now regardless of env setting */
+#define DT_NUM 25 /* Number used. */
+#define DT_LOPROC 0x70000000 /* reserved range for processor */
+#define DT_HIPROC 0x7fffffff /* specific dynamic array tags */
+
+/* Standard ELF hashing function */
+unsigned int elf_hash(const unsigned char *name);
+
+/*
+ * Note Definitions
+ */
+typedef struct {
+ Elf32_Word namesz;
+ Elf32_Word descsz;
+ Elf32_Word type;
+} Elf32_Note;
+
+typedef struct {
+ Elf64_Half namesz;
+ Elf64_Half descsz;
+ Elf64_Half type;
+} Elf64_Note;
+
+/*
+ * XXX - these _KERNEL items aren't part of the ABI!
+ */
+#if defined(_KERNEL) || defined(_DYN_LOADER)
+
+#define ELF32_NO_ADDR ((u_long) ~0) /* Indicates addr. not yet filled in */
+#define ELF_AUX_ENTRIES 8 /* Size of aux array passed to loader */
+
+typedef struct {
+ Elf32_Sword au_id; /* 32-bit id */
+ Elf32_Word au_v; /* 32-bit value */
+} Aux32Info;
+
+#define ELF64_NO_ADDR ((u_int64_t) ~0)/* Indicates addr. not yet filled in */
+#define ELF64_AUX_ENTRIES 8 /* Size of aux array passed to loader */
+
+typedef struct {
+ Elf64_Shalf au_id; /* 32-bit id */
+ Elf64_Word au_v; /* 64-bit id */
+} Aux64Info;
+
+enum AuxID {
+ AUX_null = 0,
+ AUX_ignore = 1,
+ AUX_execfd = 2,
+ AUX_phdr = 3, /* &phdr[0] */
+ AUX_phent = 4, /* sizeof(phdr[0]) */
+ AUX_phnum = 5, /* # phdr entries */
+ AUX_pagesz = 6, /* PAGESIZE */
+ AUX_base = 7, /* ld.so base addr */
+ AUX_flags = 8, /* processor flags */
+ AUX_entry = 9, /* a.out entry */
+ AUX_sun_uid = 2000, /* euid */
+ AUX_sun_ruid = 2001, /* ruid */
+ AUX_sun_gid = 2002, /* egid */
+ AUX_sun_rgid = 2003 /* rgid */
+};
+
+struct elf_args {
+ u_long arg_entry; /* progran entry point */
+ u_long arg_interp; /* Interpreter load address */
+ u_long arg_phaddr; /* program header address */
+ u_long arg_phentsize; /* Size of program header */
+ u_long arg_phnum; /* Number of program headers */
+ u_long arg_os; /* OS tag */
+};
+
+#endif
+
+#if !defined(ELFSIZE) && defined(ARCH_ELFSIZE)
+#define ELFSIZE ARCH_ELFSIZE
+#endif
+
+#if defined(ELFSIZE)
+#define CONCAT(x,y) __CONCAT(x,y)
+#define ELFNAME(x) CONCAT(elf,CONCAT(ELFSIZE,CONCAT(_,x)))
+#define ELFNAME2(x,y) CONCAT(x,CONCAT(_elf,CONCAT(ELFSIZE,CONCAT(_,y))))
+#define ELFNAMEEND(x) CONCAT(x,CONCAT(_elf,ELFSIZE))
+#define ELFDEFNNAME(x) CONCAT(ELF,CONCAT(ELFSIZE,CONCAT(_,x)))
+#endif
+
+#if defined(ELFSIZE) && (ELFSIZE == 32)
+#define Elf_Ehdr Elf32_Ehdr
+#define Elf_Phdr Elf32_Phdr
+#define Elf_Shdr Elf32_Shdr
+#define Elf_Sym Elf32_Sym
+#define Elf_Rel Elf32_Rel
+#define Elf_RelA Elf32_Rela
+#define Elf_Dyn Elf32_Dyn
+#define Elf_Word Elf32_Word
+#define Elf_Sword Elf32_Sword
+#define Elf_Addr Elf32_Addr
+#define Elf_Off Elf32_Off
+#define Elf_Nhdr Elf32_Nhdr
+
+#define ELF_R_SYM ELF32_R_SYM
+#define ELF_R_TYPE ELF32_R_TYPE
+#define ELF_R_INFO ELF32_R_INFO
+#define ELFCLASS ELFCLASS32
+
+#define ELF_ST_BIND ELF32_ST_BIND
+#define ELF_ST_TYPE ELF32_ST_TYPE
+#define ELF_ST_INFO ELF32_ST_INFO
+
+#define AuxInfo Aux32Info
+#elif defined(ELFSIZE) && (ELFSIZE == 64)
+#define Elf_Ehdr Elf64_Ehdr
+#define Elf_Phdr Elf64_Phdr
+#define Elf_Shdr Elf64_Shdr
+#define Elf_Sym Elf64_Sym
+#define Elf_Rel Elf64_Rel
+#define Elf_RelA Elf64_Rela
+#define Elf_Dyn Elf64_Dyn
+#define Elf_Word Elf64_Word
+#define Elf_Sword Elf64_Sword
+#define Elf_Addr Elf64_Addr
+#define Elf_Off Elf64_Off
+#define Elf_Nhdr Elf64_Nhdr
+
+#define ELF_R_SYM ELF64_R_SYM
+#define ELF_R_TYPE ELF64_R_TYPE
+#define ELF_R_INFO ELF64_R_INFO
+#define ELFCLASS ELFCLASS64
+
+#define ELF_ST_BIND ELF64_ST_BIND
+#define ELF_ST_TYPE ELF64_ST_TYPE
+#define ELF_ST_INFO ELF64_ST_INFO
+
+#define AuxInfo Aux64Info
+#endif
+
+#ifdef _KERNEL
+#ifdef _KERN_DO_ELF64
+int exec_elf64_makecmds __P((struct proc *, struct exec_package *));
+void *elf64_copyargs __P((struct exec_package *, struct ps_strings *,
+ void *, void *));
+int exec_elf64_fixup __P((struct proc *, struct exec_package *));
+char *elf64_check_brand __P((Elf64_Ehdr *));
+int elf64_os_pt_note __P((struct proc *, struct exec_package *, Elf64_Ehdr *,
+ char *, size_t, size_t));
+#endif
+#ifdef _KERN_DO_ELF
+int exec_elf_makecmds __P((struct proc *, struct exec_package *));
+void *elf_copyargs __P((struct exec_package *, struct ps_strings *,
+ void *, void *));
+int exec_elf_fixup __P((struct proc *, struct exec_package *));
+char *elf_check_brand __P((Elf32_Ehdr *));
+#endif
+
+#endif /* _KERNEL */
+
+#define ELF_TARG_VER 1 /* The ver for which this code is intended */
+
+#endif /* _SYS_EXEC_ELF_H_ */
--- /dev/null
+/* $Id: ppc.h,v 1.1 2001/05/31 22:12:27 wd Exp $ */
+
+#ifndef _PPC_H
+#define _PPC_H
+
+/*======================================================================
+ *
+ * OPERANDS
+ *
+ *======================================================================*/
+
+enum OP_FIELD {
+ O_AA = 1, O_BD, O_BI, O_BO, O_crbD, O_crbA, O_crbB, O_CRM, O_d, O_frC, O_frD,
+ O_frS, O_IMM, O_LI, O_LK, O_MB, O_ME, O_NB, O_OE, O_rA, O_rB, O_Rc, O_rD,
+ O_rS, O_SH, O_SIMM, O_SR, O_TO, O_UIMM, O_crfD, O_crfS, O_L, O_spr, O_tbr,
+ O_cr2 };
+
+struct operand {
+ enum OP_FIELD field; /* The operand identifier from the
+ enum above */
+
+ char * name; /* Symbolic name of this operand */
+
+ unsigned int bits; /* The number of bits used by this
+ operand */
+
+ unsigned int shift; /* How far to the right the operand
+ should be shifted so that it is
+ aligned at the beginning of the
+ word */
+
+ unsigned int hint; /* A bitwise-inclusive-OR of the
+ values shown below. These are used
+ tell the disassembler how to print
+ this operand */
+};
+
+/* Values for operand hint */
+#define OH_SILENT 0x01 /* dont print this operand */
+#define OH_ADDR 0x02 /* this operand is an address */
+#define OH_REG 0x04 /* this operand is a register */
+#define OH_SPR 0x08 /* this operand is an SPR */
+#define OH_TBR 0x10 /* this operand is a TBR */
+#define OH_OFFSET 0x20 /* this operand is an offset */
+#define OH_LITERAL 0x40 /* a literal string */
+
+\f
+/*======================================================================
+ *
+ * OPCODES
+ *
+ *======================================================================*/
+
+/* From the MPCxxx instruction set documentation, all instructions are
+ * 32 bits long and word aligned. Bits 0-5 always specify the primary
+ * opcode. Many instructions also have an extended opcode.
+ */
+
+#define GET_OPCD(i) (((unsigned long)(i) >> 26) & 0x3f)
+#define MAKE_OPCODE(i) ((((unsigned long)(i)) & 0x3f) << 26)
+
+/* The MPC860 User's Manual, Appendix D.4 contains the definitions of the
+ * instruction forms
+ */
+
+
+/*-------------------------------------------------
+ * I-Form Instructions:
+ * bX
+ *-------------------------------------------------
+ * OPCD | LI |AA|LK
+ *-------------------------------------------------*/
+
+#define I_OPCODE(i,aa,lk) (MAKE_OPCODE(i) | (((aa) & 0x1) << 1) | ((lk) & 0x1))
+#define I_MASK I_OPCODE(0x3f,0x1,0x1)
+
+
+/*-------------------------------------------------
+ * B-Form Instructions:
+ * bcX
+ *-------------------------------------------------
+ * OPCD | BO | BI | BD |AA|LK
+ *-------------------------------------------------*/
+
+#define B_OPCODE(i,aa,lk) (MAKE_OPCODE(i) | (((aa) & 0x1) << 1) | ((lk) & 0x1))
+#define B_MASK B_OPCODE(0x3f,0x1,0x1)
+
+
+/*-------------------------------------------------
+ * SC-Form Instructions:
+ * sc
+ *-------------------------------------------------
+ * OPCD | 00000 | 00000 | 00000000000000 |1|0
+ *-------------------------------------------------*/
+
+#define SC_OPCODE(i) (MAKE_OPCODE(i) | 0x2)
+#define SC_MASK SC_OPCODE(0x3f)
+
+
+/*-------------------------------------------------
+ * D-Form Instructions:
+ * addi addic addic. addis andi. andis. cmpi cmpli
+ * lbz lbzu lha lhau lhz lhzu lmw lwz lwzu mulli
+ * ori oris stb stbu sth sthu stmw stw stwu subfic
+ * twi xori xoris
+ *-------------------------------------------------
+ * OPCD | D | A | d
+ * OPCD | D | A | SIMM
+ * OPCD | S | A | d
+ * OPCD | S | A | UIMM
+ * OPCD |crfD|0|L| A | SIMM
+ * OPCD |crfD|0|L| A | UIMM
+ * OPCD | TO | A | SIMM
+ *-------------------------------------------------*/
+
+#define D_OPCODE(i) MAKE_OPCODE(i)
+#define D_MASK MAKE_OPCODE(0x3f)
+
+
+/*-------------------------------------------------
+ * DS-Form Instructions:
+ * (none supported by MPC860)
+ *-------------------------------------------------
+ * OPCD | D | A | ds |XO
+ * OPCD | S | A | ds |XO
+ *-------------------------------------------------*/
+
+#define DS_OPCODE(i,xo) (MAKE_OPCODE(i) | ((xo) & 0x3))
+#define DS_MASK DS_OPCODE(0x3f,0x1)
+
+
+/*---------------------------------------------------
+ * X-Form Instructions:
+ * andX andcX cmp cmpl cntlzwX dcbf dcbi dcbst dcbt
+ * dcbtst dcbz eciwx ecowx eieio eqvX extsbX extshX
+ * icbi lbzux lbxz lhaux lhax lhbrx lhzux lhxz lswi
+ * lswx lwarx lwbrx lwzux lwxz mcrfs mcrxr mfcr
+ * mfmsr mfsr mfsrin mtmsr mtsr mtsrin nandX norX
+ * orX orcX slwX srawX srawiX srwX stbux stbx
+ * sthbrx sthuxsthx stswi stswx stwbrx stwcx. stwux
+ * stwx sync tlbie tlbld tlbli tlbsync tw xorX
+ *---------------------------------------------------
+ * OPCD | D | A | B | XO |0
+ * OPCD | D | A | NB | XO |0
+ * OPCD | D | 00000 | B | XO |0
+ * OPCD | D | 00000 | 00000 | XO |0
+ * OPCD | D |0| SR | 00000 | XO |0
+ * OPCD | S | A | B | XO |Rc
+ * OPCD | S | A | B | XO |1
+ * OPCD | S | A | B | XO |0
+ * OPCD | S | A | NB | XO |0
+ * OPCD | S | A | 00000 | XO |Rc
+ * OPCD | S | 00000 | B | XO |0
+ * OPCD | S | 00000 | 00000 | XO |0
+ * OPCD | S |0| SR | 00000 | XO |0
+ * OPCD | S | A | SH | XO |Rc
+ * OPCD |crfD|0|L| A | SH | XO |0
+ * OPCD |crfD |00| A | B | XO |0
+ * OPCD |crfD |00|crfS |00| 00000 | XO |0
+ * OPCD |crfD |00| 00000 | 00000 | XO |0
+ * OPCD |crfD |00| 00000 | IMM |0| XO |Rc
+ * OPCD | TO | A | B | XO |0
+ * OPCD | D | 00000 | B | XO |Rc
+ * OPCD | D | 00000 | 00000 | XO |Rc
+ * OPCD | crbD | 00000 | 00000 | XO |Rc
+ * OPCD | 00000 | A | B | XO |0
+ * OPCD | 00000 | 00000 | B | XO |0
+ * OPCD | 00000 | 00000 | 00000 | XO |0
+ *---------------------------------------------------*/
+
+#define X_OPCODE(i,xo,rc) (MAKE_OPCODE(i) | (((xo) & 0x3ff) << 1) | \
+ ((rc) & 0x1))
+#define X_MASK X_OPCODE(0x3f,0x3ff,0x1)
+
+
+/*---------------------------------------------------
+ * XL-Form Instructions:
+ * bcctrX bclrX crand crandc creqv crnand crnor cror
+ * croc crxorisync mcrf rfi
+ *---------------------------------------------------
+ * OPCD | BO | BI | 00000 | XO |LK
+ * OPCD | crbD | crbA | crbB | XO |0
+ * OPCD |crfD |00|crfS |00| 00000 | XO |0
+ * OPCD | 00000 | 00000 | 00000 | XO |0
+ *---------------------------------------------------*/
+
+#define XL_OPCODE(i,xo,lk) (MAKE_OPCODE(i) | (((xo) & 0x3ff) << 1) | \
+ ((lk) & 0x1))
+#define XL_MASK XL_OPCODE(0x3f,0x3ff,0x1)
+
+
+/*---------------------------------------------------
+ * XFX-Form Instructions:
+ * mfspr mftb mtcrf mtspr
+ *---------------------------------------------------
+ * OPCD | D | spr | XO |0
+ * OPCD | D |0| CRM |0| XO |0
+ * OPCD | S | spr | XO |0
+ * OPCD | D | tbr | XO |0
+ *---------------------------------------------------*/
+
+#define XFX_OPCODE(i,xo,rc) (MAKE_OPCODE(i) | (((xo) & 0x3ff) << 1) | \
+ ((rc) & 0x1))
+#define XFX_MASK XFX_OPCODE(0x3f,0x3ff,0x1)
+
+
+/*---------------------------------------------------
+ * XFL-Form Instructions:
+ * (none supported by MPC860)
+ *---------------------------------------------------
+ * OPCD |0| FM |0| B | XO |0
+ *---------------------------------------------------*/
+
+#define XFL_OPCODE(i,xo,rc) (MAKE_OPCODE(i) | (((xo) & 0x3ff) << 1) | \
+ ((rc) & 0x1))
+#define XFL_MASK XFL_OPCODE(0x3f,0x3ff,0x1)
+
+
+/*---------------------------------------------------
+ * XS-Form Instructions:
+ * (none supported by MPC860)
+ *---------------------------------------------------
+ * OPCD | S | A | sh | XO |sh|LK
+ *---------------------------------------------------*/
+
+#define XS_OPCODE(i,xo,rc) (MAKE_OPCODE(i) | (((xo) & 0x1ff) << 2) | \
+ ((rc) & 0x1))
+#define XS_MASK XS_OPCODE(0x3f,0x1ff,0x1)
+
+
+/*---------------------------------------------------
+ * XO-Form Instructions:
+ * addX addcXaddeX addmeX addzeX divwX divwuX mulhwX
+ * mulhwuX mullwX negX subfX subfcX subfeX subfmeX
+ * subfzeX
+ *---------------------------------------------------
+ * OPCD | D | A | B |OE| XO |Rc
+ * OPCD | D | A | B |0 | XO |Rc
+ * OPCD | D | A | 00000 |OE| XO |Rc
+ *---------------------------------------------------*/
+
+#define XO_OPCODE(i,xo,oe,rc) (MAKE_OPCODE(i) | (((oe) & 0x1) << 10) | \
+ (((xo) & 0x1ff) << 1) | ((rc) & 0x1))
+#define XO_MASK XO_OPCODE(0x3f,0x1ff,0x1,0x1)
+
+
+/*---------------------------------------------------
+ * A-Form Instructions:
+ * (none supported by MPC860)
+ *---------------------------------------------------
+ * OPCD | D | A | B |00000| XO |Rc
+ * OPCD | D | A | B | C | XO |Rc
+ * OPCD | D | A | 00000 | C | XO |Rc
+ * OPCD | D | 00000 | B |00000| XO |Rc
+ *---------------------------------------------------*/
+
+#define A_OPCODE(i,xo,rc) (MAKE_OPCODE(i) | (((xo) & 0x1f) << 1) | \
+ ((rc) & 0x1))
+#define A_MASK A_OPCODE(0x3f,0x1f,0x1)
+
+
+/*---------------------------------------------------
+ * M-Form Instructions:
+ * rlwimiX rlwinmX rlwnmX
+ *---------------------------------------------------
+ * OPCD | S | A | SH | MB | ME |Rc
+ * OPCD | S | A | B | MB | ME |Rc
+ *---------------------------------------------------*/
+
+#define M_OPCODE(i,rc) (MAKE_OPCODE(i) | ((rc) & 0x1))
+#define M_MASK M_OPCODE(0x3f,0x1)
+
+
+/*---------------------------------------------------
+ * MD-Form Instructions:
+ * (none supported by MPC860)
+ *---------------------------------------------------
+ * OPCD | S | A | sh | mb | XO |sh|Rc
+ * OPCD | S | A | sh | me | XO |sh|Rc
+ *---------------------------------------------------*/
+
+#define MD_OPCODE(i,xo,rc) (MAKE_OPCODE(i) | (((xo) & 0x7) << 2) | \
+ ((rc) & 0x1))
+#define MD_MASK MD_OPCODE(0x3f,0x7,0x1)
+
+
+/*---------------------------------------------------
+ * MDS-Form Instructions:
+ * (none supported by MPC860)
+ *---------------------------------------------------
+ * OPCD | S | A | B | mb | XO |Rc
+ * OPCD | S | A | B | me | XO |Rc
+ *---------------------------------------------------*/
+
+#define MDS_OPCODE(i,xo,rc) (MAKE_OPCODE(i) | (((xo) & 0xf) << 1) | \
+ ((rc) & 0x1))
+#define MDS_MASK MDS_OPCODE(0x3f,0xf,0x1)
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE (!FALSE)
+#endif
+
+#define INSTRUCTION( memaddr ) ntohl(*(unsigned long *)(memaddr))
+
+#define MAX_OPERANDS 8
+
+struct ppc_ctx;
+
+struct opcode {
+ unsigned long opcode; /* The complete opcode as produced by
+ one of the XXX_OPCODE macros above */
+
+ unsigned long mask; /* The mask to use on an instruction
+ before comparing with the opcode
+ field to see if it matches */
+
+ enum OP_FIELD fields[MAX_OPERANDS];
+ /* An array defining the operands for
+ this opcode. The values of the
+ array are the operand identifiers */
+
+ int (*hfunc)(struct ppc_ctx *);
+ /* Address of a function to handle the given
+ mnemonic */
+
+ char * name; /* The symbolic name of this opcode */
+
+ unsigned int hint; /* A bitwise-inclusive-OR of the
+ values shown below. These are used
+ tell the disassembler how to print
+ some operands for this opcode */
+};
+
+/* values for opcode hints */
+#define H_RELATIVE 0x1 /* The address operand is relative */
+#define H_IMM_HIGH 0x2 /* [U|S]IMM field shifted high */
+#define H_RA0_IS_0 0x4 /* If rA = 0 then treat as literal 0 */
+
+struct ppc_ctx {
+ struct opcode * op;
+ unsigned long instr;
+ unsigned int flags;
+ int datalen;
+ char data[ 256 ];
+ char radix_fmt[ 8 ];
+ unsigned char * virtual;
+};
+
+
+/*======================================================================
+ *
+ * FUNCTIONS
+ *
+ *======================================================================*/
+
+/* Values for flags as passed to various ppc routines */
+#define F_RADOCTAL 0x1 /* output radix = unsigned octal */
+#define F_RADUDECIMAL 0x2 /* output radix = unsigned decimal */
+#define F_RADSDECIMAL 0x4 /* output radix = signed decimal */
+#define F_RADHEX 0x8 /* output radix = unsigned hex */
+#define F_SIMPLE 0x10 /* use simplified mnemonics */
+#define F_SYMBOL 0x20 /* use symbol lookups for addresses */
+#define F_INSTR 0x40 /* output the raw instruction */
+#define F_LOCALMEM 0x80 /* retrieve opcodes from local memory
+ rather than from the HMI */
+#define F_LINENO 0x100 /* show line number info if available */
+#define F_VALIDONLY 0x200 /* cache: valid entries only */
+
+/* Values for assembler error codes */
+#define E_ASM_BAD_OPCODE 1
+#define E_ASM_NUM_OPERANDS 2
+#define E_ASM_BAD_REGISTER 3
+#define E_ASM_BAD_SPR 4
+#define E_ASM_BAD_TBR 5
+
+extern int disppc __P((unsigned char *,unsigned char *,int,
+ int (*)(const char *), unsigned long));
+extern int print_source_line __P((char *,char *,int,
+ int (*pfunc)(const char *)));
+extern int find_next_address __P((unsigned char *,int,struct pt_regs *));
+extern int handle_bc __P((struct ppc_ctx *));
+extern unsigned long asmppc __P((unsigned long,char*,int*));
+extern char *asm_error_str __P((int));
+
+/*======================================================================
+ *
+ * GLOBAL VARIABLES
+ *
+ *======================================================================*/
+
+extern struct operand operands[];
+extern const unsigned int n_operands;
+extern struct opcode opcodes[];
+extern const unsigned int n_opcodes;
+
+#endif /* _PPC_H */
+
+
+/*
+ * Copyright (c) 2000 William L. Pitts and W. Gerald Hicks
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
--- /dev/null
+/* $Id: regs.h,v 1.1 2001/05/31 22:12:27 wd Exp $ */
+
+#ifndef _REGS_H
+#define _REGS_H
+
+/* Special Purpose Registers */
+
+#define SPR_CR -1
+#define SPR_MSR -2
+
+#define SPR_XER 1
+#define SPR_LR 8
+#define SPR_CTR 9
+#define SPR_DSISR 18
+#define SPR_DAR 19
+#define SPR_DEC 22
+#define SPR_SRR0 26
+#define SPR_SRR1 27
+#define SPR_EIE 80
+#define SPR_EID 81
+#define SPR_CMPA 144
+#define SPR_CMPB 145
+#define SPR_CMPC 146
+#define SPR_CMPD 147
+#define SPR_ICR 148
+#define SPR_DER 149
+#define SPR_COUNTA 150
+#define SPR_COUNTB 151
+#define SPR_CMPE 152
+#define SPR_CMPF 153
+#define SPR_CMPG 154
+#define SPR_CMPH 155
+#define SPR_LCTRL1 156
+#define SPR_LCTRL2 157
+#define SPR_ICTRL 158
+#define SPR_BAR 159
+#define SPR_USPRG0 256
+#define SPR_SPRG4_RO 260
+#define SPR_SPRG5_RO 261
+#define SPR_SPRG6_RO 262
+#define SPR_SPRG7_RO 263
+#define SPR_SPRG0 272
+#define SPR_SPRG1 273
+#define SPR_SPRG2 274
+#define SPR_SPRG3 275
+#define SPR_SPRG4 276
+#define SPR_SPRG5 277
+#define SPR_SPRG6 278
+#define SPR_SPRG7 279
+#define SPR_TBL 284
+#define SPR_TBU 285
+#define SPR_PVR 287
+#define SPR_IC_CST 560
+#define SPR_IC_ADR 561
+#define SPR_IC_DAT 562
+#define SPR_DC_CST 568
+#define SPR_DC_ADR 569
+#define SPR_DC_DAT 570
+#define SPR_DPDR 630
+#define SPR_IMMR 638
+#define SPR_MI_CTR 784
+#define SPR_MI_AP 786
+#define SPR_MI_EPN 787
+#define SPR_MI_TWC 789
+#define SPR_MI_RPN 790
+#define SPR_MD_CTR 792
+#define SPR_M_CASID 793
+#define SPR_MD_AP 794
+#define SPR_MD_EPN 795
+#define SPR_M_TWB 796
+#define SPR_MD_TWC 797
+#define SPR_MD_RPN 798
+#define SPR_M_TW 799
+#define SPR_MI_DBCAM 816
+#define SPR_MI_DBRAM0 817
+#define SPR_MI_DBRAM1 818
+#define SPR_MD_DBCAM 824
+#define SPR_MD_DBRAM0 825
+#define SPR_MD_DBRAM1 826
+#define SPR_ZPR 944
+#define SPR_PID 945
+#define SPR_CCR0 947
+#define SPR_IAC3 948
+#define SPR_IAC4 949
+#define SPR_DVC1 950
+#define SPR_DVC2 951
+#define SPR_SGR 953
+#define SPR_DCWR 954
+#define SPR_SLER 955
+#define SPR_SU0R 956
+#define SPR_DBCR1 957
+#define SPR_ICDBDR 979
+#define SPR_ESR 980
+#define SPR_DEAR 981
+#define SPR_EVPR 982
+#define SPR_TSR 984
+#define SPR_TCR 986
+#define SPR_PIT 987
+#define SPR_SRR2 990
+#define SPR_SRR3 991
+#define SPR_DBSR 1008
+#define SPR_DBCR0 1010
+#define SPR_IAC1 1012
+#define SPR_IAC2 1013
+#define SPR_DAC1 1014
+#define SPR_DAC2 1015
+#define SPR_DCCR 1018
+#define SPR_ICCR 1019
+
+/* Bits for the DBCR0 register */
+#define DBCR0_EDM 0x80000000
+#define DBCR0_IDM 0x40000000
+#define DBCR0_RST 0x30000000
+#define DBCR0_IC 0x08000000
+#define DBCR0_BT 0x04000000
+#define DBCR0_EDE 0x02000000
+#define DBCR0_TDE 0x01000000
+#define DBCR0_IA1 0x00800000
+#define DBCR0_IA2 0x00400000
+#define DBCR0_IA12 0x00200000
+#define DBCR0_IA12X 0x00100000
+#define DBCR0_IA3 0x00080000
+#define DBCR0_IA4 0x00040000
+#define DBCR0_IA34 0x00020000
+#define DBCR0_IA34X 0x00010000
+#define DBCR0_IA12T 0x00008000
+#define DBCR0_IA34T 0x00004000
+#define DBCR0_FT 0x00000001
+
+/* Bits for the DBCR1 register */
+#define DBCR1_D1R 0x80000000
+#define DBCR1_D2R 0x40000000
+#define DBCR1_D1W 0x20000000
+#define DBCR1_D2W 0x10000000
+#define DBCR1_D1S 0x0C000000
+#define DBCR1_D2S 0x03000000
+#define DBCR1_DA12 0x00800000
+#define DBCR1_DA12X 0x00400000
+#define DBCR1_DV1M 0x000C0000
+#define DBCR1_DV2M 0x00030000
+#define DBCR1_DV1BE 0x0000F000
+#define DBCR1_DV2BE 0x00000F00
+
+/* Bits for the DBSR register */
+#define DBSR_IC 0x80000000
+#define DBSR_BT 0x40000000
+#define DBSR_EDE 0x20000000
+#define DBSR_TIE 0x10000000
+#define DBSR_UDE 0x08000000
+#define DBSR_IA1 0x04000000
+#define DBSR_IA2 0x02000000
+#define DBSR_DR1 0x01000000
+#define DBSR_DW1 0x00800000
+#define DBSR_DR2 0x00400000
+#define DBSR_DW2 0x00200000
+#define DBSR_IDE 0x00100000
+#define DBSR_IA3 0x00080000
+#define DBSR_IA4 0x00040000
+#define DBSR_MRR 0x00000300
+
+struct spr_info {
+ int spr_val;
+ char spr_name[ 10 ];
+};
+
+extern struct spr_info spr_map[];
+extern const unsigned int n_sprs;
+
+
+#define SET_REGISTER( str, val ) \
+({ unsigned long __value = (val); \
+ asm volatile( str : : "r" (__value)); \
+ __value; })
+
+#define GET_REGISTER( str ) \
+({ unsigned long __value; \
+ asm volatile( str : "=r" (__value) : ); \
+ __value; })
+
+#define GET_CR() GET_REGISTER( "mfcr %0" )
+#define SET_CR(val) SET_REGISTER( "mtcr %0", val )
+#define GET_MSR() GET_REGISTER( "mfmsr %0" )
+#define SET_MSR(val) SET_REGISTER( "mtmsr %0", val )
+#define GET_XER() GET_REGISTER( "mfspr %0,1" )
+#define SET_XER(val) SET_REGISTER( "mtspr 1,%0", val )
+#define GET_LR() GET_REGISTER( "mfspr %0,8" )
+#define SET_LR(val) SET_REGISTER( "mtspr 8,%0", val )
+#define GET_CTR() GET_REGISTER( "mfspr %0,9" )
+#define SET_CTR(val) SET_REGISTER( "mtspr 9,%0", val )
+#define GET_DSISR() GET_REGISTER( "mfspr %0,18" )
+#define SET_DSISR(val) SET_REGISTER( "mtspr 18,%0", val )
+#define GET_DAR() GET_REGISTER( "mfspr %0,19" )
+#define SET_DAR(val) SET_REGISTER( "mtspr 19,%0", val )
+#define GET_DEC() GET_REGISTER( "mfspr %0,22" )
+#define SET_DEC(val) SET_REGISTER( "mtspr 22,%0", val )
+#define GET_SRR0() GET_REGISTER( "mfspr %0,26" )
+#define SET_SRR0(val) SET_REGISTER( "mtspr 26,%0", val )
+#define GET_SRR1() GET_REGISTER( "mfspr %0,27" )
+#define SET_SRR1(val) SET_REGISTER( "mtspr 27,%0", val )
+#define GET_EIE() GET_REGISTER( "mfspr %0,80" )
+#define SET_EIE(val) SET_REGISTER( "mtspr 80,%0", val )
+#define GET_EID() GET_REGISTER( "mfspr %0,81" )
+#define SET_EID(val) SET_REGISTER( "mtspr 81,%0", val )
+#define GET_CMPA() GET_REGISTER( "mfspr %0,144" )
+#define SET_CMPA(val) SET_REGISTER( "mtspr 144,%0", val )
+#define GET_CMPB() GET_REGISTER( "mfspr %0,145" )
+#define SET_CMPB(val) SET_REGISTER( "mtspr 145,%0", val )
+#define GET_CMPC() GET_REGISTER( "mfspr %0,146" )
+#define SET_CMPC(val) SET_REGISTER( "mtspr 146,%0", val )
+#define GET_CMPD() GET_REGISTER( "mfspr %0,147" )
+#define SET_CMPD(val) SET_REGISTER( "mtspr 147,%0", val )
+#define GET_ICR() GET_REGISTER( "mfspr %0,148" )
+#define SET_ICR(val) SET_REGISTER( "mtspr 148,%0", val )
+#define GET_DER() GET_REGISTER( "mfspr %0,149" )
+#define SET_DER(val) SET_REGISTER( "mtspr 149,%0", val )
+#define GET_COUNTA() GET_REGISTER( "mfspr %0,150" )
+#define SET_COUNTA(val) SET_REGISTER( "mtspr 150,%0", val )
+#define GET_COUNTB() GET_REGISTER( "mfspr %0,151" )
+#define SET_COUNTB(val) SET_REGISTER( "mtspr 151,%0", val )
+#define GET_CMPE() GET_REGISTER( "mfspr %0,152" )
+#define SET_CMPE(val) SET_REGISTER( "mtspr 152,%0", val )
+#define GET_CMPF() GET_REGISTER( "mfspr %0,153" )
+#define SET_CMPF(val) SET_REGISTER( "mtspr 153,%0", val )
+#define GET_CMPG() GET_REGISTER( "mfspr %0,154" )
+#define SET_CMPG(val) SET_REGISTER( "mtspr 154,%0", val )
+#define GET_CMPH() GET_REGISTER( "mfspr %0,155" )
+#define SET_CMPH(val) SET_REGISTER( "mtspr 155,%0", val )
+#define GET_LCTRL1() GET_REGISTER( "mfspr %0,156" )
+#define SET_LCTRL1(val) SET_REGISTER( "mtspr 156,%0", val )
+#define GET_LCTRL2() GET_REGISTER( "mfspr %0,157" )
+#define SET_LCTRL2(val) SET_REGISTER( "mtspr 157,%0", val )
+#define GET_ICTRL() GET_REGISTER( "mfspr %0,158" )
+#define SET_ICTRL(val) SET_REGISTER( "mtspr 158,%0", val )
+#define GET_BAR() GET_REGISTER( "mfspr %0,159" )
+#define SET_BAR(val) SET_REGISTER( "mtspr 159,%0", val )
+#define GET_USPRG0() GET_REGISTER( "mfspr %0,256" )
+#define SET_USPRG0(val) SET_REGISTER( "mtspr 256,%0", val )
+#define GET_SPRG4_RO() GET_REGISTER( "mfspr %0,260" )
+#define SET_SPRG4_RO(val) SET_REGISTER( "mtspr 260,%0", val )
+#define GET_SPRG5_RO() GET_REGISTER( "mfspr %0,261" )
+#define SET_SPRG5_RO(val) SET_REGISTER( "mtspr 261,%0", val )
+#define GET_SPRG6_RO() GET_REGISTER( "mfspr %0,262" )
+#define SET_SPRG6_RO(val) SET_REGISTER( "mtspr 262,%0", val )
+#define GET_SPRG7_RO() GET_REGISTER( "mfspr %0,263" )
+#define SET_SPRG7_RO(val) SET_REGISTER( "mtspr 263,%0", val )
+#define GET_SPRG0() GET_REGISTER( "mfspr %0,272" )
+#define SET_SPRG0(val) SET_REGISTER( "mtspr 272,%0", val )
+#define GET_SPRG1() GET_REGISTER( "mfspr %0,273" )
+#define SET_SPRG1(val) SET_REGISTER( "mtspr 273,%0", val )
+#define GET_SPRG2() GET_REGISTER( "mfspr %0,274" )
+#define SET_SPRG2(val) SET_REGISTER( "mtspr 274,%0", val )
+#define GET_SPRG3() GET_REGISTER( "mfspr %0,275" )
+#define SET_SPRG3(val) SET_REGISTER( "mtspr 275,%0", val )
+#define GET_SPRG4() GET_REGISTER( "mfspr %0,276" )
+#define SET_SPRG4(val) SET_REGISTER( "mtspr 276,%0", val )
+#define GET_SPRG5() GET_REGISTER( "mfspr %0,277" )
+#define SET_SPRG5(val) SET_REGISTER( "mtspr 277,%0", val )
+#define GET_SPRG6() GET_REGISTER( "mfspr %0,278" )
+#define SET_SPRG6(val) SET_REGISTER( "mtspr 278,%0", val )
+#define GET_SPRG7() GET_REGISTER( "mfspr %0,279" )
+#define SET_SPRG7(val) SET_REGISTER( "mtspr 279,%0", val )
+#define GET_TBL() GET_REGISTER( "mfspr %0,284" )
+#define SET_TBL(val) SET_REGISTER( "mtspr 284,%0", val )
+#define GET_TBU() GET_REGISTER( "mfspr %0,285" )
+#define SET_TBU(val) SET_REGISTER( "mtspr 285,%0", val )
+#define GET_PVR() GET_REGISTER( "mfspr %0,287" )
+#define SET_PVR(val) SET_REGISTER( "mtspr 287,%0", val )
+#define GET_IC_CST() GET_REGISTER( "mfspr %0,560" )
+#define SET_IC_CST(val) SET_REGISTER( "mtspr 560,%0", val )
+#define GET_IC_ADR() GET_REGISTER( "mfspr %0,561" )
+#define SET_IC_ADR(val) SET_REGISTER( "mtspr 561,%0", val )
+#define GET_IC_DAT() GET_REGISTER( "mfspr %0,562" )
+#define SET_IC_DAT(val) SET_REGISTER( "mtspr 562,%0", val )
+#define GET_DC_CST() GET_REGISTER( "mfspr %0,568" )
+#define SET_DC_CST(val) SET_REGISTER( "mtspr 568,%0", val )
+#define GET_DC_ADR() GET_REGISTER( "mfspr %0,569" )
+#define SET_DC_ADR(val) SET_REGISTER( "mtspr 569,%0", val )
+#define GET_DC_DAT() GET_REGISTER( "mfspr %0,570" )
+#define SET_DC_DAT(val) SET_REGISTER( "mtspr 570,%0", val )
+#define GET_DPDR() GET_REGISTER( "mfspr %0,630" )
+#define SET_DPDR(val) SET_REGISTER( "mtspr 630,%0", val )
+#define GET_IMMR() GET_REGISTER( "mfspr %0,638" )
+#define SET_IMMR(val) SET_REGISTER( "mtspr 638,%0", val )
+#define GET_MI_CTR() GET_REGISTER( "mfspr %0,784" )
+#define SET_MI_CTR(val) SET_REGISTER( "mtspr 784,%0", val )
+#define GET_MI_AP() GET_REGISTER( "mfspr %0,786" )
+#define SET_MI_AP(val) SET_REGISTER( "mtspr 786,%0", val )
+#define GET_MI_EPN() GET_REGISTER( "mfspr %0,787" )
+#define SET_MI_EPN(val) SET_REGISTER( "mtspr 787,%0", val )
+#define GET_MI_TWC() GET_REGISTER( "mfspr %0,789" )
+#define SET_MI_TWC(val) SET_REGISTER( "mtspr 789,%0", val )
+#define GET_MI_RPN() GET_REGISTER( "mfspr %0,790" )
+#define SET_MI_RPN(val) SET_REGISTER( "mtspr 790,%0", val )
+#define GET_MD_CTR() GET_REGISTER( "mfspr %0,792" )
+#define SET_MD_CTR(val) SET_REGISTER( "mtspr 792,%0", val )
+#define GET_M_CASID() GET_REGISTER( "mfspr %0,793" )
+#define SET_M_CASID(val) SET_REGISTER( "mtspr 793,%0", val )
+#define GET_MD_AP() GET_REGISTER( "mfspr %0,794" )
+#define SET_MD_AP(val) SET_REGISTER( "mtspr ,794%0", val )
+#define GET_MD_EPN() GET_REGISTER( "mfspr %0,795" )
+#define SET_MD_EPN(val) SET_REGISTER( "mtspr 795,%0", val )
+#define GET_M_TWB() GET_REGISTER( "mfspr %0,796" )
+#define SET_M_TWB(val) SET_REGISTER( "mtspr 796,%0", val )
+#define GET_MD_TWC() GET_REGISTER( "mfspr %0,797" )
+#define SET_MD_TWC(val) SET_REGISTER( "mtspr 797,%0", val )
+#define GET_MD_RPN() GET_REGISTER( "mfspr %0,798" )
+#define SET_MD_RPN(val) SET_REGISTER( "mtspr 798,%0", val )
+#define GET_M_TW() GET_REGISTER( "mfspr %0,799" )
+#define SET_M_TW(val) SET_REGISTER( "mtspr 799,%0", val )
+#define GET_MI_DBCAM() GET_REGISTER( "mfspr %0,816" )
+#define SET_MI_DBCAM(val) SET_REGISTER( "mtspr 816,%0", val )
+#define GET_MI_DBRAM0() GET_REGISTER( "mfspr %0,817" )
+#define SET_MI_DBRAM0(val) SET_REGISTER( "mtspr 817,%0", val )
+#define GET_MI_DBRAM1() GET_REGISTER( "mfspr %0,818" )
+#define SET_MI_DBRAM1(val) SET_REGISTER( "mtspr 818,%0", val )
+#define GET_MD_DBCAM() GET_REGISTER( "mfspr %0,824" )
+#define SET_MD_DBCA(val) SET_REGISTER( "mtspr 824,%0", val )
+#define GET_MD_DBRAM0() GET_REGISTER( "mfspr %0,825" )
+#define SET_MD_DBRAM0(val) SET_REGISTER( "mtspr 825,%0", val )
+#define GET_MD_DBRAM1() GET_REGISTER( "mfspr %0,826" )
+#define SET_MD_DBRAM1(val) SET_REGISTER( "mtspr 826,%0", val )
+#define GET_ZPR() GET_REGISTER( "mfspr %0,944" )
+#define SET_ZPR(val) SET_REGISTER( "mtspr 944,%0", val )
+#define GET_PID() GET_REGISTER( "mfspr %0,945" )
+#define SET_PID(val) SET_REGISTER( "mtspr 945,%0", val )
+#define GET_CCR0() GET_REGISTER( "mfspr %0,947" )
+#define SET_CCR0(val) SET_REGISTER( "mtspr 947,%0", val )
+#define GET_IAC3() GET_REGISTER( "mfspr %0,948" )
+#define SET_IAC3(val) SET_REGISTER( "mtspr 948,%0", val )
+#define GET_IAC4() GET_REGISTER( "mfspr %0,949" )
+#define SET_IAC4(val) SET_REGISTER( "mtspr 949,%0", val )
+#define GET_DVC1() GET_REGISTER( "mfspr %0,950" )
+#define SET_DVC1(val) SET_REGISTER( "mtspr 950,%0", val )
+#define GET_DVC2() GET_REGISTER( "mfspr %0,951" )
+#define SET_DVC2(val) SET_REGISTER( "mtspr 951,%0", val )
+#define GET_SGR() GET_REGISTER( "mfspr %0,953" )
+#define SET_SGR(val) SET_REGISTER( "mtspr 953,%0", val )
+#define GET_DCWR() GET_REGISTER( "mfspr %0,954" )
+#define SET_DCWR(val) SET_REGISTER( "mtspr 954,%0", val )
+#define GET_SLER() GET_REGISTER( "mfspr %0,955" )
+#define SET_SLER(val) SET_REGISTER( "mtspr 955,%0", val )
+#define GET_SU0R() GET_REGISTER( "mfspr %0,956" )
+#define SET_SU0R(val) SET_REGISTER( "mtspr 956,%0", val )
+#define GET_DBCR1() GET_REGISTER( "mfspr %0,957" )
+#define SET_DBCR1(val) SET_REGISTER( "mtspr 957,%0", val )
+#define GET_ICDBDR() GET_REGISTER( "mfspr %0,979" )
+#define SET_ICDBDR(val) SET_REGISTER( "mtspr 979,%0", val )
+#define GET_ESR() GET_REGISTER( "mfspr %0,980" )
+#define SET_ESR(val) SET_REGISTER( "mtspr 980,%0", val )
+#define GET_DEAR() GET_REGISTER( "mfspr %0,981" )
+#define SET_DEAR(val) SET_REGISTER( "mtspr 981,%0", val )
+#define GET_EVPR() GET_REGISTER( "mfspr %0,982" )
+#define SET_EVPR(val) SET_REGISTER( "mtspr 982,%0", val )
+#define GET_TSR() GET_REGISTER( "mfspr %0,984" )
+#define SET_TSR(val) SET_REGISTER( "mtspr 984,%0", val )
+#define GET_TCR() GET_REGISTER( "mfspr %0,986" )
+#define SET_TCR(val) SET_REGISTER( "mtspr 986,%0", val )
+#define GET_PIT() GET_REGISTER( "mfspr %0,987" )
+#define SET_PIT(val) SET_REGISTER( "mtspr 987,%0", val )
+#define GET_SRR2() GET_REGISTER( "mfspr %0,990" )
+#define SET_SRR2(val) SET_REGISTER( "mtspr 990,%0", val )
+#define GET_SRR3() GET_REGISTER( "mfspr %0,991" )
+#define SET_SRR3(val) SET_REGISTER( "mtspr 991,%0", val )
+#define GET_DBSR() GET_REGISTER( "mfspr %0,1008" )
+#define SET_DBSR(val) SET_REGISTER( "mtspr 1008,%0", val )
+#define GET_DBCR0() GET_REGISTER( "mfspr %0,1010" )
+#define SET_DBCR0(val) SET_REGISTER( "mtspr 1010,%0", val )
+#define GET_IAC1() GET_REGISTER( "mfspr %0,1012" )
+#define SET_IAC1(val) SET_REGISTER( "mtspr 1012,%0", val )
+#define GET_IAC2() GET_REGISTER( "mfspr %0,1013" )
+#define SET_IAC2(val) SET_REGISTER( "mtspr 1013,%0", val )
+#define GET_DAC1() GET_REGISTER( "mfspr %0,1014" )
+#define SET_DAC1(val) SET_REGISTER( "mtspr 1014,%0", val )
+#define GET_DAC2() GET_REGISTER( "mfspr %0,1015" )
+#define SET_DAC2(val) SET_REGISTER( "mtspr 1015,%0", val )
+#define GET_DCCR() GET_REGISTER( "mfspr %0,1018" )
+#define SET_DCCR(val) SET_REGISTER( "mtspr 1018,%0", val )
+#define GET_ICCR() GET_REGISTER( "mfspr %0,1019" )
+#define SET_ICCR(val) SET_REGISTER( "mtspr 1019,%0", val )
+
+#endif /* _REGS_H */
+
+
+/*
+ * Copyright (c) 2000 William L. Pitts and W. Gerald Hicks
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
--- /dev/null
+/* $Id: tables.h,v 1.1 2001/05/31 22:12:27 wd Exp $ */
+
+#ifndef TABLES_H
+#define TABLES_H
+
+/* This is only included by common/bedbug.c, and depends on the following
+ * files to already be included
+ * ppcboot.h
+ * bedbug/bedbug.h
+ * bedbug/ppc.h
+ * bedbug/regs.h
+ */
+
+struct operand operands[] = {
+ /*Field Name Bits Shift Hint Position */
+ /*----- ------ ----- ----- ---- ------------ */
+ { O_AA, "O_AA", 1, 1, OH_SILENT }, /* 30 */
+ { O_BD, "O_BD", 14, 2, OH_ADDR }, /* 16-29 */
+ { O_BI, "O_BI", 5, 16, 0 }, /* 11-15 */
+ { O_BO, "O_BO", 5, 21, 0 }, /* 6-10 */
+ { O_crbD, "O_crbD", 5, 21, 0 }, /* 6-10 */
+ { O_crbA, "O_crbA", 5, 16, 0 }, /* 11-15 */
+ { O_crbB, "O_crbB", 5, 11, 0 }, /* 16-20 */
+ { O_CRM, "O_CRM", 8, 12, 0 }, /* 12-19 */
+ { O_d, "O_d", 15, 0, OH_OFFSET }, /* 16-31 */
+ { O_frC, "O_frC", 5, 6, 0 }, /* 21-25 */
+ { O_frD, "O_frD", 5, 21, 0 }, /* 6-10 */
+ { O_frS, "O_frS", 5, 21, 0 }, /* 6-10 */
+ { O_IMM, "O_IMM", 4, 12, 0 }, /* 16-19 */
+ { O_LI, "O_LI", 24, 2, OH_ADDR }, /* 6-29 */
+ { O_LK, "O_LK", 1, 0, OH_SILENT }, /* 31 */
+ { O_MB, "O_MB", 5, 6, 0 }, /* 21-25 */
+ { O_ME, "O_ME", 5, 1, 0 }, /* 26-30 */
+ { O_NB, "O_NB", 5, 11, 0 }, /* 16-20 */
+ { O_OE, "O_OE", 1, 10, OH_SILENT }, /* 21 */
+ { O_rA, "O_rA", 5, 16, OH_REG }, /* 11-15 */
+ { O_rB, "O_rB", 5, 11, OH_REG }, /* 16-20 */
+ { O_Rc, "O_Rc", 1, 0, OH_SILENT }, /* 31 */
+ { O_rD, "O_rD", 5, 21, OH_REG }, /* 6-10 */
+ { O_rS, "O_rS", 5, 21, OH_REG }, /* 6-10 */
+ { O_SH, "O_SH", 5, 11, 0 }, /* 16-20 */
+ { O_SIMM, "O_SIMM", 16, 0, 0 }, /* 16-31 */
+ { O_SR, "O_SR", 4, 16, 0 }, /* 12-15 */
+ { O_TO, "O_TO", 5, 21, 0 }, /* 6-10 */
+ { O_UIMM, "O_UIMM", 16, 0, 0 }, /* 16-31 */
+ { O_crfD, "O_crfD", 3, 23, 0 }, /* 6- 8 */
+ { O_crfS, "O_crfS", 3, 18, 0 }, /* 11-13 */
+ { O_L, "O_L", 1, 21, 0 }, /* 10 */
+ { O_spr, "O_spr", 10, 11, OH_SPR }, /* 11-20 */
+ { O_tbr, "O_tbr", 10, 11, OH_TBR }, /* 11-20 */
+ { O_cr2, "O_cr2", 0, 0, OH_LITERAL }, /* "cr2" */
+};
+
+const unsigned int n_operands = sizeof(operands) / sizeof(operands[0]);
+
+/* A note about the fields array in the opcodes structure:
+ The operands are listed in the order they appear in the output.
+
+ This table is arranged in numeric order of the opcode. Note that some
+ opcodes have defined bits in odd places so not all forms of a command
+ will be in the same place. This is done so that a binary search can be
+ done to find the opcodes. Note that table D.2 in the MPC860 User's
+ Manual "Instructions Sorted by Opcode" does not account for these
+ bit locations */
+
+struct opcode opcodes[] = {
+ { D_OPCODE(3), D_MASK, {O_TO, O_rA, O_SIMM, 0},
+ 0, "twi", 0 },
+ { D_OPCODE(7), D_MASK, {O_rD, O_rA, O_SIMM, 0},
+ 0, "mulli", 0 },
+ { D_OPCODE(8), D_MASK, {O_rD, O_rA, O_SIMM, 0},
+ 0, "subfic", 0 },
+ { D_OPCODE(10), D_MASK, {O_crfD, O_L, O_rA, O_UIMM, 0},
+ 0, "cmpli", 0 },
+ { D_OPCODE(11), D_MASK, {O_crfD, O_L, O_rA, O_SIMM, 0},
+ 0, "cmpi", 0 },
+ { D_OPCODE(12), D_MASK, {O_rD, O_rA, O_SIMM, 0},
+ 0, "addic", 0 },
+ { D_OPCODE(13), D_MASK, {O_rD, O_rA, O_SIMM, 0},
+ 0, "addic.", 0 },
+ { D_OPCODE(14), D_MASK, {O_rD, O_rA, O_SIMM, 0},
+ 0, "addi", H_RA0_IS_0 },
+ { D_OPCODE(15), D_MASK, {O_rD, O_rA, O_SIMM, 0},
+ 0, "addis", H_RA0_IS_0|H_IMM_HIGH },
+ { B_OPCODE(16,0,0), B_MASK, {O_BO, O_BI, O_BD, O_AA, O_LK, 0},
+ handle_bc, "bc", H_RELATIVE },
+ { B_OPCODE(16,0,1), B_MASK, {O_BO, O_BI, O_BD, O_AA, O_LK, 0},
+ 0, "bcl", H_RELATIVE },
+ { B_OPCODE(16,1,0), B_MASK, {O_BO, O_BI, O_BD, O_AA, O_LK, 0},
+ 0, "bca", 0 },
+ { B_OPCODE(16,1,1), B_MASK, {O_BO, O_BI, O_BD, O_AA, O_LK, 0},
+ 0, "bcla", 0 },
+ { SC_OPCODE(17), SC_MASK, {0},
+ 0, "sc", 0 },
+ { I_OPCODE(18,0,0), I_MASK, {O_LI, O_AA, O_LK, 0},
+ 0, "b", H_RELATIVE },
+ { I_OPCODE(18,0,1), I_MASK, {O_LI, O_AA, O_LK, 0},
+ 0, "bl", H_RELATIVE },
+ { I_OPCODE(18,1,0), I_MASK, {O_LI, O_AA, O_LK, 0},
+ 0, "ba", 0 },
+ { I_OPCODE(18,1,1), I_MASK, {O_LI, O_AA, O_LK, 0},
+ 0, "bla", 0 },
+ { XL_OPCODE(19,0,0), XL_MASK, {O_crfD, O_crfS},
+ 0, "mcrf", 0 },
+ { XL_OPCODE(19,16,0), XL_MASK, {O_BO, O_BI, O_LK, 0},
+ 0, "bclr", 0 },
+ { XL_OPCODE(19,16,1), XL_MASK, {O_BO, O_BI, O_LK, 0},
+ 0, "bclrl", 0 },
+ { XL_OPCODE(19,33,0), XL_MASK, {O_crbD, O_crbA, O_crbB, 0},
+ 0, "crnor", 0 },
+ { XL_OPCODE(19,50,0), XL_MASK, {0},
+ 0, "rfi", 0 },
+ { XL_OPCODE(19,129,0), XL_MASK, {O_crbD, O_crbA, O_crbB, 0},
+ 0, "crandc", 0 },
+ { XL_OPCODE(19,150,0), XL_MASK, {0},
+ 0, "isync", 0 },
+ { XL_OPCODE(19,193,0), XL_MASK, {O_crbD, O_crbA, O_crbB, 0},
+ 0, "crxor", 0 },
+ { XL_OPCODE(19,225,0), XL_MASK, {O_crbD, O_crbA, O_crbB, 0},
+ 0, "crnand", 0 },
+ { XL_OPCODE(19,257,0), XL_MASK, {O_crbD, O_crbA, O_crbB, 0},
+ 0, "crand", 0 },
+ { XL_OPCODE(19,289,0), XL_MASK, {O_crbD, O_crbA, O_crbB, 0},
+ 0, "creqv", 0 },
+ { XL_OPCODE(19,417,0), XL_MASK, {O_crbD, O_crbA, O_crbB, 0},
+ 0, "crorc", 0 },
+ { XL_OPCODE(19,449,0), XL_MASK, {O_crbD, O_crbA, O_crbB, 0},
+ 0, "cror", 0 },
+ { XL_OPCODE(19,528,0), XL_MASK, {O_BO, O_BI, O_LK, 0},
+ 0, "bcctr", 0 },
+ { XL_OPCODE(19,528,1), XL_MASK, {O_BO, O_BI, O_LK, 0},
+ 0, "bcctrl", 0 },
+ { M_OPCODE(20,0), M_MASK, {O_rA, O_rS, O_SH, O_MB, O_ME, O_Rc, 0},
+ 0, "rlwimi", 0 },
+ { M_OPCODE(20,1), M_MASK, {O_rA, O_rS, O_SH, O_MB, O_ME, O_Rc, 0},
+ 0, "rlwimi.", 0 },
+ { M_OPCODE(21,0), M_MASK, {O_rA, O_rS, O_SH, O_MB, O_ME, O_Rc, 0},
+ 0, "rlwinm", 0 },
+ { M_OPCODE(21,1), M_MASK, {O_rA, O_rS, O_SH, O_MB, O_ME, O_Rc, 0},
+ 0, "rlwinm.", 0 },
+ { M_OPCODE(23,0), M_MASK, {O_rA, O_rS, O_rB, O_MB, O_ME, O_Rc, 0},
+ 0, "rlwnm", 0 },
+ { M_OPCODE(23,1), M_MASK, {O_rA, O_rS, O_rB, O_MB, O_ME, O_Rc, 0},
+ 0, "rlwnm.", 0 },
+ { D_OPCODE(24), D_MASK, {O_rA, O_rS, O_UIMM, 0},
+ 0, "ori", 0 },
+ { D_OPCODE(25), D_MASK, {O_rA, O_rS, O_UIMM, 0},
+ 0, "oris", H_IMM_HIGH },
+ { D_OPCODE(26), D_MASK, {O_rA, O_rS, O_UIMM, 0},
+ 0, "xori", 0 },
+ { D_OPCODE(27), D_MASK, {O_rA, O_rS, O_UIMM, 0},
+ 0, "xoris", H_IMM_HIGH },
+ { D_OPCODE(28), D_MASK, {O_rA, O_rS, O_UIMM, 0},
+ 0, "andi.", 0 },
+ { D_OPCODE(29), D_MASK, {O_rA, O_rS, O_UIMM, 0},
+ 0, "andis.", H_IMM_HIGH },
+ { X_OPCODE(31,0,0), X_MASK, {O_crfD, O_L, O_rA, O_rB, 0},
+ 0, "cmp", 0 },
+ { X_OPCODE(31,4,0), X_MASK, {O_TO, O_rA, O_rB, 0},
+ 0, "tw", 0 },
+ { XO_OPCODE(31,8,0,0), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "subfc", 0 },
+ { XO_OPCODE(31,8,0,1), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "subfc.", 0 },
+ { XO_OPCODE(31,10,0,0), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "addc", 0 },
+ { XO_OPCODE(31,10,0,1), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "addc.", 0 },
+ { XO_OPCODE(31,11,0,0), XO_MASK, {O_rD, O_rA, O_rB, O_Rc, 0},
+ 0, "mulhwu", 0 },
+ { XO_OPCODE(31,11,0,1), XO_MASK, {O_rD, O_rA, O_rB, O_Rc, 0},
+ 0, "mulhwu.", 0 },
+ { X_OPCODE(31,19,0), X_MASK, {O_rD, 0},
+ 0, "mfcr", 0 },
+ { X_OPCODE(31,20,0), X_MASK, {O_rD, O_rA, O_rB, 0},
+ 0, "lwarx", H_RA0_IS_0 },
+ { X_OPCODE(31,23,0), X_MASK, {O_rD, O_rA, O_rB, 0},
+ 0, "lwzx", H_RA0_IS_0 },
+ { X_OPCODE(31,24,0), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "slw", 0 },
+ { X_OPCODE(31,24,1), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "slw.", 0 },
+ { X_OPCODE(31,26,0), X_MASK, {O_rA, O_rS, O_Rc, 0 },
+ 0, "cntlzw", 0 },
+ { X_OPCODE(31,26,1), X_MASK, {O_rA, O_rS, O_Rc, 0},
+ 0, "cntlzw.", 0 },
+ { X_OPCODE(31,28,0), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "and", 0 },
+ { X_OPCODE(31,28,1), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "and.", 0 },
+ { X_OPCODE(31,32,0), X_MASK, {O_crfD, O_L, O_rA, O_rB, 0},
+ 0, "cmpl", 0 },
+ { XO_OPCODE(31,40,0,0), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "subf", 0 },
+ { XO_OPCODE(31,40,0,1), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "subf.", 0 },
+ { X_OPCODE(31,54,0), X_MASK, {O_rA, O_rB, 0},
+ 0, "dcbst", H_RA0_IS_0 },
+ { X_OPCODE(31,55,0), X_MASK, {O_rD, O_rA, O_rB, 0},
+ 0, "lwzux", 0 },
+ { X_OPCODE(31,60,0), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "andc", 0 },
+ { X_OPCODE(31,60,1), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "andc.", 0 },
+ { XO_OPCODE(31,75,0,0), XO_MASK, {O_rD, O_rA, O_rB, O_Rc, 0},
+ 0, "mulhw", 0 },
+ { XO_OPCODE(31,75,0,1), XO_MASK, {O_rD, O_rA, O_rB, O_Rc, 0},
+ 0, "mulhw.", 0 },
+ { X_OPCODE(31,83,0), X_MASK, {O_rD, 0},
+ 0, "mfmsr", 0 },
+ { X_OPCODE(31,86,0), X_MASK, {O_rA, O_rB, 0},
+ 0, "dcbf", H_RA0_IS_0 },
+ { X_OPCODE(31,87,0), X_MASK, {O_rD, O_rA, O_rB, 0},
+ 0, "lbzx", H_RA0_IS_0 },
+ { XO_OPCODE(31,104,0,0), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "neg", 0 },
+ { XO_OPCODE(31,104,0,1), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "neg.", 0 },
+ { X_OPCODE(31,119,0), X_MASK, {O_rD, O_rA, O_rB, 0},
+ 0, "lbzux", 0 },
+ { X_OPCODE(31,124,0), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "nor", 0 },
+ { X_OPCODE(31,124,1), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "nor.", 0 },
+ { XO_OPCODE(31,136,0,0), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "subfe", 0 },
+ { XO_OPCODE(31,136,0,1), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "subfe.", 0 },
+ { XO_OPCODE(31,138,0,0), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "adde", 0 },
+ { XO_OPCODE(31,138,0,1), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "adde.", 0 },
+ { XFX_OPCODE(31,144,0), XFX_MASK, {O_CRM, O_rS, 0},
+ 0, "mtcrf", 0 },
+ { X_OPCODE(31,146,0), X_MASK, {O_rS, 0},
+ 0, "mtmsr", 0 },
+ { X_OPCODE(31,150,1), X_MASK, {O_rS, O_rA, O_rB, 0},
+ 0, "stwcx.", 0 },
+ { X_OPCODE(31,151,0), X_MASK, {O_rS, O_rA, O_rB, 0},
+ 0, "stwx", 0 },
+ { X_OPCODE(31,183,0), X_MASK, {O_rS, O_rA, O_rB, 0},
+ 0, "stwux", 0 },
+ { XO_OPCODE(31,200,0,0), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "subfze", 0 },
+ { XO_OPCODE(31,200,0,1), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "subfze.", 0 },
+ { XO_OPCODE(31,202,0,0), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "addze", 0 },
+ { XO_OPCODE(31,202,0,1), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "addze.", 0 },
+ { X_OPCODE(31,210,0), X_MASK, {O_SR, O_rS, 0},
+ 0, "mtsr", 0 },
+ { X_OPCODE(31,215,0), X_MASK, {O_rS, O_rA, O_rB, 0},
+ 0, "stbx", H_RA0_IS_0 },
+ { XO_OPCODE(31,232,0,0), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "subfme", 0 },
+ { XO_OPCODE(31,232,0,1), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "subfme.", 0 },
+ { XO_OPCODE(31,234,0,0), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "addme", 0 },
+ { XO_OPCODE(31,234,0,1), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "addme.", 0 },
+ { XO_OPCODE(31,235,0,0), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "mullw", 0 },
+ { XO_OPCODE(31,235,0,1), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "mullw.", 0 },
+ { X_OPCODE(31,242,0), X_MASK, {O_rS, O_rB, 0},
+ 0, "mtsrin", 0 },
+ { X_OPCODE(31,246,0), X_MASK, {O_rA, O_rB, 0},
+ 0, "dcbtst", H_RA0_IS_0 },
+ { X_OPCODE(31,247,0), X_MASK, {O_rS, O_rA, O_rB, 0},
+ 0, "stbux", 0 },
+ { XO_OPCODE(31,266,0,0), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "add", 0 },
+ { XO_OPCODE(31,266,0,1), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "add.", 0 },
+ { X_OPCODE(31,278,0), X_MASK, {O_rA, O_rB, 0},
+ 0, "dcbt", H_RA0_IS_0 },
+ { X_OPCODE(31,279,0), X_MASK, {O_rD, O_rA, O_rB, 0},
+ 0, "lhzx", H_RA0_IS_0 },
+ { X_OPCODE(31,284,0), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "eqv", 0 },
+ { X_OPCODE(31,284,1), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "eqv.", 0 },
+ { X_OPCODE(31,306,0), X_MASK, {O_rB, 0},
+ 0, "tlbie", 0 },
+ { X_OPCODE(31,310,0), X_MASK, {O_rD, O_rA, O_rB, 0},
+ 0, "eciwx", H_RA0_IS_0 },
+ { X_OPCODE(31,311,0), X_MASK, {O_rD, O_rA, O_rB, 0},
+ 0, "lhzux", 0 },
+ { X_OPCODE(31,316,0), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "xor", 0 },
+ { X_OPCODE(31,316,1), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "xor.", 0 },
+ { XFX_OPCODE(31,339,0), XFX_MASK, {O_rD, O_spr, 0},
+ 0, "mfspr", 0 },
+ { X_OPCODE(31,343,0), X_MASK, {O_rD, O_rA, O_rB, 0},
+ 0, "lhax", H_RA0_IS_0 },
+ { X_OPCODE(31,370,0), X_MASK, {0},
+ 0, "tlbia", 0 },
+ { XFX_OPCODE(31,371,0), XFX_MASK, {O_rD, O_tbr, 0},
+ 0, "mftb", 0 },
+ { X_OPCODE(31,375,0), X_MASK, {O_rD, O_rA, O_rB, 0},
+ 0, "lhaux", 0 },
+ { X_OPCODE(31,407,0), X_MASK, {O_rS, O_rA, O_rB, 0},
+ 0, "sthx", H_RA0_IS_0 },
+ { X_OPCODE(31,412,0), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "orc", 0 },
+ { X_OPCODE(31,412,1), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "orc.", 0 },
+ { X_OPCODE(31,438,0), X_MASK, {O_rS, O_rA, O_rB, 0},
+ 0, "ecowx", H_RA0_IS_0 },
+ { X_OPCODE(31,439,0), X_MASK, {O_rS, O_rA, O_rB, 0},
+ 0, "sthux", 0 },
+ { X_OPCODE(31,444,0), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "or", 0 },
+ { X_OPCODE(31,444,1), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "or.", 0 },
+ { XO_OPCODE(31,459,0,0), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "divwu", 0 },
+ { XO_OPCODE(31,459,0,1), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "divwu.", 0 },
+ { XFX_OPCODE(31,467,0), XFX_MASK, {O_spr, O_rS, 0},
+ 0, "mtspr", 0 },
+ { X_OPCODE(31,470,0), X_MASK, {O_rA, O_rB, 0},
+ 0, "dcbi", H_RA0_IS_0 },
+ { X_OPCODE(31,476,0), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "nand", 0 },
+ { X_OPCODE(31,476,1), X_MASK, {O_rA, O_rS, O_rB, O_Rc,0},
+ 0, "nand.", 0 },
+ { XO_OPCODE(31,491,0,0), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "divw", 0 },
+ { XO_OPCODE(31,491,0,1), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "divw.", 0 },
+ { X_OPCODE(31,512,0), X_MASK, {O_crfD, 0},
+ 0, "mcrxr", 0 },
+ { XO_OPCODE(31,8,1,0), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "subfco", 0 },
+ { XO_OPCODE(31,8,1,1), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "subfco.", 0 },
+ { XO_OPCODE(31,10,1,0), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "addco", 0 },
+ { XO_OPCODE(31,10,1,1), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "addco.", 0 },
+ { X_OPCODE(31,533,0), X_MASK, {O_rD, O_rA, O_rB, 0},
+ 0, "lswx", H_RA0_IS_0 },
+ { X_OPCODE(31,534,0), X_MASK, {O_rD, O_rA, O_rB, 0},
+ 0, "lwbrx", H_RA0_IS_0 },
+ { X_OPCODE(31,536,0), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "srw", 0 },
+ { X_OPCODE(31,536,1), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "srw.", 0 },
+ { XO_OPCODE(31,40,1,0), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "subfo", 0 },
+ { XO_OPCODE(31,40,1,1), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "subfo.", 0 },
+ { X_OPCODE(31,566,0), X_MASK, {0},
+ 0, "tlbsync", 0 },
+ { X_OPCODE(31,595,0), X_MASK, {O_rD, O_SR, 0},
+ 0, "mfsr", 0 },
+ { X_OPCODE(31,597,0), X_MASK, {O_rD, O_rA, O_NB, 0},
+ 0, "lswi", H_RA0_IS_0 },
+ { X_OPCODE(31,598,0), X_MASK, {0},
+ 0, "sync", 0 },
+ { XO_OPCODE(31,104,1,0), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "nego", 0 },
+ { XO_OPCODE(31,104,1,1), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "nego.", 0 },
+ { XO_OPCODE(31,136,1,0), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "subfeo", 0 },
+ { XO_OPCODE(31,136,1,1), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "subfeo.", 0 },
+ { XO_OPCODE(31,138,1,0), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "addeo", 0 },
+ { XO_OPCODE(31,138,1,1), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "addeo.", 0 },
+ { X_OPCODE(31,659,0), X_MASK, {O_rD, O_rB, 0},
+ 0, "mfsrin", 0 },
+ { X_OPCODE(31,661,0), X_MASK, {O_rS, O_rA, O_rB, 0},
+ 0, "stswx", H_RA0_IS_0 },
+ { X_OPCODE(31,662,0), X_MASK, {O_rS, O_rA, O_rB, 0},
+ 0, "stwbrx", H_RA0_IS_0 },
+ { XO_OPCODE(31,200,1,0), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "subfzeo", 0 },
+ { XO_OPCODE(31,200,1,1), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "subfzeo.", 0 },
+ { XO_OPCODE(31,202,1,0), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "addzeo", 0 },
+ { XO_OPCODE(31,202,1,1), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "addzeo.", 0 },
+ { X_OPCODE(31,725,0), X_MASK, {O_rS, O_rA, O_NB, 0},
+ 0, "stswi", H_RA0_IS_0 },
+ { XO_OPCODE(31,232,1,0), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "subfmeo", 0 },
+ { XO_OPCODE(31,232,1,1), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "subfmeo.", 0 },
+ { XO_OPCODE(31,234,1,0), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "addmeo", 0 },
+ { XO_OPCODE(31,234,1,1), XO_MASK, {O_rD, O_rA, O_OE, O_Rc, 0},
+ 0, "addmeo.", 0 },
+ { XO_OPCODE(31,235,1,0), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "mullwo", 0 },
+ { XO_OPCODE(31,235,1,1), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "mullwo.", 0 },
+ { XO_OPCODE(31,266,1,0), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "addo", 0 },
+ { XO_OPCODE(31,266,1,1), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "addo.", 0 },
+ { X_OPCODE(31,790,0), X_MASK, {O_rD, O_rA, O_rB, 0},
+ 0, "lhbrx", H_RA0_IS_0 },
+ { X_OPCODE(31,792,0), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "sraw", 0 },
+ { X_OPCODE(31,792,1), X_MASK, {O_rA, O_rS, O_rB, O_Rc, 0},
+ 0, "sraw.", 0 },
+ { X_OPCODE(31,824,0), X_MASK, {O_rA, O_rS, O_SH, O_Rc, 0},
+ 0, "srawi", 0 },
+ { X_OPCODE(31,824,1), X_MASK, {O_rA, O_rS, O_SH, O_Rc, 0},
+ 0, "srawi.", 0 },
+ { X_OPCODE(31,854,0), X_MASK, {0},
+ 0, "eieio", 0 },
+ { X_OPCODE(31,918,0), X_MASK, {O_rS, O_rA, O_rB, 0},
+ 0, "sthbrx", H_RA0_IS_0 },
+ { X_OPCODE(31,922,0), X_MASK, {O_rA, O_rS, O_Rc, 0},
+ 0, "extsh", 0 },
+ { X_OPCODE(31,922,1), X_MASK, {O_rA, O_rS, O_Rc, 0},
+ 0, "extsh.", 0 },
+ { X_OPCODE(31,954,0), X_MASK, {O_rA, O_rS, O_Rc, 0},
+ 0, "extsb", 0 },
+ { X_OPCODE(31,954,1), X_MASK, {O_rA, O_rS, O_Rc, 0},
+ 0, "extsb.", 0 },
+ { XO_OPCODE(31,459,1,0), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "divwuo", 0 },
+ { XO_OPCODE(31,459,1,1), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "divwuo.", 0 },
+ { X_OPCODE(31,978,0), X_MASK, {O_rB, 0},
+ 0, "tlbld", 0 },
+ { X_OPCODE(31,982,0), X_MASK, {O_rA, O_rB, 0},
+ 0, "icbi", H_RA0_IS_0 },
+ { XO_OPCODE(31,491,1,0), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "divwo", 0 },
+ { XO_OPCODE(31,491,1,1), XO_MASK, {O_rD, O_rA, O_rB, O_OE, O_Rc, 0},
+ 0, "divwo.", 0 },
+ { X_OPCODE(31,1010,0), X_MASK, {O_rB, 0},
+ 0, "tlbli", 0 },
+ { X_OPCODE(31,1014,0), X_MASK, {O_rA, O_rB, 0},
+ 0, "dcbz", H_RA0_IS_0 },
+ { D_OPCODE(32), D_MASK, {O_rD, O_d, O_rA, 0},
+ 0, "lwz", H_RA0_IS_0 },
+ { D_OPCODE(33), D_MASK, {O_rD, O_d, O_rA, 0},
+ 0, "lwzu", 0 },
+ { D_OPCODE(34), D_MASK, {O_rD, O_d, O_rA, 0},
+ 0, "lbz", H_RA0_IS_0 },
+ { D_OPCODE(35), D_MASK, {O_rD, O_d, O_rA, 0},
+ 0, "lbzu", 0 },
+ { D_OPCODE(36), D_MASK, {O_rS, O_d, O_rA, 0},
+ 0, "stw", H_RA0_IS_0 },
+ { D_OPCODE(37), D_MASK, {O_rS, O_d, O_rA, 0},
+ 0, "stwu", 0 },
+ { D_OPCODE(38), D_MASK, {O_rS, O_d, O_rA, 0},
+ 0, "stb", H_RA0_IS_0 },
+ { D_OPCODE(39), D_MASK, {O_rS, O_d, O_rA, 0},
+ 0, "stbu", 0 },
+ { D_OPCODE(40), D_MASK, {O_rD, O_d, O_rA, 0},
+ 0, "lhz", H_RA0_IS_0 },
+ { D_OPCODE(41), D_MASK, {O_rD, O_d, O_rA, 0},
+ 0, "lhzu", 0 },
+ { D_OPCODE(42), D_MASK, {O_rD, O_d, O_rA, 0},
+ 0, "lha", H_RA0_IS_0 },
+ { D_OPCODE(43), D_MASK, {O_rD, O_d, O_rA, 0},
+ 0, "lhau", 0 },
+ { D_OPCODE(44), D_MASK, {O_rS, O_d, O_rA, 0},
+ 0, "sth", H_RA0_IS_0 },
+ { D_OPCODE(45), D_MASK, {O_rS, O_d, O_rA, 0},
+ 0, "sthu", 0 },
+ { D_OPCODE(46), D_MASK, {O_rD, O_d, O_rA, 0},
+ 0, "lmw", H_RA0_IS_0 },
+ { D_OPCODE(47), D_MASK, {O_rS, O_d, O_rA, 0},
+ 0, "stmw", H_RA0_IS_0 },
+};
+
+const unsigned int n_opcodes = sizeof(opcodes) / sizeof(opcodes[0]);
+
+struct spr_info spr_map[] = {
+ { SPR_XER, "XER" },
+ { SPR_LR, "LR" },
+ { SPR_CTR, "CTR" },
+ { SPR_DSISR, "DSISR" },
+ { SPR_DAR, "DAR" },
+ { SPR_DEC, "DEC" },
+ { SPR_SRR0, "SRR0" },
+ { SPR_SRR1, "SRR1" },
+ { SPR_EIE, "EIE" },
+ { SPR_EID, "EID" },
+ { SPR_CMPA, "CMPA" },
+ { SPR_CMPB, "CMPB" },
+ { SPR_CMPC, "CMPC" },
+ { SPR_CMPD, "CMPD" },
+ { SPR_ICR, "ICR" },
+ { SPR_DER, "DER" },
+ { SPR_COUNTA, "COUNTA" },
+ { SPR_COUNTB, "COUNTB" },
+ { SPR_CMPE, "CMPE" },
+ { SPR_CMPF, "CMPF" },
+ { SPR_CMPG, "CMPG" },
+ { SPR_CMPH, "CMPH" },
+ { SPR_LCTRL1, "LCTRL1" },
+ { SPR_LCTRL2, "LCTRL2" },
+ { SPR_ICTRL, "ICTRL" },
+ { SPR_BAR, "BAR" },
+ { SPR_USPRG0, "USPRG0" },
+ { SPR_SPRG4_RO, "SPRG4_RO" },
+ { SPR_SPRG5_RO, "SPRG5_RO" },
+ { SPR_SPRG6_RO, "SPRG6_RO" },
+ { SPR_SPRG7_RO, "SPRG7_RO" },
+ { SPR_SPRG0, "SPRG0" },
+ { SPR_SPRG1, "SPRG1" },
+ { SPR_SPRG2, "SPRG2" },
+ { SPR_SPRG3, "SPRG3" },
+ { SPR_SPRG4, "SPRG4" },
+ { SPR_SPRG5, "SPRG5" },
+ { SPR_SPRG6, "SPRG6" },
+ { SPR_SPRG7, "SPRG7" },
+ { SPR_TBL, "TBL" },
+ { SPR_TBU, "TBU" },
+ { SPR_IC_CST, "IC_CST" },
+ { SPR_IC_ADR, "IC_ADR" },
+ { SPR_IC_DAT, "IC_DAT" },
+ { SPR_DC_CST, "DC_CST" },
+ { SPR_DC_ADR, "DC_ADR" },
+ { SPR_DC_DAT, "DC_DAT" },
+ { SPR_DPDR, "DPDR" },
+ { SPR_IMMR, "IMMR" },
+ { SPR_MI_CTR, "MI_CTR" },
+ { SPR_MI_AP, "MI_AP" },
+ { SPR_MI_EPN, "MI_EPN" },
+ { SPR_MI_TWC, "MI_TWC" },
+ { SPR_MI_RPN, "MI_RPN" },
+ { SPR_MD_CTR, "MD_CTR" },
+ { SPR_M_CASID, "M_CASID" },
+ { SPR_MD_AP, "MD_AP" },
+ { SPR_MD_EPN, "MD_EPN" },
+ { SPR_M_TWB, "M_TWB" },
+ { SPR_MD_TWC, "MD_TWC" },
+ { SPR_MD_RPN, "MD_RPN" },
+ { SPR_M_TW, "M_TW" },
+ { SPR_MI_DBCAM, "MI_DBCAM" },
+ { SPR_MI_DBRAM0, "MI_DBRAM0" },
+ { SPR_MI_DBRAM1, "MI_DBRAM1" },
+ { SPR_MD_DBCAM, "MD_DBCAM" },
+ { SPR_MD_DBRAM0, "MD_DBRAM0" },
+ { SPR_MD_DBRAM1, "MD_DBRAM1" },
+ { SPR_ZPR, "ZPR" },
+ { SPR_PID, "PID" },
+ { SPR_CCR0, "CCR0" },
+ { SPR_IAC3, "IAC3" },
+ { SPR_IAC4, "IAC4" },
+ { SPR_DVC1, "DVC1" },
+ { SPR_DVC2, "DVC2" },
+ { SPR_SGR, "SGR" },
+ { SPR_DCWR, "DCWR" },
+ { SPR_SLER, "SLER" },
+ { SPR_SU0R, "SU0R" },
+ { SPR_DBCR1, "DBCR1" },
+ { SPR_ICDBDR, "ICDBDR" },
+ { SPR_ESR, "ESR" },
+ { SPR_DEAR, "DEAR" },
+ { SPR_EVPR, "EVPR" },
+ { SPR_TSR, "TSR" },
+ { SPR_TCR, "TCR" },
+ { SPR_PIT, "PIT" },
+ { SPR_SRR2, "SRR2" },
+ { SPR_SRR3, "SRR3" },
+ { SPR_DBSR, "DBSR" },
+ { SPR_DBCR0, "DBCR0" },
+ { SPR_IAC1, "IAC1" },
+ { SPR_IAC2, "IAC2" },
+ { SPR_DAC1, "DAC1" },
+ { SPR_DAC2, "DAC2" },
+ { SPR_DCCR, "DCCR" },
+ { SPR_ICCR, "ICCR" },
+};
+
+const unsigned int n_sprs = sizeof(spr_map) / sizeof(spr_map[0]);
+
+#endif
+
+/*
+ * Copyright (c) 2000 William L. Pitts and W. Gerald Hicks
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
+
--- /dev/null
+/*
+ * BedBug Functions
+ */
+#ifndef _CMD_BEDBUG_H
+#define _CMD_BEDBUG_H
+
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+
+#define CMD_TBL_DIS MK_CMD_TBL_ENTRY( \
+ "ds", 2, 3, 1, do_bedbug_dis, \
+ "ds - disassemble memory\n", \
+ "ds <address> [# instructions]\n" \
+ ),
+
+#define CMD_TBL_ASM MK_CMD_TBL_ENTRY( \
+ "as", 2, 2, 0, do_bedbug_asm, \
+ "as - assemble memory\n", \
+ "as <address>\n" \
+ ),
+
+#define CMD_TBL_BREAK MK_CMD_TBL_ENTRY( \
+ "break", 2, 3, 0, do_bedbug_break, \
+ "break - set or clear a breakpoint\n", \
+ " - Set or clear a breakpoint\n" \
+ "break <address> - Break at an address\n" \
+ "break off <bp#> - Disable breakpoint.\n" \
+ "break show - List breakpoints.\n" \
+ ),
+
+#define CMD_TBL_CONTINUE MK_CMD_TBL_ENTRY( \
+ "continue", 4, 1, 0, do_bedbug_continue, \
+ "break - continue from a breakpoint\n", \
+ " - continue from a breakpoint.\n" \
+ ),
+
+#define CMD_TBL_STEP MK_CMD_TBL_ENTRY( \
+ "step", 1, 1, 1, do_bedbug_step, \
+ "step - single step execution.\n", \
+ " - single step execution.\n" \
+ ),
+
+#define CMD_TBL_NEXT MK_CMD_TBL_ENTRY( \
+ "next", 1, 1, 1, do_bedbug_next, \
+ "next - single step execution, stepping over subroutines.\n",\
+ " - single step execution, stepping over subroutines.\n" \
+ ),
+
+#define CMD_TBL_STACK MK_CMD_TBL_ENTRY( \
+ "where", 2, 1, 1, do_bedbug_stack, \
+ "where - Print the running stack.\n", \
+ " - Print the running stack.\n" \
+ ),
+
+#define CMD_TBL_RDUMP MK_CMD_TBL_ENTRY( \
+ "rdump", 2, 1, 1, do_bedbug_rdump, \
+ "rdump - Show registers.\n", \
+ " - Show registers.\n" \
+ ),
+
+#define CMD_TBL_BOOTELF MK_CMD_TBL_ENTRY( \
+ "bootelf", 7, 2, 0, do_bootelf, \
+ "bootelf - Boot from an ELF image in memory\n", \
+ " [address] - load address of ELF image.\n" \
+ ),
+
+#define CMD_TBL_BOOTVX MK_CMD_TBL_ENTRY( \
+ "bootvx", 6, 2, 0, do_bootvx, \
+ "bootvx - Boot vxWorks from an ELF image\n", \
+ " [address] - load address of vxWorks ELF image.\n" \
+ ),
+
+extern void do_bedbug_dis (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern void do_bedbug_asm (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern void do_bedbug_break (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern void do_bedbug_continue (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern void do_bedbug_step (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern void do_bedbug_next (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern void do_bedbug_stack (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern void do_bedbug_rdump (cmd_tbl_t *, bd_t *, int, int, char *[]);
+
+extern void do_bootelf (cmd_tbl_t *, bd_t *, int, int, char *[]);
+extern void do_bootvx (cmd_tbl_t *, bd_t *, int, int, char *[]);
+
+/* Supporting routines */
+extern int bedbug_puts (const char *);
+extern void bedbug_init (void);
+extern void do_bedbug_breakpoint (struct pt_regs*);
+extern void bedbug_main_loop (unsigned long,struct pt_regs *);
+extern int valid_elf_image (unsigned long);
+extern unsigned long load_elf_image (unsigned long);
+
+
+typedef struct {
+ int hw_debug_enabled;
+ int stopped;
+ int current_bp;
+ struct pt_regs * regs;
+ bd_t * bd;
+
+ void (*do_break)(cmd_tbl_t*,bd_t*,int,int,char *[]);
+ void (*break_isr)(struct pt_regs *);
+ int (*find_empty)(void);
+ int (*set)(int,unsigned long);
+ int (*clear)(int);
+} CPU_DEBUG_CTX;
+
+
+#else /* ! CFG_CMD_BEDBUG */
+
+#define CMD_TBL_DIS
+#define CMD_TBL_ASM
+#define CMD_TBL_BREAK
+#define CMD_TBL_CONTINUE
+#define CMD_TBL_STEP
+#define CMD_TBL_NEXT
+#define CMD_TBL_STACK
+#define CMD_TBL_RDUMP
+#define CMD_TBL_BOOTELF
+#define CMD_TBL_BOOTVX
+
+#endif /* CFG_CMD_BEDBUG */
+#endif /* _CMD_BEDBUG_H */
+
+
+/*
+ * Copyright (c) 2001 William L. Pitts
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are freely
+ * permitted provided that the above copyright notice and this
+ * paragraph and the following disclaimer are duplicated in all
+ * such forms.
+ *
+ * This software is provided "AS IS" and without any express or
+ * implied warranties, including, without limitation, the implied
+ * warranties of merchantability and fitness for a particular
+ * purpose.
+ */
#define CFG_CMD_IMMAP 0x00400000 /* IMMR dump support */
#define CFG_CMD_DATE 0x00800000 /* support for RTC, date/time...*/
#define CFG_CMD_DHCP 0x01000000 /* DHCP Support */
-#define CFG_CMD_BSP 0x02000000 /* Board SPecific functions */
+#define CFG_CMD_BEDBUG 0x02000000 /* Include BedBug Debugger */
+#define CFG_CMD_BSP 0x04000000 /* Board SPecific functions */
#define CFG_CMD_ALL 0xFFFFFFFF /* ALL commands */
CFG_CMD_REGINFO | \
CFG_CMD_IMMAP | \
CFG_CMD_DATE | \
+ CFG_CMD_BEDBUG | \
CFG_CMD_BSP )
/* Default configuration
#else /* force ENV to be embedded */
#define CFG_ENV_SIZE (2 * 1024) /* Total Size of Environment Sector 2k */
#define CFG_ENV_ADDR (CFG_MONITOR_BASE + CFG_MONITOR_LEN - CFG_ENV_SIZE - 0x10) /* let space for reset vector */
-/* #define CFG_ENV_ADDR (CFG_MONITOR_BASE)*/ /* let space for reset vector */
+/* #define CFG_ENV_ADDR (CFG_MONITOR_BASE)*/
#define CFG_ENV_OFFSET (CFG_ENV_ADDR - CFG_FLASH_BASE)
#endif
& ~CFG_CMD_PCI \
& ~CFG_CMD_EEPROM \
& ~CFG_CMD_I2C \
- & ~CFG_CMD_IRQ)
+ & ~CFG_CMD_IRQ \
+ & ~CFG_CMD_BEDBUG )
#if CONFIG_LANTEC >= 2
#define CONFIG_RTC_MPC8xx /* use internal RTC of MPC8xx */
#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \
CFG_CMD_DHCP | \
CFG_CMD_IDE | \
+ CFG_CMD_DHCP | \
CFG_CMD_DATE )
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
--- /dev/null
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * board/config.h - configuration options, board specific
+ */
+
+#ifndef __CONFIG_H
+#define __CONFIG_H
+
+/*
+ * High Level Configuration Options
+ * (easy to change)
+ */
+
+#define CONFIG_MPC8260 1 /* This is a MPC8260 CPU */
+#define CONFIG_TQM8260 100 /* ...on a TQM8260 module Rev.100 */
+#define CONFIG_82xx_CONS_SMC1 1 /* console on SMC1 */
+
+#if 0
+#define CONFIG_BOOTDELAY -1 /* autoboot disabled */
+#else
+#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */
+#endif
+
+#undef CONFIG_BOOTARGS
+#define CONFIG_BOOTCOMMAND \
+ "bootp; " \
+ "setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) " \
+ "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off; " \
+ "bootm"
+
+#define CONFIG_SOFT_I2C 1 /* I2C support */
+#define CONFIG_I2C_X 1 /* extended EEPROM addressing */
+
+# define CFG_I2C_EEPROM_ADDR 0x50
+# define CFG_EEPROM_PAGE_WRITE_BITS 5
+
+/*
+ * select serial console configuration
+ *
+ * if either CONFIG_CONS_ON_SMC or CONFIG_CONS_ON_SCC is selected, then
+ * CONFIG_CONS_INDEX must be set to the channel number (1-2 for SMC, 1-4
+ * for SCC).
+ *
+ * if CONFIG_CONS_NONE is defined, then the serial console routines must
+ * defined elsewhere (for example, on the cogent platform, there are serial
+ * ports on the motherboard which are used for the serial console - see
+ * cogent/cma101/serial.[ch]).
+ */
+#define CONFIG_CONS_ON_SMC /* define if console on SMC */
+#undef CONFIG_CONS_ON_SCC /* define if console on SCC */
+#undef CONFIG_CONS_NONE /* define if console on something else*/
+#ifdef CONFIG_82xx_CONS_SMC1
+#define CONFIG_CONS_INDEX 1 /* which serial channel for console */
+#endif
+#ifdef CONFIG_82xx_CONS_SMC2
+#define CONFIG_CONS_INDEX 2 /* which serial channel for console */
+#endif
+
+#undef CONFIG_CONS_USE_EXTC /* SMC/SCC use ext clock not brg_clk */
+#define CONFIG_CONS_EXTC_RATE 3686400 /* SMC/SCC ext clk rate in Hz */
+#define CONFIG_CONS_EXTC_PINSEL 0 /* pin select 0=CLK3/CLK9 */
+
+/*
+ * select ethernet configuration
+ *
+ * if either CONFIG_ETHER_ON_SCC or CONFIG_ETHER_ON_FCC is selected, then
+ * CONFIG_ETHER_INDEX must be set to the channel number (1-4 for SCC, 1-3
+ * for FCC)
+ *
+ * if CONFIG_ETHER_NONE is defined, then either the ethernet routines must be
+ * defined elsewhere (as for the console), or CFG_CMD_NET must be removed
+ * from CONFIG_COMMANDS to remove support for networking.
+ *
+ * (On TQM8260 either SCC1 or FCC2 may be chosen: SCC1 is hardwired to the
+ * X.29 connector, and FCC2 is hardwired to the X.1 connector)
+ */
+#undef CONFIG_ETHER_ON_SCC /* define if ether on SCC */
+#define CONFIG_ETHER_ON_FCC /* define if ether on FCC */
+#undef CONFIG_ETHER_NONE /* define if ether on something else */
+#define CONFIG_ETHER_INDEX 2 /* which SCC/FCC channel for ethernet */
+
+/* system clock rate (CLKIN) - equal to the 60x and local bus speed */
+#define CONFIG_8260_CLKIN 66666666 /* in Hz */
+
+#if defined(CONFIG_CONS_NONE) || defined(CONFIG_CONS_USE_EXTC)
+#define CONFIG_BAUDRATE 230400
+#else
+#define CONFIG_BAUDRATE 9600
+#endif
+
+#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */
+#undef CFG_LOADS_BAUD_CHANGE /* don't allow baudrate change */
+
+#undef CONFIG_WATCHDOG /* watchdog disabled */
+
+#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAULT|CONFIG_BOOTP_BOOTFILESIZE)
+
+#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_EEPROM)
+
+/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
+#include <cmd_confdefs.h>
+
+/*
+ * Miscellaneous configurable options
+ */
+#define CFG_LONGHELP /* undef to save memory */
+#define CFG_PROMPT "=> " /* Monitor Command Prompt */
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */
+#else
+#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
+#endif
+#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
+#define CFG_MAXARGS 16 /* max number of command args */
+#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */
+
+#define CFG_MEMTEST_START 0x0400000 /* memtest works on */
+#define CFG_MEMTEST_END 0x0C00000 /* 4 ... 12 MB in DRAM */
+
+#define CFG_LOAD_ADDR 0x100000 /* default load address */
+
+#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */
+
+#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
+
+/*
+ * For booting Linux, the board info and command line data
+ * have to be in the first 8 MB of memory, since this is
+ * the maximum mapped by the Linux kernel during initialization.
+ */
+#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */
+
+
+/* What should the base address of the main FLASH be and how big is
+ * it (in MBytes)? This must contain TEXT_BASE from board/tqm8260/config.mk
+ * The main FLASH is whichever is connected to *CS0.
+ */
+#define CFG_FLASH0_BASE 0x40000000
+#define CFG_FLASH1_BASE 0x60000000
+#define CFG_FLASH0_SIZE 32
+#define CFG_FLASH1_SIZE 32
+
+/* Flash bank size (for preliminary settings)
+ */
+#define CFG_FLASH_SIZE CFG_FLASH0_SIZE
+
+/*-----------------------------------------------------------------------
+ * FLASH organization
+ */
+#define CFG_MAX_FLASH_BANKS 1 /* max num of memory banks */
+#define CFG_MAX_FLASH_SECT 128 /* max num of sects on one chip */
+
+#define CFG_FLASH_ERASE_TOUT 240000 /* Flash Erase Timeout (in ms) */
+#define CFG_FLASH_WRITE_TOUT 500 /* Flash Write Timeout (in ms) */
+
+#if 0
+/* Start port with environment in flash; switch to EEPROM later */
+#define CFG_ENV_IS_IN_FLASH 1
+#define CFG_ENV_ADDR (CFG_FLASH_BASE+0x40000)
+#define CFG_ENV_SIZE 0x40000
+#define CFG_ENV_SECT_SIZE 0x40000
+#else
+/* Final version: environment in EEPROM */
+#define CFG_ENV_IS_IN_EEPROM 1
+#define CFG_ENV_OFFSET 0
+#define CFG_ENV_SIZE 1024
+#endif
+
+/*-----------------------------------------------------------------------
+ * Hard Reset Configuration Words
+ *
+ * if you change bits in the HRCW, you must also change the CFG_*
+ * defines for the various registers affected by the HRCW e.g. changing
+ * HRCW_DPPCxx requires you to also change CFG_SIUMCR.
+ */
+#define CFG_HRCW_MASTER (HRCW_CIP | HRCW_ISB111 | HRCW_BMS)
+
+/* no slaves so just fill with zeros */
+#define CFG_HRCW_SLAVE1 0
+#define CFG_HRCW_SLAVE2 0
+#define CFG_HRCW_SLAVE3 0
+#define CFG_HRCW_SLAVE4 0
+#define CFG_HRCW_SLAVE5 0
+#define CFG_HRCW_SLAVE6 0
+#define CFG_HRCW_SLAVE7 0
+
+/*-----------------------------------------------------------------------
+ * Internal Memory Mapped Register
+ */
+#define CFG_IMMR 0xFFF00000
+
+/*-----------------------------------------------------------------------
+ * Definitions for initial stack pointer and data area (in DPRAM)
+ */
+#define CFG_INIT_RAM_ADDR CFG_IMMR
+#define CFG_INIT_RAM_END 0x4000 /* End of used area in DPRAM */
+#define CFG_INIT_DATA_SIZE 128 /* size in bytes reserved for initial data*/
+#define CFG_INIT_DATA_OFFSET (CFG_INIT_RAM_END - CFG_INIT_DATA_SIZE)
+#define CFG_INIT_SP_OFFSET CFG_INIT_DATA_OFFSET
+
+/*-----------------------------------------------------------------------
+ * Start addresses for the final memory configuration
+ * (Set up by the startup code)
+ * Please note that CFG_SDRAM_BASE _must_ start at 0
+ *
+ * 60x SDRAM is mapped at CFG_SDRAM_BASE, local SDRAM
+ * is mapped at SDRAM_BASE2_PRELIM.
+ */
+#define CFG_SDRAM_BASE 0x00000000
+#define CFG_FLASH_BASE CFG_FLASH0_BASE
+#define CFG_MONITOR_BASE TEXT_BASE
+#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */
+#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc()*/
+
+/*
+ * Internal Definitions
+ *
+ * Boot Flags
+ */
+#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH*/
+#define BOOTFLAG_WARM 0x02 /* Software reboot */
+
+
+/*-----------------------------------------------------------------------
+ * Cache Configuration
+ */
+#define CFG_CACHELINE_SIZE 32 /* For MPC8260 CPU */
+
+/*-----------------------------------------------------------------------
+ * HIDx - Hardware Implementation-dependent Registers 2-11
+ *-----------------------------------------------------------------------
+ * HID0 also contains cache control - initially enable both caches and
+ * invalidate contents, then the final state leaves only the instruction
+ * cache enabled. Note that Power-On and Hard reset invalidate the caches,
+ * but Soft reset does not.
+ *
+ * HID1 has only read-only information - nothing to set.
+ */
+#define CFG_HID0_INIT (HID0_ICE|HID0_DCE|HID0_ICFI|HID0_DCI|\
+ HID0_IFEM|HID0_ABE)
+#define CFG_HID0_FINAL (HID0_ICE|HID0_IFEM|HID0_ABE)
+#define CFG_HID2 0
+
+/*-----------------------------------------------------------------------
+ * RMR - Reset Mode Register 5-5
+ *-----------------------------------------------------------------------
+ * turn on Checkstop Reset Enable
+ */
+#define CFG_RMR RMR_CSRE
+
+/*-----------------------------------------------------------------------
+ * BCR - Bus Configuration 4-25
+ *-----------------------------------------------------------------------
+ */
+#define CFG_BCR (BCR_EBM|BCR_L2C|BCR_LETM|\
+ BCR_NPQM0|BCR_NPQM1|BCR_NPQM2)
+
+/*-----------------------------------------------------------------------
+ * SIUMCR - SIU Module Configuration 4-31
+ *-----------------------------------------------------------------------
+ */
+#define CFG_SIUMCR (SIUMCR_DPPC10|SIUMCR_APPC10)
+
+
+/*-----------------------------------------------------------------------
+ * SYPCR - System Protection Control 4-35
+ * SYPCR can only be written once after reset!
+ *-----------------------------------------------------------------------
+ * Watchdog & Bus Monitor Timer max, 60x Bus Monitor enable
+ */
+#if defined(CONFIG_WATCHDOG)
+#define CFG_SYPCR (SYPCR_SWTC|SYPCR_BMT|SYPCR_PBME|SYPCR_LBME|\
+ SYPCR_SWRI|SYPCR_SWP|SYPCR_SWE)
+#else
+#define CFG_SYPCR (SYPCR_SWTC|SYPCR_BMT|SYPCR_PBME|SYPCR_LBME|\
+ SYPCR_SWRI|SYPCR_SWP)
+#endif /* CONFIG_WATCHDOG */
+
+/*-----------------------------------------------------------------------
+ * TMCNTSC - Time Counter Status and Control 4-40
+ *-----------------------------------------------------------------------
+ * Clear once per Second and Alarm Interrupt Status, Set 32KHz timersclk,
+ * and enable Time Counter
+ */
+#define CFG_TMCNTSC (TMCNTSC_SEC|TMCNTSC_ALR|TMCNTSC_TCF|TMCNTSC_TCE)
+
+/*-----------------------------------------------------------------------
+ * PISCR - Periodic Interrupt Status and Control 4-42
+ *-----------------------------------------------------------------------
+ * Clear Periodic Interrupt Status, Set 32KHz timersclk, and enable
+ * Periodic timer
+ */
+#define CFG_PISCR (PISCR_PS|PISCR_PTF|PISCR_PTE)
+
+/*-----------------------------------------------------------------------
+ * SCCR - System Clock Control 9-8
+ *-----------------------------------------------------------------------
+ * Ensure DFBRG is Divide by 16
+ */
+#define CFG_SCCR 0
+
+/*-----------------------------------------------------------------------
+ * RCCR - RISC Controller Configuration 13-7
+ *-----------------------------------------------------------------------
+ */
+#define CFG_RCCR 0
+
+/*
+ * Init Memory Controller:
+ *
+ * Bank Bus Machine PortSz Device
+ * ---- --- ------- ------ ------
+ * 0 60x GPCM 64 bit FLASH
+ * 1 60x SDRAM 64 bit SDRAM
+ * 2 Local SDRAM 32 bit SDRAM
+ *
+ */
+
+ /* Initialize SDRAM on local bus
+ */
+#define CFG_INIT_LOCAL_SDRAM
+
+
+/* Minimum mask to separate preliminary
+ * address ranges for CS[0:2]
+ */
+#define CFG_MIN_AM_MASK 0xC0000000
+
+#define CFG_MPTPR 0x4000
+
+/*-----------------------------------------------------------------------------
+ * Address for Mode Register Set (MRS) command
+ *-----------------------------------------------------------------------------
+ * In fact, the address is rather configuration data presented to the SDRAM on
+ * its address lines. Because the address lines may be mux'ed externally either
+ * for 8 column or 9 column devices, some bits appear twice in the 8260's
+ * address:
+ *
+ * | (RFU) | (RFU) | WBL | TM | CL | BT | Burst Length |
+ * | BA1 BA0 | A12 : A10 | A9 | A8 A7 | A6 : A4 | A3 | A2 : A0 |
+ * 8 columns mux'ing: | A9 | A10 A21 | A22 : A24 | A25 | A26 : A28 |
+ * 9 columns mux'ing: | A8 | A20 A21 | A22 : A24 | A25 | A26 : A28 |
+ * Settings: | 0 | 0 0 | 0 1 0 | 0 | 0 1 0 |
+ *-----------------------------------------------------------------------------
+ */
+#define CFG_MRS_OFFS 0x00000110
+
+
+/* Bank 0 - FLASH
+ */
+#define CFG_BR0_PRELIM ((CFG_FLASH_BASE & BRx_BA_MSK) |\
+ BRx_PS_64 |\
+ BRx_MS_GPCM_P |\
+ BRx_V)
+
+#define CFG_OR0_PRELIM (MEG_TO_AM(CFG_FLASH_SIZE) |\
+ ORxG_CSNT |\
+ ORxG_ACS_DIV1 |\
+ ORxG_SCY_3_CLK |\
+ ORxG_EHTR |\
+ ORxG_TRLX)
+
+ /* SDRAM on TQM8260 can have either 8 or 9 columns.
+ * The number affects configuration values.
+ */
+
+/* Bank 1 - 60x bus SDRAM
+ */
+#define CFG_PSRT 0x20
+#define CFG_LSRT 0x20
+#ifndef CFG_RAMBOOT
+#define CFG_BR1_PRELIM ((CFG_SDRAM_BASE & BRx_BA_MSK) |\
+ BRx_PS_64 |\
+ BRx_MS_SDRAM_P |\
+ BRx_V)
+
+#define CFG_OR1_PRELIM CFG_OR1_8COL
+
+
+ /* SDRAM initialization values for 8-column chips
+ */
+#define CFG_OR1_8COL (CFG_MIN_AM_MASK |\
+ ORxS_BPD_4 |\
+ ORxS_ROWST_PBI1_A7 |\
+ ORxS_NUMR_12)
+
+#define CFG_PSDMR_8COL (PSDMR_PBI |\
+ PSDMR_SDAM_A15_IS_A5 |\
+ PSDMR_BSMA_A12_A14 |\
+ PSDMR_SDA10_PBI1_A8 |\
+ PSDMR_RFRC_7_CLK |\
+ PSDMR_PRETOACT_2W |\
+ PSDMR_ACTTORW_2W |\
+ PSDMR_LDOTOPRE_1C |\
+ PSDMR_WRC_2C |\
+ PSDMR_EAMUX |\
+ PSDMR_CL_2)
+
+ /* SDRAM initialization values for 9-column chips
+ */
+#define CFG_OR1_9COL (CFG_MIN_AM_MASK |\
+ ORxS_BPD_4 |\
+ ORxS_ROWST_PBI1_A5 |\
+ ORxS_NUMR_13)
+
+#define CFG_PSDMR_9COL (PSDMR_PBI |\
+ PSDMR_SDAM_A16_IS_A5 |\
+ PSDMR_BSMA_A12_A14 |\
+ PSDMR_SDA10_PBI1_A7 |\
+ PSDMR_RFRC_7_CLK |\
+ PSDMR_PRETOACT_2W |\
+ PSDMR_ACTTORW_2W |\
+ PSDMR_LDOTOPRE_1C |\
+ PSDMR_WRC_2C |\
+ PSDMR_EAMUX |\
+ PSDMR_CL_2)
+
+/* Bank 2 - Local bus SDRAM
+ */
+#ifdef CFG_INIT_LOCAL_SDRAM
+#define CFG_BR2_PRELIM ((SDRAM_BASE2_PRELIM & BRx_BA_MSK) |\
+ BRx_PS_32 |\
+ BRx_MS_SDRAM_L |\
+ BRx_V)
+
+#define CFG_OR2_PRELIM CFG_OR2_8COL
+
+#define SDRAM_BASE2_PRELIM 0x80000000
+
+ /* SDRAM initialization values for 8-column chips
+ */
+#define CFG_OR2_8COL (CFG_MIN_AM_MASK |\
+ ORxS_BPD_4 |\
+ ORxS_ROWST_PBI1_A8 |\
+ ORxS_NUMR_12)
+
+#define CFG_LSDMR_8COL (PSDMR_PBI |\
+ PSDMR_SDAM_A15_IS_A5 |\
+ PSDMR_BSMA_A13_A15 |\
+ PSDMR_SDA10_PBI1_A9 |\
+ PSDMR_RFRC_7_CLK |\
+ PSDMR_PRETOACT_2W |\
+ PSDMR_ACTTORW_2W |\
+ PSDMR_BL |\
+ PSDMR_LDOTOPRE_1C |\
+ PSDMR_WRC_2C |\
+ PSDMR_CL_2)
+
+ /* SDRAM initialization values for 9-column chips
+ */
+#define CFG_OR2_9COL (CFG_MIN_AM_MASK |\
+ ORxS_BPD_4 |\
+ ORxS_ROWST_PBI1_A6 |\
+ ORxS_NUMR_13)
+
+#define CFG_LSDMR_9COL (PSDMR_PBI |\
+ PSDMR_SDAM_A16_IS_A5 |\
+ PSDMR_BSMA_A13_A15 |\
+ PSDMR_SDA10_PBI1_A8 |\
+ PSDMR_RFRC_7_CLK |\
+ PSDMR_PRETOACT_2W |\
+ PSDMR_ACTTORW_2W |\
+ PSDMR_BL |\
+ PSDMR_LDOTOPRE_1C |\
+ PSDMR_WRC_2C |\
+ PSDMR_CL_2)
+
+#endif /* CFG_INIT_LOCAL_SDRAM */
+
+#endif /* CFG_RAMBOOT */
+
+#endif /* __CONFIG_H */
CFG_CMD_PCI | \
CFG_CMD_IRQ | \
CFG_CMD_KGDB | \
- CFG_CMD_DHCP)
+ CFG_CMD_DHCP | \
+ CFG_CMD_BEDBUG )
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include <cmd_confdefs.h>
CFG_CMD_PCMCIA | \
CFG_CMD_PCI | \
CFG_CMD_DATE | \
- CFG_CMD_EEPROM ))
+ CFG_CMD_BEDBUG | \
+ CFG_CMD_EEPROM ) )
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include <cmd_confdefs.h>
#else
#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \
CFG_CMD_EEPROM | \
+ CFG_CMD_DHCP | \
CFG_CMD_DATE | \
CFG_CMD_IDE | \
CFG_CMD_BSP )
-/* CFG_CMD_DHCP */
#endif
#define CONFIG_MAC_PARTITION
#define CONFIG_DOS_PARTITION
/*
- * (C) Copyright 2000
+ * (C) Copyright 2000, 2001
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
#define AMD_ID_DL324B 0x225F225F /* 29DL324B ID (32 M, bottom boot sect) */
#define AMD_ID_DL640 0x227E227E /* 29DL640D ID (64 M, dual boot sectors)*/
+#define AMD_ID_LV640U 0x22D722D7 /* 29LV640U ID (64 M, uniform sectors) */
#define SST_ID_xF200A 0x27892789 /* 39xF200A ID ( 2M = 128K x 16 ) */
#define SST_ID_xF400A 0x27802780 /* 39xF400A ID ( 4M = 256K x 16 ) */
#define FLASH_28F160S3 0x0086 /* Intel 28F160S3 ( 16M = 512K x 32 ) */
#define FLASH_28F320S3 0x0088 /* Intel 28F320S3 ( 32M = 512K x 64 ) */
#define FLASH_28F320C3 0x0089 /* Intel 28F320C3 ( 32M = 64Kx8 + 512x64)*/
+#define FLASH_AM640U 0x0090 /* AMD Am29LV640U ( 64M = 4M x 16 ) */
#define FLASH_UNKNOWN 0xFFFF /* unknown flash type */
#endif
-#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || defined (CONFIG_WALNUT405)
+#if defined(CONFIG_CPCI405) || defined(CONFIG_AR405) || \
+ defined (CONFIG_WALNUT405) || defined (CONFIG_ERIC)
-void i2c_receive(unsigned char address,
+void i2c_init(void);
+int i2c_receive(unsigned char address,
unsigned short size_to_expect, unsigned char datain[] );
-void i2c_send(unsigned char address,
+int i2c_send(unsigned char address,
unsigned short size_to_send, unsigned char dataout[] );
-#else /* !CPCI405, !AR405, !WALNUT405 */
+#else /* !CPCI405, !AR405, !WALNUT405, !ERIC */
#define I2C_RXTX_LEN 128 /* maximum tx/rx buffer length */
* r21, r22 (SRR0), and r23 (SRR1).
*/
+/*
+ * Critical exception entry code. This is just like the other exception
+ * code except that it uses SRR2 and SRR3 instead of SRR0 and SRR1.
+ */
+#define CRITICAL_EXCEPTION_PROLOG \
+ mtspr SPRG0,r20; \
+ mtspr SPRG1,r21; \
+ mfcr r20; \
+ subi r21,r1,INT_FRAME_SIZE+STACK_UNDERHEAD; /* alloc exc. frame */\
+ stw r20,_CCR(r21); /* save registers */ \
+ stw r22,GPR22(r21); \
+ stw r23,GPR23(r21); \
+ mfspr r20,SPRG0; \
+ stw r20,GPR20(r21); \
+ mfspr r22,SPRG1; \
+ stw r22,GPR21(r21); \
+ mflr r20; \
+ stw r20,_LINK(r21); \
+ mfctr r22; \
+ stw r22,_CTR(r21); \
+ mfspr r20,XER; \
+ stw r20,_XER(r21); \
+ mfspr r22,990; /* SRR2 */ \
+ mfspr r23,991; /* SRR3 */ \
+ stw r0,GPR0(r21); \
+ stw r1,GPR1(r21); \
+ stw r2,GPR2(r21); \
+ stw r1,0(r21); \
+ mr r1,r21; /* set new kernel sp */ \
+ SAVE_4GPRS(3, r21);
+/*
+ * Note: code which follows this uses cr0.eq (set if from kernel),
+ * r21, r22 (SRR2), and r23 (SRR3).
+ */
+
/*
* Exception vectors.
*
.long int_return - _start + EXC_OFF_SYS_RESET
+#define CRIT_EXCEPTION(n, label, hdlr) \
+ . = n; \
+label: \
+ CRITICAL_EXCEPTION_PROLOG; \
+ lwz r3,GOT(transfer_to_handler); \
+ mtlr r3; \
+ addi r3,r1,STACK_FRAME_OVERHEAD; \
+ li r20,MSR_KERNEL; \
+ rlwimi r20,r23,0,25,25; \
+ blrl ; \
+.L_ ## label : \
+ .long hdlr - _start + EXC_OFF_SYS_RESET; \
+ .long crit_return - _start + EXC_OFF_SYS_RESET
+
#endif /* __PPC_ASM_TMPL__ */
#if defined(CONFIG_CPCI405) || \
defined(CONFIG_AR405) || \
defined (CONFIG_WALNUT405) || \
- defined (CONFIG_CPCIISER4)
+ defined (CONFIG_CPCIISER4) || \
+ defined (CONFIG_ERIC)
/* $(CPU)/405gp_pci.c */
void pci_init (void);
void pciinfo (int);
defined(CONFIG_CANBT) || \
defined(CONFIG_WALNUT405) || \
defined(CONFIG_CPCIISER4) || \
- defined(CONFIG_LWMON)
+ defined(CONFIG_LWMON) || \
+ defined(CONFIG_TQM8260)
/* $(BOARD)/eeprom.c */
void eeprom_init (void);
void eeprom_read (unsigned offset, uchar *buffer, unsigned cnt);
#ifndef __VERSION_H__
#define __VERSION_H__
-#define PPCBOOT_VERSION "PPCBoot 0.9.3"
+#define PPCBOOT_VERSION "PPCBoot 1.0.0-pre1"
#endif /* __VERSION_H__ */
#define DEBUG_BOOTP_EXT 1 /* Debug received vendor fields */
#endif
+#ifdef DEBUG_BOOTP_EXT
+#define debug_ext(fmt,args...) printf (fmt ,##args)
+#else
+#define debug_ext(fmt,args...)
+#endif
+
#include <ppcboot.h>
#include <command.h>
#include "net.h"
if (bp->bp_id != BootpID)
retval = -6;
-#ifdef DEBUG
- printf("Filtering pkt = %d\n", retval);
-#endif
+ debug ("Filtering pkt = %d\n", retval);
+
return retval;
}
NetServerIP = bp->bp_siaddr;
NetCopyEther(NetServerEther, ((Ethernet_t *)NetRxPkt)->et_src);
copy_filename (BootFile, bp->bp_file, sizeof(BootFile));
-#ifdef DEBUG
- printf("Bootfile: %s\n", BootFile);
-#endif
+
+ debug ("Bootfile: %s\n", BootFile);
/* Propagate to environment */
setenv ("bootfile", BootFile);
{
int size = *(ext+1) ;
-#ifdef DEBUG_BOOTP_EXT
- printf("[BOOTP] Processing extension %d... (%d bytes)\n", *ext, *(ext+1));
-#endif
+ debug_ext ("[BOOTP] Processing extension %d... (%d bytes)\n", *ext, *(ext+1));
NetBootFileSize = 0;
static void BootpVendorProcess(u8 *ext, int size)
{
u8 *end = ext + size ;
-#ifdef DEBUG_BOOTP_EXT
- printf("[BOOTP] Checking extension (%d bytes)...\n", size);
-#endif
+
+ debug_ext ("[BOOTP] Checking extension (%d bytes)...\n", size);
+
while ((ext < end) && (*ext != 0xff)) {
if (*ext == 0) {
ext ++ ;
Bootp_t *bp;
char *s;
-#ifdef DEBUG
- printf("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%d)\n",
+ debug ("got BOOTP packet (src=%d, dst=%d, len=%d want_len=%d)\n",
src, dest, len, sizeof (Bootp_t));
-#endif /* DEBUG */
bp = (Bootp_t *)pkt;
- if ( BootpCheckPkt(pkt, dest, src, len) ) /* Filter out pkts we don't want */
+ if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
return;
/*
NetSetTimeout(0, (thand_f *)0);
-#ifdef DEBUG
- printf("Got good BOOTP\n");
-#endif /* DEBUG */
+ debug ("Got good BOOTP\n");
if (((s = getenv("autoload")) != NULL) && (*s == 'n')) {
/*
case 3:
NetOurGatewayIP = *(IPaddr_t *)(popt + 2);
break;
- case 53:
- break; /* Ignore Message Type Option */
- case 54:
- NetServerIP = *(IPaddr_t *)(popt+2);
+ case 6:
+ NetOurDNSIP = *(IPaddr_t *)(popt +2);
+ break;
+ case 12:
+ memcpy(&NetOurHostName, popt+2, oplen);
+ NetOurHostName[oplen] = 0 ;
+ break;
+ case 15: /* Ignore Domain Name Option */
+ break;
+ case 17:
+ memcpy(&NetOurRootPath, popt+2, oplen);
+ NetOurRootPath[oplen] = 0 ;
break;
case 51:
dhcp_leasetime = *(unsigned int *)(popt + 2);
break;
+ case 53: /* Ignore Message Type Option */
+ break;
+ case 54:
+ NetServerIP = *(IPaddr_t *)(popt+2);
+ break;
+ case 58: /* Ignore Renewal Time Option */
+ break;
+ case 59: /* Ignore Rebinding Time Option */
+ break;
default:
printf("*** Unhandled DHCP Option in OFFER/ACK: %d\n",
*popt);
Bootp_t *bp;
int pktlen, iplen, extlen;
-#ifdef DEBUG
- printf("DhcpSendRequestPkt: Sending DHCPREQUEST\n");
-#endif
+ debug ("DhcpSendRequestPkt: Sending DHCPREQUEST\n");
pkt = NetTxPacket;
memset ((void*)pkt, 0, PKTSIZE);
bp->bp_hlen = HWL_ETHER;
bp->bp_hops = 0;
bp->bp_secs = SWAP16( get_timer(0) / CFG_HZ);
- bp->bp_ciaddr = bp_offer->bp_ciaddr;
+ bp->bp_ciaddr = bp_offer->bp_ciaddr;
bp->bp_yiaddr = bp_offer->bp_yiaddr;
bp->bp_siaddr = bp_offer->bp_siaddr;
bp->bp_giaddr = bp_offer->bp_giaddr;
iplen = BOOTP_HDR_SIZE - sizeof(bp->bp_vend) + extlen;
NetSetIP(iphdr, 0xffffffffL, PORT_BOOTPS, PORT_BOOTPC, iplen);
- printf("Transmitting packet: len = %d\n", pktlen);
+ debug ("Transmitting DHCPREQUEST packet: len = %d\n", pktlen);
NetSendPacket(NetTxPacket, pktlen);
}
DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len)
{
Bootp_t *bp = (Bootp_t *)pkt;
+
+ debug ("DHCPHandler: got packet: (src=%d, dst=%d, len=%d) state: %d\n",
+ src, dest, len, dhcp_state);
+
if (BootpCheckPkt(pkt, dest, src, len)) /* Filter out pkts we don't want */
return;
-#ifdef DEBUG
- printf("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state: %d\n",
+ debug ("DHCPHandler: got DHCP packet: (src=%d, dst=%d, len=%d) state: %d\n",
src, dest, len, dhcp_state);
-#endif /* DEBUG */
switch (dhcp_state) {
case SELECTING:
* If filename is in format we recognize, assume it is a valid
* OFFER from a server we want.
*/
-#ifdef DEBUG
- printf("DHCP: state=SELECTING bp_file: \"%s\"\n", bp->bp_file);
-#endif
+ debug ("DHCP: state=SELECTING bp_file: \"%s\"\n", bp->bp_file);
#ifdef CFG_BOOTFILE_PREFIX
if (strncmp(bp->bp_file,
CFG_BOOTFILE_PREFIX,
strlen(CFG_BOOTFILE_PREFIX)) == 0 ) {
#endif /* CFG_BOOTFILE_PREFIX */
-#ifdef DEBUG
- printf("TRANSITIONING TO REQUESTING STATE\n");
-#endif
+ debug ("TRANSITIONING TO REQUESTING STATE\n");
dhcp_state = REQUESTING;
+#if 0
if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
DhcpOptionsProcess(&bp->bp_vend[4]);
+#endif
BootpCopyNetParams(bp); /* Store net params from reply */
NetSetTimeout(TIMEOUT * CFG_HZ, BootpTimeout);
return;
break;
case REQUESTING:
-#ifdef DEBUG
- printf("DHCP State: REQUESTING\n");
-#endif
+ debug ("DHCP State: REQUESTING\n");
+
if ( DhcpMessageType(bp->bp_vend) == DHCP_ACK ) {
+ if ((*(uint *)bp->bp_vend) == BOOTP_VENDOR_MAGIC)
+ DhcpOptionsProcess(&bp->bp_vend[4]);
+ BootpCopyNetParams(bp); /* Store net params from reply */
dhcp_state = BOUND;
- printf("DhcpHandler: Client BOUND to address ");
+ printf("DHCP client bound to address ");
print_IPaddr(NetOurIP);
printf("\n");
#if 0 /* Not much point in configuring PPCBoot w/o loading boot file - CLH */
}
break;
default:
- printf("DHCP State: INVALID STATE\n");
+ printf("DHCP: INVALID STATE\n");
break;
}
#if (CONFIG_COMMANDS & CFG_CMD_NET)
-#undef ET_DEBUG
+#if 0
+#define ET_DEBUG
+#endif
/** BOOTP EXTENTIONS **/
#ifdef ET_DEBUG
printf("Got IP\n");
#endif
- if (len < IP_HDR_SIZE)
+ if (len < IP_HDR_SIZE) {
+ debug ("len bad %d < %d\n", len, IP_HDR_SIZE);
return;
+ }
if (len < SWAP16(ip->ip_len)) {
printf("len bad %d < %d\n", len, SWAP16(ip->ip_len));
return;
#ifdef ET_DEBUG
printf("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff);
#endif
- if ((ip->ip_hl_v & 0xf0) != 0x40)
+ if ((ip->ip_hl_v & 0xf0) != 0x40) {
return;
- if (ip->ip_off & SWAP16c(0x1fff)) /* Can't deal w/ fragments */
+ }
+ if (ip->ip_off & SWAP16c(0x1fff)) { /* Can't deal w/ fragments */
return;
+ }
if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
printf("checksum bad\n");
return;
}
- if (NetOurIP && ip->ip_dst != NetOurIP)
+ if (NetOurIP &&
+ ip->ip_dst != NetOurIP &&
+ ip->ip_dst != 0xFFFFFFFF) {
return;
+ }
/*
* watch for ICMP host redirects
*