From: wdenk Date: Fri, 1 Jun 2001 23:57:50 +0000 (+0000) Subject: * Added bedbug (http://www.mindspring.com/~wlp/bedbug.html) embedded X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=09997f29283029c618413d048716f6b349b8e270;p=users%2Frw%2Fppcboot.git * 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 * Fixed some DHCP problems --- diff --git a/CHANGELOG b/CHANGELOG index d391e0a..5403252 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -56,6 +56,12 @@ To do: 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 diff --git a/CREDITS b/CREDITS index 076b1d0..f803ac8 100644 --- a/CREDITS +++ b/CREDITS @@ -104,6 +104,10 @@ N: Frank Morauf 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 diff --git a/MAKEALL b/MAKEALL index ef98a3d..ed07af7 100755 --- a/MAKEALL +++ b/MAKEALL @@ -53,6 +53,7 @@ LIST="$LIST \ ######################################################################### LIST="$LIST \ + TQM8260 \ hymod \ cogent_mpc8260 \ rsdproto \ diff --git a/Makefile b/Makefile index d8bcc95..14fcb0b 100644 --- a/Makefile +++ b/Makefile @@ -422,6 +422,14 @@ RPXsuper_config: unconfig echo "CPU = mpc8260" >>config.mk ; \ echo "#include " >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.h + ######################################################################### clean: diff --git a/board/eric/flash.c b/board/eric/flash.c index deae93a..f688a29 100644 --- a/board/eric/flash.c +++ b/board/eric/flash.c @@ -81,10 +81,17 @@ unsigned long flash_init (void) 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; } @@ -123,11 +130,18 @@ unsigned long flash_init (void) 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]); diff --git a/board/tqm8260/Makefile b/board/tqm8260/Makefile new file mode 100644 index 0000000..35b8428 --- /dev/null +++ b/board/tqm8260/Makefile @@ -0,0 +1,40 @@ +# +# (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 + +######################################################################### diff --git a/board/tqm8260/config.mk b/board/tqm8260/config.mk new file mode 100644 index 0000000..673f622 --- /dev/null +++ b/board/tqm8260/config.mk @@ -0,0 +1,34 @@ +# +# (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) diff --git a/board/tqm8260/flash.c b/board/tqm8260/flash.c new file mode 100644 index 0000000..50c2559 --- /dev/null +++ b/board/tqm8260/flash.c @@ -0,0 +1,421 @@ +/* + * (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 +#include + +#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>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; isector_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); +} + diff --git a/board/tqm8260/ppcboot.lds b/board/tqm8260/ppcboot.lds new file mode 100644 index 0000000..5df4cdb --- /dev/null +++ b/board/tqm8260/ppcboot.lds @@ -0,0 +1,118 @@ +/* + * (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 = .); +} + diff --git a/board/tqm8260/tqm8260.c b/board/tqm8260/tqm8260.c new file mode 100644 index 0000000..4574df3 --- /dev/null +++ b/board/tqm8260/tqm8260.c @@ -0,0 +1,356 @@ +/* + * (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 +#include +#include + +/* + * 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); +} + diff --git a/common/Makefile b/common/Makefile index 52b2989..e8f8015 100644 --- a/common/Makefile +++ b/common/Makefile @@ -33,7 +33,7 @@ COBJS = board.o main.o command.o \ 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) diff --git a/common/bedbug.c b/common/bedbug.c new file mode 100644 index 0000000..1158a08 --- /dev/null +++ b/common/bedbug.c @@ -0,0 +1,1291 @@ +/* $Id: bedbug.c,v 1.1 2001/05/31 22:12:25 wd Exp $ */ + +#include +#include +#include +#include +#include +#include + +#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*)); + + +/*====================================================================== + * 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: IIIIIIII disassembly" where, + XXXXXXXX is the memory address in hex, + 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 */ + + + +/*====================================================================== + * 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 */ + + + +/*====================================================================== + * 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 */ + + + +/*====================================================================== + * 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 */ + + + +/*====================================================================== + * 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 */ + + + +/*====================================================================== + * 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 */ + + + +/*====================================================================== + * 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 */ + + + +/*====================================================================== + * 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 */ + + + +/*====================================================================== + * 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 */ + + + +/*====================================================================== + * 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 */ + + + +/*====================================================================== + * 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 */ + + + +/*====================================================================== + * 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 */ + + + +/*====================================================================== + * 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 */ + + + +/*====================================================================== + * 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 */ + + + +/*====================================================================== + * 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 */ + + + +/*====================================================================== + * 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. + */ diff --git a/common/board.c b/common/board.c index 3ff007c..96e1941 100644 --- a/common/board.c +++ b/common/board.c @@ -40,6 +40,9 @@ #if (CONFIG_COMMANDS & CFG_CMD_NET) #include #endif +#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG) +#include +#endif #ifdef CFG_ALLOC_DPRAM #include #endif @@ -600,6 +603,10 @@ void board_init_r (bd_t *bd, ulong dest_addr) 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); diff --git a/common/cmd_bedbug.c b/common/cmd_bedbug.c new file mode 100644 index 0000000..ad1ac45 --- /dev/null +++ b/common/cmd_bedbug.c @@ -0,0 +1,653 @@ +/* + * BedBug Functions + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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 */ + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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 ("\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 */ + + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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. + */ diff --git a/common/cmd_i2c.c b/common/cmd_i2c.c index 10c3675..7826066 100644 --- a/common/cmd_i2c.c +++ b/common/cmd_i2c.c @@ -1,5 +1,5 @@ /* - * (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 @@ -49,7 +49,15 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) 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) { @@ -61,7 +69,12 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) 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; } @@ -74,7 +87,12 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) 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; } @@ -84,7 +102,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) 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); @@ -96,17 +114,39 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) #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; @@ -114,7 +154,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) 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); @@ -122,16 +162,36 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) 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; @@ -143,7 +203,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) 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); @@ -153,17 +213,37 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) "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; @@ -172,7 +252,7 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) 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); @@ -182,17 +262,36 @@ do_i2c (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) "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; diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index 6e2e277..ca902c0 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -728,27 +728,30 @@ void do_saveenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) { 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 */ diff --git a/common/command.c b/common/command.c index 5c10a90..5447686 100644 --- a/common/command.c +++ b/common/command.c @@ -53,6 +53,8 @@ #include #endif +#include + /* * HELP command */ @@ -188,6 +190,10 @@ cmd_tbl_t *find_cmd(const char *cmd) 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 @@ -258,6 +264,15 @@ cmd_tbl_t cmd_tbl[] = { 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 ) }; diff --git a/cpu/mpc8260/Makefile b/cpu/mpc8260/Makefile index b013d57..5be5f99 100644 --- a/cpu/mpc8260/Makefile +++ b/cpu/mpc8260/Makefile @@ -27,7 +27,7 @@ LIB = lib$(CPU).a 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) diff --git a/cpu/mpc8260/ether_fcc.c b/cpu/mpc8260/ether_fcc.c index 9b5f67b..492b67f 100644 --- a/cpu/mpc8260/ether_fcc.c +++ b/cpu/mpc8260/ether_fcc.c @@ -70,7 +70,6 @@ #if defined(CONFIG_RPXSUPER) #error "on RPX Super ethernet must be FCC3" #endif - #elif (CONFIG_ETHER_INDEX == 2) #define PROFF_ENET PROFF_FCC2 @@ -118,6 +117,19 @@ #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) diff --git a/cpu/mpc8260/ether_scc.c b/cpu/mpc8260/ether_scc.c index ef47605..5512999 100644 --- a/cpu/mpc8260/ether_scc.c +++ b/cpu/mpc8260/ether_scc.c @@ -54,6 +54,16 @@ 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 @@ -208,7 +218,7 @@ int eth_init(bd_t *bis) /* 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); diff --git a/cpu/mpc8260/soft_i2c.c b/cpu/mpc8260/soft_i2c.c new file mode 100644 index 0000000..882483b --- /dev/null +++ b/cpu/mpc8260/soft_i2c.c @@ -0,0 +1,381 @@ +/* + * (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 +#include +#include + +#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 */ +/*----------------------------------------------------------------------- + */ diff --git a/cpu/mpc8260/start.S b/cpu/mpc8260/start.S index 2c45fd6..29e4a81 100644 --- a/cpu/mpc8260/start.S +++ b/cpu/mpc8260/start.S @@ -1,7 +1,7 @@ /* * Copyright (C) 1998 Dan Malek * Copyright (C) 1999 Magnus Damm - * Copyright (C) 2000 Wolfgang Denk + * Copyright (C) 2000, 2001 Wolfgang Denk * * See file CREDITS for list of people who contributed to this * project. @@ -95,7 +95,7 @@ version_string: * 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 diff --git a/cpu/ppc4xx/Makefile b/cpu/ppc4xx/Makefile index ea73eb3..db81d2b 100644 --- a/cpu/ppc4xx/Makefile +++ b/cpu/ppc4xx/Makefile @@ -27,7 +27,7 @@ LIB = lib$(CPU).a 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) diff --git a/cpu/ppc4xx/bedbug_405.c b/cpu/ppc4xx/bedbug_405.c new file mode 100644 index 0000000..5fb939f --- /dev/null +++ b/cpu/ppc4xx/bedbug_405.c @@ -0,0 +1,321 @@ +/* + * Bedbug Functions specific to the PPC405 chip + */ + +#include +#include +#include + +#include +#include +#include +#include + +#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)); + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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 */ + + + +/* ====================================================================== + * 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 + diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S index c454dc1..80e8fe2 100644 --- a/cpu/ppc4xx/start.S +++ b/cpu/ppc4xx/start.S @@ -371,12 +371,13 @@ ProgramCheck: 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 @@ -453,6 +454,36 @@ int_return: 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: diff --git a/cpu/ppc4xx/traps.c b/cpu/ppc4xx/traps.c index c4fc6af..538022c 100644 --- a/cpu/ppc4xx/traps.c +++ b/cpu/ppc4xx/traps.c @@ -53,6 +53,23 @@ static __inline__ void set_tsr(unsigned long val) 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 @@ -176,12 +193,23 @@ AlignmentException(struct pt_regs *regs) 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"); } @@ -214,6 +242,16 @@ UnknownException(struct pt_regs *regs) _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. */ diff --git a/doc/README.bedbug b/doc/README.bedbug new file mode 100644 index 0000000..109e8cb --- /dev/null +++ b/doc/README.bedbug @@ -0,0 +1,62 @@ +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. + diff --git a/include/bedbug/bedbug.h b/include/bedbug/bedbug.h new file mode 100644 index 0000000..10c4102 --- /dev/null +++ b/include/bedbug/bedbug.h @@ -0,0 +1,42 @@ +/* $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. + */ diff --git a/include/bedbug/elf.h b/include/bedbug/elf.h new file mode 100644 index 0000000..a6e3d20 --- /dev/null +++ b/include/bedbug/elf.h @@ -0,0 +1,582 @@ +/* $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 */ +/* #include */ + +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_ */ diff --git a/include/bedbug/ppc.h b/include/bedbug/ppc.h new file mode 100644 index 0000000..29fa840 --- /dev/null +++ b/include/bedbug/ppc.h @@ -0,0 +1,413 @@ +/* $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 */ + + +/*====================================================================== + * + * 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. + */ diff --git a/include/bedbug/regs.h b/include/bedbug/regs.h new file mode 100644 index 0000000..93c7e0c --- /dev/null +++ b/include/bedbug/regs.h @@ -0,0 +1,397 @@ +/* $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. + */ diff --git a/include/bedbug/tables.h b/include/bedbug/tables.h new file mode 100644 index 0000000..f04c6c8 --- /dev/null +++ b/include/bedbug/tables.h @@ -0,0 +1,601 @@ +/* $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. + */ + diff --git a/include/cmd_bedbug.h b/include/cmd_bedbug.h new file mode 100644 index 0000000..8ab502e --- /dev/null +++ b/include/cmd_bedbug.h @@ -0,0 +1,138 @@ +/* + * 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
[# instructions]\n" \ + ), + +#define CMD_TBL_ASM MK_CMD_TBL_ENTRY( \ + "as", 2, 2, 0, do_bedbug_asm, \ + "as - assemble memory\n", \ + "as
\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
- Break at an address\n" \ + "break off - 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. + */ diff --git a/include/cmd_confdefs.h b/include/cmd_confdefs.h index 8c0a56a..d25a134 100644 --- a/include/cmd_confdefs.h +++ b/include/cmd_confdefs.h @@ -56,7 +56,8 @@ #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 */ @@ -76,6 +77,7 @@ CFG_CMD_REGINFO | \ CFG_CMD_IMMAP | \ CFG_CMD_DATE | \ + CFG_CMD_BEDBUG | \ CFG_CMD_BSP ) /* Default configuration diff --git a/include/config_ERIC.h b/include/config_ERIC.h index 65571ca..fb4a3d9 100644 --- a/include/config_ERIC.h +++ b/include/config_ERIC.h @@ -293,7 +293,7 @@ #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 diff --git a/include/config_LANTEC.h b/include/config_LANTEC.h index 6867962..baf4e10 100644 --- a/include/config_LANTEC.h +++ b/include/config_LANTEC.h @@ -87,7 +87,8 @@ & ~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 */ diff --git a/include/config_TQM823L.h b/include/config_TQM823L.h index 2d146d1..9779a9e 100644 --- a/include/config_TQM823L.h +++ b/include/config_TQM823L.h @@ -74,6 +74,7 @@ #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) */ diff --git a/include/config_TQM8260.h b/include/config_TQM8260.h new file mode 100644 index 0000000..3b773ce --- /dev/null +++ b/include/config_TQM8260.h @@ -0,0 +1,494 @@ +/* + * (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 + +/* + * 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 */ diff --git a/include/config_WALNUT405.h b/include/config_WALNUT405.h index 540627f..bd0d168 100644 --- a/include/config_WALNUT405.h +++ b/include/config_WALNUT405.h @@ -78,7 +78,8 @@ 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 diff --git a/include/config_hymod.h b/include/config_hymod.h index 9f5fb57..8b7cf7a 100644 --- a/include/config_hymod.h +++ b/include/config_hymod.h @@ -93,7 +93,8 @@ 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 diff --git a/include/config_lwmon.h b/include/config_lwmon.h index 44d0680..25c6a3b 100644 --- a/include/config_lwmon.h +++ b/include/config_lwmon.h @@ -81,10 +81,10 @@ #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 diff --git a/include/flash.h b/include/flash.h index 98a5d22..9510e4c 100644 --- a/include/flash.h +++ b/include/flash.h @@ -1,5 +1,5 @@ /* - * (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 @@ -112,6 +112,7 @@ int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt); #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 ) */ @@ -198,6 +199,7 @@ int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt); #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 */ diff --git a/include/i2c.h b/include/i2c.h index d554c1d..953fc62 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -21,14 +21,16 @@ void i2c_write (uchar *addr, int alen, uchar *buffer, int len); #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 */ diff --git a/include/ppc_asm.tmpl b/include/ppc_asm.tmpl index f939b38..29b1cda 100644 --- a/include/ppc_asm.tmpl +++ b/include/ppc_asm.tmpl @@ -231,6 +231,41 @@ * 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. * @@ -253,4 +288,18 @@ label: \ .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__ */ diff --git a/include/ppcboot.h b/include/ppcboot.h index 0e866b0..46889c2 100644 --- a/include/ppcboot.h +++ b/include/ppcboot.h @@ -183,7 +183,8 @@ void inline setenv (char *, char *); #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); @@ -217,7 +218,8 @@ void reset_phy (void); 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); diff --git a/include/version.h b/include/version.h index bb68a35..1f74ebe 100644 --- a/include/version.h +++ b/include/version.h @@ -24,6 +24,6 @@ #ifndef __VERSION_H__ #define __VERSION_H__ -#define PPCBOOT_VERSION "PPCBoot 0.9.3" +#define PPCBOOT_VERSION "PPCBoot 1.0.0-pre1" #endif /* __VERSION_H__ */ diff --git a/net/bootp.c b/net/bootp.c index de4cbc2..8ad82c7 100644 --- a/net/bootp.c +++ b/net/bootp.c @@ -12,6 +12,12 @@ #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 #include #include "net.h" @@ -81,9 +87,8 @@ static int BootpCheckPkt(uchar *pkt, unsigned dest, unsigned src, unsigned len) if (bp->bp_id != BootpID) retval = -6; -#ifdef DEBUG - printf("Filtering pkt = %d\n", retval); -#endif + debug ("Filtering pkt = %d\n", retval); + return retval; } @@ -96,9 +101,8 @@ void BootpCopyNetParams(Bootp_t *bp) 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); @@ -109,9 +113,7 @@ static void BootpVendorFieldProcess(u8 *ext) { 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; @@ -197,9 +199,9 @@ static void BootpVendorFieldProcess(u8 *ext) 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 ++ ; @@ -252,14 +254,12 @@ BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) 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; /* @@ -277,9 +277,7 @@ BootpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) 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')) { /* @@ -596,14 +594,31 @@ void DhcpOptionsProcess(char *popt) 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); @@ -633,9 +648,7 @@ void DhcpSendRequestPkt(Bootp_t *bp_offer) 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); @@ -651,7 +664,7 @@ void DhcpSendRequestPkt(Bootp_t *bp_offer) 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; @@ -672,7 +685,7 @@ void DhcpSendRequestPkt(Bootp_t *bp_offer) 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); } @@ -683,13 +696,15 @@ static void 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: @@ -699,22 +714,20 @@ DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) * 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); @@ -726,12 +739,14 @@ DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) 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 */ @@ -746,7 +761,7 @@ DhcpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) } break; default: - printf("DHCP State: INVALID STATE\n"); + printf("DHCP: INVALID STATE\n"); break; } diff --git a/net/net.c b/net/net.c index 0e03cce..443e208 100644 --- a/net/net.c +++ b/net/net.c @@ -68,7 +68,9 @@ #if (CONFIG_COMMANDS & CFG_CMD_NET) -#undef ET_DEBUG +#if 0 +#define ET_DEBUG +#endif /** BOOTP EXTENTIONS **/ @@ -440,8 +442,10 @@ NetReceive(volatile uchar * pkt, int len) #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; @@ -450,16 +454,21 @@ NetReceive(volatile uchar * pkt, int len) #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 *