This is the mail archive of the newlib@sources.redhat.com mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Patch to allow programs run from kernel segment 0 on MIPS


Michael Meissner wrote:
> 
> The following patch adds a new linker script to run programs in kernel
> segment 0 (which can be cached) as opposed to kernel segment 1 which
> is always uncached.  The ROM monitor I'm dealing with also doesn't
> like memory sizing from kernel segment 0, so I added code to always
> use kernel segment 1 for sizing memory if the program was linked for
> kernel segment 0 (kernel segment 0 and 1 both address the same memory,
> so it is safe to do this always).  I did test it, doing a build, and
> downloading a program into kernel segment 0, and ran it.  Is it ok to
> apply the patches?
> 

Yes, please go ahead.  You probably should change the copyright to Red Hat
instead of Cygnus Support since you are updating it anyway. 

-- Jeff J.

> 2001-10-15  Michael Meissner  <meissner@redhat.com>
> 
>         * regs.S (K0BASE_ADDR,K1BASE_ADDR): Define as addresses to
>         identify if a program is running in kernel segment 0.
> 
>         * cma101.c (__sizemem): If we are running in kernel segment 0,
>         instead of kernel segment 1, use kernel segment 0 addresses which
>         are uncached when sizing memory.
> 
>         * ddb-kseg0.ld: New file, clone of ddb.ld, except it links the
>         program to run in kernel segment 0, instead of kernel segment 1.
> 
>         * configure.in: Treat ddb-kseg0.ld like ddb.ld.
>         * configure: Regenerate.
> 
> *** libgloss/mips/regs.S.~1~    Fri Mar 17 17:48:51 2000
> --- libgloss/mips/regs.S        Mon Oct 15 16:15:20 2001
> ***************
> *** 56,63 ****
> --- 56,67 ----
>   #define K0BASE                0x80000000
>   #ifndef __mips64
>   #define K1BASE                0xA0000000
> + #define K0BASE_ADDR   ((char *)K0BASE)
> + #define K1BASE_ADDR   ((char *)K1BASE)
>   #else
>   #define K1BASE                0xFFFFFFFFA0000000LL
> + #define K0BASE_ADDR   ((char *)0xFFFFFFFF80000000LL)
> + #define K1BASE_ADDR   ((char *)K1BASE)
>   #endif
> 
>   #define PHYS_TO_K1(a)   ((unsigned)(a) | K1BASE)
> *** libgloss/mips/cma101.c.~1~  Fri Mar 17 17:48:51 2000
> --- libgloss/mips/cma101.c      Mon Oct 15 17:21:11 2001
> ***************
> *** 1,7 ****
>   /*
>    * cma101.c -- lo-level support for Cogent CMA101 development board.
>    *
> !  * Copyright (c) 1996 Cygnus Support
>    *
>    * The authors hereby grant permission to use, copy, modify, distribute,
>    * and license this software and its documentation for any purpose, provided
> --- 1,7 ----
>   /*
>    * cma101.c -- lo-level support for Cogent CMA101 development board.
>    *
> !  * Copyright (c) 1996, 2001 Cygnus Support
>    *
>    * The authors hereby grant permission to use, copy, modify, distribute,
>    * and license this software and its documentation for any purpose, provided
> *************** __sizemem ()
> *** 187,194 ****
> --- 187,200 ----
>     unsigned int baseorig;
>     unsigned int sr;
>     extern void *end;
> +   char *endptr = (char *)&end;
>     int extra;
> 
> +   /* If we are running in kernel segment 0 (possibly cached), try sizing memory
> +      in kernel segment 1 (uncached) to avoid some problems with monitors.  */
> +   if (endptr >= K0BASE_ADDR && endptr < K1BASE_ADDR)
> +     endptr = (endptr - K0BASE_ADDR) + K1BASE_ADDR;
> +
>     INTDISABLE(sr,baseorig); /* disable all interrupt masks */
> 
>     __default_buserr_handler();
> *************** __sizemem ()
> *** 200,207 ****
>        for an int pointer, so we adjust the address to make sure it is safe.
>        We use void * arithmetic to avoid accidentally truncating the pointer.  */
> 
> !   extra = ((int) &end & (sizeof (int) - 1));
> !   base = ((void *) &end + sizeof (int) - extra);
>     baseorig = *base;
> 
>     *base = SM_PATTERN;
> --- 206,213 ----
>        for an int pointer, so we adjust the address to make sure it is safe.
>        We use void * arithmetic to avoid accidentally truncating the pointer.  */
> 
> !   extra = ((int) endptr & (sizeof (int) - 1));
> !   base = ((void *) endptr + sizeof (int) - extra);
>     baseorig = *base;
> 
>     *base = SM_PATTERN;
> *** libgloss/mips/ddb-kseg0.ld.~1~      Mon Oct 15 18:18:51 2001
> --- libgloss/mips/ddb-kseg0.ld  Mon Oct 15 16:16:46 2001
> ***************
> *** 0 ****
> --- 1,154 ----
> + /* The following TEXT start address leaves space for the monitor
> +    workspace. */
> +
> + ENTRY(_start)
> + OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-littlemips")
> + GROUP(-lc -lpmon -lgcc)
> + SEARCH_DIR(.)
> + __DYNAMIC  =  0;
> +
> + /*
> +  * Allocate the stack to be at the top of memory, since the stack
> +  * grows down
> +  */
> + PROVIDE (__stack = 0);
> + /* PROVIDE (__global = 0); */
> +
> + /*
> +  * Initalize some symbols to be zero so we can reference them in the
> +  * crt0 without core dumping. These functions are all optional, but
> +  * we do this so we can have our crt0 always use them if they exist.
> +  * This is so BSPs work better when using the crt0 installed with gcc.
> +  * We have to initalize them twice, so we multiple object file
> +  * formats, as some prepend an underscore.
> +  */
> + PROVIDE (hardware_init_hook = 0);
> + PROVIDE (software_init_hook = 0);
> +
> + SECTIONS
> + {
> +   . = 0x80100000;
> +   .text : {
> +      _ftext = . ;
> +     *(.init)
> +      eprol  =  .;
> +     *(.text)
> +     *(.text.*)
> +     *(.gnu.linkonce.t*)
> +     *(.mips16.fn.*)
> +     *(.mips16.call.*)
> +     PROVIDE (__runtime_reloc_start = .);
> +     *(.rel.sdata)
> +     PROVIDE (__runtime_reloc_stop = .);
> +     *(.fini)
> +      etext  =  .;
> +      _etext  =  .;
> +   }
> +
> +   .ctors    :
> +   {
> +     /* gcc uses crtbegin.o to find the start of
> +        the constructors, so we make sure it is
> +        first.  Because this is a wildcard, it
> +        doesn't matter if the user does not
> +        actually link against crtbegin.o; the
> +        linker won't look for a file to match a
> +        wildcard.  The wildcard also means that it
> +        doesn't matter which directory crtbegin.o
> +        is in.  */
> +
> +     KEEP (*crtbegin.o(.ctors))
> +
> +     /* We don't want to include the .ctor section from
> +        from the crtend.o file until after the sorted ctors.
> +        The .ctor section from the crtend file contains the
> +        end of ctors marker and it must be last */
> +
> +     KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
> +     KEEP (*(SORT(.ctors.*)))
> +     KEEP (*(.ctors))
> +   }
> +
> +   .dtors    :
> +   {
> +     KEEP (*crtbegin.o(.dtors))
> +     KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
> +     KEEP (*(SORT(.dtors.*)))
> +     KEEP (*(.dtors))
> +   }
> +
> +   . = .;
> +   .rdata : {
> +     *(.rdata)
> +     *(.rodata)
> +     *(.rodata.*)
> +     *(.gnu.linkonce.r*)
> +   }
> +    _fdata = ALIGN(16);
> +   .data : {
> +     *(.data)
> +     *(.data.*)
> +     *(.gnu.linkonce.d*)
> +   }
> +   . = ALIGN(8);
> +   _gp = . + 0x8000;
> +   __global = _gp;
> +   .lit8 : {
> +     *(.lit8)
> +   }
> +   .lit4 : {
> +     *(.lit4)
> +   }
> +   .sdata : {
> +     *(.sdata)
> +     *(.sdata.*)
> +     *(.gnu.linkonce.s*)
> +   }
> +   . = ALIGN(4);
> +    edata  =  .;
> +    _edata  =  .;
> +    _fbss = .;
> +   .sbss : {
> +     *(.sbss)
> +     *(.scommon)
> +   }
> +   .bss : {
> +     _bss_start = . ;
> +     *(.bss)
> +     *(COMMON)
> +   }
> +
> +    end = .;
> +    _end = .;
> +
> +   /* DWARF debug sections.
> +      Symbols in the DWARF debugging sections are relative to
> +      the beginning of the section so we begin them at 0.  */
> +
> +   /* DWARF 1 */
> +   .debug          0 : { *(.debug) }
> +   .line           0 : { *(.line) }
> +
> +   /* GNU DWARF 1 extensions */
> +   .debug_srcinfo  0 : { *(.debug_srcinfo) }
> +   .debug_sfnames  0 : { *(.debug_sfnames) }
> +
> +   /* DWARF 1.1 and DWARF 2 */
> +   .debug_aranges  0 : { *(.debug_aranges) }
> +   .debug_pubnames 0 : { *(.debug_pubnames) }
> +
> +   /* DWARF 2 */
> +   .debug_info     0 : { *(.debug_info) }
> +   .debug_abbrev   0 : { *(.debug_abbrev) }
> +   .debug_line     0 : { *(.debug_line) }
> +   .debug_frame    0 : { *(.debug_frame) }
> +   .debug_str      0 : { *(.debug_str) }
> +   .debug_loc      0 : { *(.debug_loc) }
> +   .debug_macinfo  0 : { *(.debug_macinfo) }
> +
> +   /* SGI/MIPS DWARF 2 extensions */
> +   .debug_weaknames 0 : { *(.debug_weaknames) }
> +   .debug_funcnames 0 : { *(.debug_funcnames) }
> +   .debug_typenames 0 : { *(.debug_typenames) }
> +   .debug_varnames  0 : { *(.debug_varnames) }
> + }
> *** libgloss/mips/configure.in.~1~      Mon Oct 15 15:40:24 2001
> --- libgloss/mips/configure.in  Mon Oct 15 16:02:27 2001
> *************** case "${target}" in
> *** 101,107 ****
>     mips64vr5*-*-*)
>         part_specific_obj="vr5xxx.o cma101.o"
>         part_specific_defines=-DR5000
> !         script_list="idt pmon ddb lsi idtecoff nullmon"
>           bsp_list="libidt.a libpmon.a liblsi.a libnullmon.a"
>         ;;
>     mipsisa32*-*-*)
> --- 101,107 ----
>     mips64vr5*-*-*)
>         part_specific_obj="vr5xxx.o cma101.o"
>         part_specific_defines=-DR5000
> !         script_list="idt pmon ddb ddb-kseg0 lsi idtecoff nullmon"
>           bsp_list="libidt.a libpmon.a liblsi.a libnullmon.a"
>         ;;
>     mipsisa32*-*-*)
> *************** case "${target}" in
> *** 113,119 ****
>     *)
>           part_specific_obj="vr4300.o cma101.o"
>         part_specific_defines=
> !         script_list="idt pmon ddb lsi idtecoff nullmon"
>           bsp_list="libidt.a libpmon.a liblsi.a libnullmon.a"
>           ;;
>   esac
> --- 113,119 ----
>     *)
>           part_specific_obj="vr4300.o cma101.o"
>         part_specific_defines=
> !         script_list="idt pmon ddb ddb-kseg0 lsi idtecoff nullmon"
>           bsp_list="libidt.a libpmon.a liblsi.a libnullmon.a"
>           ;;
>   esac
> *** libgloss/mips/configure.~1~ Mon Oct 15 18:19:11 2001
> --- libgloss/mips/configure     Mon Oct 15 18:19:29 2001
> *************** program_suffix=NONE
> *** 28,33 ****
> --- 28,34 ----
>   program_transform_name=s,x,x,
>   silent=
>   site=
> + sitefile=
>   srcdir=
>   target=NONE
>   verbose=
> *************** Configuration:
> *** 142,147 ****
> --- 143,149 ----
>     --help                  print this message
>     --no-create             do not create output files
>     --quiet, --silent       do not print \`checking...' messages
> +   --site-file=FILE        use FILE as the site file
>     --version               print the version of autoconf that created configure
>   Directory and file names:
>     --prefix=PREFIX         install architecture-independent files in PREFIX
> *************** EOF
> *** 312,317 ****
> --- 314,324 ----
>     -site=* | --site=* | --sit=*)
>       site="$ac_optarg" ;;
> 
> +   -site-file | --site-file | --site-fil | --site-fi | --site-f)
> +     ac_prev=sitefile ;;
> +   -site-file=* | --site-file=* | --site-fil=* | --site-fi=* | --site-f=*)
> +     sitefile="$ac_optarg" ;;
> +
>     -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
>       ac_prev=srcdir ;;
>     -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
> *************** fi
> *** 477,488 ****
>   srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
> 
>   # Prefer explicitly selected file to automatically selected ones.
> ! if test -z "$CONFIG_SITE"; then
> !   if test "x$prefix" != xNONE; then
> !     CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
> !   else
> !     CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
>     fi
>   fi
>   for ac_site_file in $CONFIG_SITE; do
>     if test -r "$ac_site_file"; then
> --- 484,499 ----
>   srcdir=`echo "${srcdir}" | sed 's%\([^/]\)/*$%\1%'`
> 
>   # Prefer explicitly selected file to automatically selected ones.
> ! if test -z "$sitefile"; then
> !   if test -z "$CONFIG_SITE"; then
> !     if test "x$prefix" != xNONE; then
> !       CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site"
> !     else
> !       CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site"
> !     fi
>     fi
> + else
> +   CONFIG_SITE="$sitefile"
>   fi
>   for ac_site_file in $CONFIG_SITE; do
>     if test -r "$ac_site_file"; then
> *************** else { echo "configure: error: can not r
> *** 583,589 ****
>   fi
> 
>   echo $ac_n "checking host system type""... $ac_c" 1>&6
> ! echo "configure:587: checking host system type" >&5
> 
>   host_alias=$host
>   case "$host_alias" in
> --- 594,600 ----
>   fi
> 
>   echo $ac_n "checking host system type""... $ac_c" 1>&6
> ! echo "configure:598: checking host system type" >&5
> 
>   host_alias=$host
>   case "$host_alias" in
> *************** host_os=`echo $host | sed 's/^\([^-]*\)-
> *** 604,610 ****
>   echo "$ac_t""$host" 1>&6
> 
>   echo $ac_n "checking target system type""... $ac_c" 1>&6
> ! echo "configure:608: checking target system type" >&5
> 
>   target_alias=$target
>   case "$target_alias" in
> --- 615,621 ----
>   echo "$ac_t""$host" 1>&6
> 
>   echo $ac_n "checking target system type""... $ac_c" 1>&6
> ! echo "configure:619: checking target system type" >&5
> 
>   target_alias=$target
>   case "$target_alias" in
> *************** target_os=`echo $target | sed 's/^\([^-]
> *** 622,628 ****
>   echo "$ac_t""$target" 1>&6
> 
>   echo $ac_n "checking build system type""... $ac_c" 1>&6
> ! echo "configure:626: checking build system type" >&5
> 
>   build_alias=$build
>   case "$build_alias" in
> --- 633,639 ----
>   echo "$ac_t""$target" 1>&6
> 
>   echo $ac_n "checking build system type""... $ac_c" 1>&6
> ! echo "configure:637: checking build system type" >&5
> 
>   build_alias=$build
>   case "$build_alias" in
> *************** test "$program_transform_name" = "" && p
> *** 676,682 ****
>   # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
>   # ./install, which can be erroneously created by make from ./install.sh.
>   echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
> ! echo "configure:680: checking for a BSD compatible install" >&5
>   if test -z "$INSTALL"; then
>   if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
>     echo $ac_n "(cached) $ac_c" 1>&6
> --- 687,693 ----
>   # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
>   # ./install, which can be erroneously created by make from ./install.sh.
>   echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6
> ! echo "configure:691: checking for a BSD compatible install" >&5
>   if test -z "$INSTALL"; then
>   if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then
>     echo $ac_n "(cached) $ac_c" 1>&6
> *************** test -z "$INSTALL_DATA" && INSTALL_DATA=
> *** 740,746 ****
>   # Extract the first word of "gcc", so it can be a program name with args.
>   set dummy gcc; ac_word=$2
>   echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
> ! echo "configure:744: checking for $ac_word" >&5
>   if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
>     echo $ac_n "(cached) $ac_c" 1>&6
>   else
> --- 751,757 ----
>   # Extract the first word of "gcc", so it can be a program name with args.
>   set dummy gcc; ac_word=$2
>   echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
> ! echo "configure:755: checking for $ac_word" >&5
>   if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
>     echo $ac_n "(cached) $ac_c" 1>&6
>   else
> *************** if test -z "$CC"; then
> *** 770,776 ****
>     # Extract the first word of "cc", so it can be a program name with args.
>   set dummy cc; ac_word=$2
>   echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
> ! echo "configure:774: checking for $ac_word" >&5
>   if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
>     echo $ac_n "(cached) $ac_c" 1>&6
>   else
> --- 781,787 ----
>     # Extract the first word of "cc", so it can be a program name with args.
>   set dummy cc; ac_word=$2
>   echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
> ! echo "configure:785: checking for $ac_word" >&5
>   if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then
>     echo $ac_n "(cached) $ac_c" 1>&6
>   else
> *************** fi
> *** 819,825 ****
>   fi
> 
>   echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
> ! echo "configure:823: checking whether we are using GNU C" >&5
>   if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
>     echo $ac_n "(cached) $ac_c" 1>&6
>   else
> --- 830,836 ----
>   fi
> 
>   echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6
> ! echo "configure:834: checking whether we are using GNU C" >&5
>   if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then
>     echo $ac_n "(cached) $ac_c" 1>&6
>   else
> *************** else
> *** 828,834 ****
>     yes;
>   #endif
>   EOF
> ! if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:832: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
>     ac_cv_prog_gcc=yes
>   else
>     ac_cv_prog_gcc=no
> --- 839,845 ----
>     yes;
>   #endif
>   EOF
> ! if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:843: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then
>     ac_cv_prog_gcc=yes
>   else
>     ac_cv_prog_gcc=no
> *************** if test $ac_cv_prog_gcc = yes; then
> *** 843,849 ****
>     ac_save_CFLAGS="$CFLAGS"
>     CFLAGS=
>     echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
> ! echo "configure:847: checking whether ${CC-cc} accepts -g" >&5
>   if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
>     echo $ac_n "(cached) $ac_c" 1>&6
>   else
> --- 854,860 ----
>     ac_save_CFLAGS="$CFLAGS"
>     CFLAGS=
>     echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6
> ! echo "configure:858: checking whether ${CC-cc} accepts -g" >&5
>   if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then
>     echo $ac_n "(cached) $ac_c" 1>&6
>   else
> *************** LD=${LD-ld}
> *** 879,885 ****
>   # Extract the first word of "ranlib", so it can be a program name with args.
>   set dummy ranlib; ac_word=$2
>   echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
> ! echo "configure:883: checking for $ac_word" >&5
>   if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
>     echo $ac_n "(cached) $ac_c" 1>&6
>   else
> --- 890,896 ----
>   # Extract the first word of "ranlib", so it can be a program name with args.
>   set dummy ranlib; ac_word=$2
>   echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
> ! echo "configure:894: checking for $ac_word" >&5
>   if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then
>     echo $ac_n "(cached) $ac_c" 1>&6
>   else
> *************** case "${target}" in
> *** 926,932 ****
>     mips64vr5*-*-*)
>         part_specific_obj="vr5xxx.o cma101.o"
>         part_specific_defines=-DR5000
> !         script_list="idt pmon ddb lsi idtecoff nullmon"
>           bsp_list="libidt.a libpmon.a liblsi.a libnullmon.a"
>         ;;
>     mipsisa32*-*-*)
> --- 937,943 ----
>     mips64vr5*-*-*)
>         part_specific_obj="vr5xxx.o cma101.o"
>         part_specific_defines=-DR5000
> !         script_list="idt pmon ddb ddb-kseg0 lsi idtecoff nullmon"
>           bsp_list="libidt.a libpmon.a liblsi.a libnullmon.a"
>         ;;
>     mipsisa32*-*-*)
> *************** case "${target}" in
> *** 938,944 ****
>     *)
>           part_specific_obj="vr4300.o cma101.o"
>         part_specific_defines=
> !         script_list="idt pmon ddb lsi idtecoff nullmon"
>           bsp_list="libidt.a libpmon.a liblsi.a libnullmon.a"
>           ;;
>   esac
> --- 949,955 ----
>     *)
>           part_specific_obj="vr4300.o cma101.o"
>         part_specific_defines=
> !         script_list="idt pmon ddb ddb-kseg0 lsi idtecoff nullmon"
>           bsp_list="libidt.a libpmon.a liblsi.a libnullmon.a"
>           ;;
>   esac
> 
> --
> Michael Meissner, Red Hat, Inc.  (GCC group)
> PMB 198, 174 Littleton Road #3, Westford, Massachusetts 01886, USA
> Work:     meissner@redhat.com           phone: +1 978-486-9304
> Non-work: meissner@spectacle-pond.org   fax:   +1 978-692-4482


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]