public inbox for ecos-discuss@sourceware.org
 help / color / mirror / Atom feed
* [ECOS] code optimizations
@ 2001-08-23  8:32 Trenton D. Adams
  2001-08-23  8:37 ` Andrew Lunn
                   ` (4 more replies)
  0 siblings, 5 replies; 17+ messages in thread
From: Trenton D. Adams @ 2001-08-23  8:32 UTC (permalink / raw)
  To: 'eCos Discussion'

Here's some output from my stepping through my pc-controller driver I'm
making.  Notice how the code jumps back and forth?  This shouldn't
happen should it?  My hardware is supposed to be initialized in a
specific order, not jump around.  If this occurs during debug, it would
occur during a normal run too, wouldn't it?  I know we talked about this
before, but this just seems really weird to me!  I never did show anyone
this before so I thought I would give it a try.

How do I make the config tool allow me to specify different compiler
options for my driver?  Is it a CDL thing?


195         *(unsigned *)PMPCON     |= 0x0002;          // +12V DC-DC
converter on
(gdb) next
197         *(unsigned *)SYSCON2    |= SYSCON2_PCMCIA1; // PCMCIA Slot 1
on
(gdb) next
198
(gdb) list
193         *(unsigned *)PEDDR      |= 0x02;            // +5V on
194         *(unsigned *)PEDR       |= 0x02;            // +5V on
195         *(unsigned *)PMPCON     |= 0x0002;          // +12V DC-DC
converter on
196         *(unsigned *)SYSCON1    |= SYSCON1_EXCKEN;  // EXPCLK on
197         *(unsigned *)SYSCON2    |= SYSCON2_PCMCIA1; // PCMCIA Slot 1
on
198
199         // Disable byte swapping and notify when 2 slots in fifo are
ready
200         *(unsigned*)PCSICR  &=
201             ~(PCSICR_ENDIAN_CONVERSION |
PCSICR_TRANSQUEUE_THRHOLD_CTRL);
202
(gdb) next
201             ~(PCSICR_ENDIAN_CONVERSION |
PCSICR_TRANSQUEUE_THRHOLD_CTRL);
(gdb) next
204             PCPMR_AUTO_POWERDOWN_ON_REMOVAL |
(gdb) next
194         *(unsigned *)PEDR       |= 0x02;            // +5V on
(gdb) list
189         static int int_init = 0;
190         unsigned long new_state = 0;
191
192         // Initialize the controller
193         *(unsigned *)PEDDR      |= 0x02;            // +5V on
194         *(unsigned *)PEDR       |= 0x02;            // +5V on
195         *(unsigned *)PMPCON     |= 0x0002;          // +12V DC-DC
converter on
196         *(unsigned *)SYSCON1    |= SYSCON1_EXCKEN;  // EXPCLK on
197         *(unsigned *)SYSCON2    |= SYSCON2_PCMCIA1; // PCMCIA Slot 1
on
198
(gdb) next
204             PCPMR_AUTO_POWERDOWN_ON_REMOVAL |
(gdb) list
199         // Disable byte swapping and notify when 2 slots in fifo are
ready
200         *(unsigned*)PCSICR  &=
201             ~(PCSICR_ENDIAN_CONVERSION |
PCSICR_TRANSQUEUE_THRHOLD_CTRL);
202
203         *(unsigned*)PCPMR   |= 0x3<<10 | // weak pull-up
204             PCPMR_AUTO_POWERDOWN_ON_REMOVAL |
205             PCPMR_AUTO_DISABLE_ON_REMOVAL |
206             PCPMR_STANDBY_DISABLE |
207             PCPMR_STANDBY_CARD_ACCESS |
208             PCPMR_PDREQ_GPIO_ENABLE |
(gdb) next
194         *(unsigned *)PEDR       |= 0x02;            // +5V on
(gdb) next
196         *(unsigned *)SYSCON1    |= SYSCON1_EXCKEN;  // EXPCLK on
(gdb) next
195         *(unsigned *)PMPCON     |= 0x0002;          // +12V DC-DC
converter on
(gdb) next
196         *(unsigned *)SYSCON1    |= SYSCON1_EXCKEN;  // EXPCLK on
(gdb) next
195         *(unsigned *)PMPCON     |= 0x0002;          // +12V DC-DC
converter on
(gdb) next
196         *(unsigned *)SYSCON1    |= SYSCON1_EXCKEN;  // EXPCLK on
(gdb) next
189         static int int_init = 0;
(gdb) next
197         *(unsigned *)SYSCON2    |= SYSCON2_PCMCIA1; // PCMCIA Slot 1
on
(gdb) next
212
(gdb) list
207             PCPMR_STANDBY_CARD_ACCESS |
208             PCPMR_PDREQ_GPIO_ENABLE |
209             PCPMR_AUTO_IDLE;
210
211         *(unsigned*)PCCICR |= PCCICR_CARD_RESETOUTPUT_ENABLE;
212
213         cyg_thread_delay (5);
214
215         new_state = *(unsigned*)PCCIILR;
216
(gdb) next
198
(gdb) next
197         *(unsigned *)SYSCON2    |= SYSCON2_PCMCIA1; // PCMCIA Slot 1
on
(gdb) next
198
(gdb) next
212
(gdb) next
201             ~(PCSICR_ENDIAN_CONVERSION |
PCSICR_TRANSQUEUE_THRHOLD_CTRL);
(gdb) next
214
(gdb) next
204             PCPMR_AUTO_POWERDOWN_ON_REMOVAL |
(gdb) next
201             ~(PCSICR_ENDIAN_CONVERSION |
PCSICR_TRANSQUEUE_THRHOLD_CTRL);
(gdb) next
204             PCPMR_AUTO_POWERDOWN_ON_REMOVAL |
(gdb) next
212
(gdb) next
204             PCPMR_AUTO_POWERDOWN_ON_REMOVAL |
(gdb) next
212
(gdb) next

Trenton D. Adams
Extreme Engineering
#17, 6025 - 12 St. SE
Calgary, Alberta, Canada
T2H 2K1

Phone: 403 640 9494 ext-208
Fax: 403 640 9599

http://www.extremeeng.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [ECOS] code optimizations
  2001-08-23  8:32 [ECOS] code optimizations Trenton D. Adams
@ 2001-08-23  8:37 ` Andrew Lunn
  2001-08-23  8:39 ` Gary Thomas
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 17+ messages in thread
From: Andrew Lunn @ 2001-08-23  8:37 UTC (permalink / raw)
  To: Trenton D. Adams; +Cc: 'eCos Discussion'

On Thu, Aug 23, 2001 at 09:32:20AM -0600, Trenton D. Adams wrote:
Notice how the code jumps back and forth?  This shouldn't
> happen should it?

Have you declared your HW registers as volatile. If not, gcc is
allowed to rearrange the code.

        Andrew

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [ECOS] code optimizations
  2001-08-23  8:32 [ECOS] code optimizations Trenton D. Adams
  2001-08-23  8:37 ` Andrew Lunn
@ 2001-08-23  8:39 ` Gary Thomas
  2001-08-23  8:43 ` Bart Veer
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 17+ messages in thread
From: Gary Thomas @ 2001-08-23  8:39 UTC (permalink / raw)
  To: Trenton D. Adams; +Cc: eCos Discussion

This is an artifact of debugging optimized code.  I believe that future
enhancements to the compiler+GDB, namely Dwarf-2 capabilities, will make
this [nearly] go away.

At the moment the only way to not see this kind of jumping-about would
be to turn off optimizations completely.

On 23-Aug-2001 Trenton D. Adams wrote:
> Here's some output from my stepping through my pc-controller driver I'm
> making.  Notice how the code jumps back and forth?  This shouldn't
> happen should it?  My hardware is supposed to be initialized in a
> specific order, not jump around.  If this occurs during debug, it would
> occur during a normal run too, wouldn't it?  I know we talked about this
> before, but this just seems really weird to me!  I never did show anyone
> this before so I thought I would give it a try.
> 
> How do I make the config tool allow me to specify different compiler
> options for my driver?  Is it a CDL thing?
> 
> 
> 195         *(unsigned *)PMPCON     |= 0x0002;          // +12V DC-DC
> converter on
> (gdb) next
> 197         *(unsigned *)SYSCON2    |= SYSCON2_PCMCIA1; // PCMCIA Slot 1
> on
> (gdb) next
> 198
> (gdb) list
> 193         *(unsigned *)PEDDR      |= 0x02;            // +5V on
> 194         *(unsigned *)PEDR       |= 0x02;            // +5V on
> 195         *(unsigned *)PMPCON     |= 0x0002;          // +12V DC-DC
> converter on
> 196         *(unsigned *)SYSCON1    |= SYSCON1_EXCKEN;  // EXPCLK on
> 197         *(unsigned *)SYSCON2    |= SYSCON2_PCMCIA1; // PCMCIA Slot 1
> on
> 198
> 199         // Disable byte swapping and notify when 2 slots in fifo are
> ready
> 200         *(unsigned*)PCSICR  &=
> 201             ~(PCSICR_ENDIAN_CONVERSION |
> PCSICR_TRANSQUEUE_THRHOLD_CTRL);
> 202
> (gdb) next
> 201             ~(PCSICR_ENDIAN_CONVERSION |
> PCSICR_TRANSQUEUE_THRHOLD_CTRL);
> (gdb) next
> 204             PCPMR_AUTO_POWERDOWN_ON_REMOVAL |
> (gdb) next
> 194         *(unsigned *)PEDR       |= 0x02;            // +5V on
> (gdb) list
> 189         static int int_init = 0;
> 190         unsigned long new_state = 0;
> 191
> 192         // Initialize the controller
> 193         *(unsigned *)PEDDR      |= 0x02;            // +5V on
> 194         *(unsigned *)PEDR       |= 0x02;            // +5V on
> 195         *(unsigned *)PMPCON     |= 0x0002;          // +12V DC-DC
> converter on
> 196         *(unsigned *)SYSCON1    |= SYSCON1_EXCKEN;  // EXPCLK on
> 197         *(unsigned *)SYSCON2    |= SYSCON2_PCMCIA1; // PCMCIA Slot 1
> on
> 198
> (gdb) next
> 204             PCPMR_AUTO_POWERDOWN_ON_REMOVAL |
> (gdb) list
> 199         // Disable byte swapping and notify when 2 slots in fifo are
> ready
> 200         *(unsigned*)PCSICR  &=
> 201             ~(PCSICR_ENDIAN_CONVERSION |
> PCSICR_TRANSQUEUE_THRHOLD_CTRL);
> 202
> 203         *(unsigned*)PCPMR   |= 0x3<<10 | // weak pull-up
> 204             PCPMR_AUTO_POWERDOWN_ON_REMOVAL |
> 205             PCPMR_AUTO_DISABLE_ON_REMOVAL |
> 206             PCPMR_STANDBY_DISABLE |
> 207             PCPMR_STANDBY_CARD_ACCESS |
> 208             PCPMR_PDREQ_GPIO_ENABLE |
> (gdb) next
> 194         *(unsigned *)PEDR       |= 0x02;            // +5V on
> (gdb) next
> 196         *(unsigned *)SYSCON1    |= SYSCON1_EXCKEN;  // EXPCLK on
> (gdb) next
> 195         *(unsigned *)PMPCON     |= 0x0002;          // +12V DC-DC
> converter on
> (gdb) next
> 196         *(unsigned *)SYSCON1    |= SYSCON1_EXCKEN;  // EXPCLK on
> (gdb) next
> 195         *(unsigned *)PMPCON     |= 0x0002;          // +12V DC-DC
> converter on
> (gdb) next
> 196         *(unsigned *)SYSCON1    |= SYSCON1_EXCKEN;  // EXPCLK on
> (gdb) next
> 189         static int int_init = 0;
> (gdb) next
> 197         *(unsigned *)SYSCON2    |= SYSCON2_PCMCIA1; // PCMCIA Slot 1
> on
> (gdb) next
> 212
> (gdb) list
> 207             PCPMR_STANDBY_CARD_ACCESS |
> 208             PCPMR_PDREQ_GPIO_ENABLE |
> 209             PCPMR_AUTO_IDLE;
> 210
> 211         *(unsigned*)PCCICR |= PCCICR_CARD_RESETOUTPUT_ENABLE;
> 212
> 213         cyg_thread_delay (5);
> 214
> 215         new_state = *(unsigned*)PCCIILR;
> 216
> (gdb) next
> 198
> (gdb) next
> 197         *(unsigned *)SYSCON2    |= SYSCON2_PCMCIA1; // PCMCIA Slot 1
> on
> (gdb) next
> 198
> (gdb) next
> 212
> (gdb) next
> 201             ~(PCSICR_ENDIAN_CONVERSION |
> PCSICR_TRANSQUEUE_THRHOLD_CTRL);
> (gdb) next
> 214
> (gdb) next
> 204             PCPMR_AUTO_POWERDOWN_ON_REMOVAL |
> (gdb) next
> 201             ~(PCSICR_ENDIAN_CONVERSION |
> PCSICR_TRANSQUEUE_THRHOLD_CTRL);
> (gdb) next
> 204             PCPMR_AUTO_POWERDOWN_ON_REMOVAL |
> (gdb) next
> 212
> (gdb) next
> 204             PCPMR_AUTO_POWERDOWN_ON_REMOVAL |
> (gdb) next
> 212
> (gdb) next
> 
> Trenton D. Adams
> Extreme Engineering
>#17, 6025 - 12 St. SE
> Calgary, Alberta, Canada
> T2H 2K1
> 
> Phone: 403 640 9494 ext-208
> Fax: 403 640 9599
> 
> http://www.extremeeng.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [ECOS] code optimizations
  2001-08-23  8:32 [ECOS] code optimizations Trenton D. Adams
  2001-08-23  8:37 ` Andrew Lunn
  2001-08-23  8:39 ` Gary Thomas
@ 2001-08-23  8:43 ` Bart Veer
  2001-08-23  8:50   ` Trenton D. Adams
  2001-08-23 11:18   ` Grant Edwards
  2001-08-23  8:52 ` Grant Edwards
  2001-08-23  8:57 ` Trenton D. Adams
  4 siblings, 2 replies; 17+ messages in thread
From: Bart Veer @ 2001-08-23  8:43 UTC (permalink / raw)
  To: tadams; +Cc: ecos-discuss

>>>>> "Trenton" == Trenton D Adams <tadams@extremeeng.com> writes:

    Trenton> Here's some output from my stepping through my
    Trenton> pc-controller driver I'm making. Notice how the code
    Trenton> jumps back and forth? This shouldn't happen should it? My
    Trenton> hardware is supposed to be initialized in a specific
    Trenton> order, not jump around. If this occurs during debug, it
    Trenton> would occur during a normal run too, wouldn't it? I know
    Trenton> we talked about this before, but this just seems really
    Trenton> weird to me! I never did show anyone this before so I
    Trenton> thought I would give it a try.

    Trenton> How do I make the config tool allow me to specify
    Trenton> different compiler options for my driver? Is it a CDL
    Trenton> thing?

This is expected behaviour if you are compiling with optimisation:
the compiler is supposed to reorganise your code in any way that
improves performance, while still meeting the exact conformance
criteria described in the ISO specification. For example, given
two lines:

    *(unsigned *)PMPCON     |= 0x0002;
    *(unsigned *)SYSCON2    |= SYSCON2_PCMCIA1;

The compiler is entirely at liberty to rearrange these instructions
if it thinks that is a good idea.

The solution here is to make proper use of the "volatile" qualifier.
The compiler is not allowed to reorder accesses to volatile memory
locations, so if you rewrite the above as:


    *(volatile unsigned *)PMPCON     |= 0x0002;
    *(volatile unsigned *)SYSCON2    |= SYSCON2_PCMCIA1;

then the compiler cannot reorder these accesses. Typically PMPCON will
be #define'd such that it includes the type and volatile qualifier,
and then you can just go:

    *PMPCON |= 0x0002;

without having to worry about casts all over the place.

Bart

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [ECOS] code optimizations
  2001-08-23  8:43 ` Bart Veer
@ 2001-08-23  8:50   ` Trenton D. Adams
  2001-08-23  9:59     ` Bart Veer
  2001-08-28  6:34     ` Hugo Tyson
  2001-08-23 11:18   ` Grant Edwards
  1 sibling, 2 replies; 17+ messages in thread
From: Trenton D. Adams @ 2001-08-23  8:50 UTC (permalink / raw)
  To: bartv, tadams; +Cc: ecos-discuss

Does it matter whether voltatile or unsigned goes first?  Because I'm
still getting the jumping around with (unsigned volatile)

194         *(unsigned volatile*)PEDR       |= 0x02;            // +5V
on
(gdb) next
193         *(unsigned volatile*)PEDDR      |= 0x02;            // +5V
on
(gdb) next
194         *(unsigned volatile*)PEDR       |= 0x02;            // +5V
on
(gdb) next
193         *(unsigned volatile*)PEDDR      |= 0x02;            // +5V
on
(gdb) next
196         *(unsigned volatile*)SYSCON1    |= SYSCON1_EXCKEN;  //
EXPCLK on
(gdb) next
194         *(unsigned volatile*)PEDR       |= 0x02;            // +5V
on
(gdb) next
195         *(unsigned volatile*)PMPCON     |= 0x0002;          // +12V
DC-DC converter on
(gdb) next
194         *(unsigned volatile*)PEDR       |= 0x02;            // +5V
on
(gdb) next
195         *(unsigned volatile*)PMPCON     |= 0x0002;          // +12V
DC-DC converter on
(gdb) next
196         *(unsigned volatile*)SYSCON1    |= SYSCON1_EXCKEN;  //
EXPCLK on
(gdb) next
195         *(unsigned volatile*)PMPCON     |= 0x0002;          // +12V
DC-DC converter on
(gdb) next
188     {
(gdb) next
196         *(unsigned volatile*)SYSCON1    |= SYSCON1_EXCKEN;  //
EXPCLK on
(gdb) next
197         *(unsigned volatile*)SYSCON2    |= SYSCON2_PCMCIA1; //
PCMCIA Slot 1 on
(gdb) next
196         *(unsigned volatile*)SYSCON1    |= SYSCON1_EXCKEN;  //
EXPCLK on
(gdb) next
197         *(unsigned volatile*)SYSCON2    |= SYSCON2_PCMCIA1; //
PCMCIA Slot 1 on
(gdb)

-----Original Message-----
From: ecos-discuss-owner@sources.redhat.com
[ mailto:ecos-discuss-owner@sources.redhat.com ] On Behalf Of Bart Veer
Sent: Thursday, August 23, 2001 9:43 AM
To: tadams@extremeeng.com
Cc: ecos-discuss@sourceware.cygnus.com
Subject: Re: [ECOS] code optimizations


>>>>> "Trenton" == Trenton D Adams <tadams@extremeeng.com> writes:

    Trenton> Here's some output from my stepping through my
    Trenton> pc-controller driver I'm making. Notice how the code
    Trenton> jumps back and forth? This shouldn't happen should it? My
    Trenton> hardware is supposed to be initialized in a specific
    Trenton> order, not jump around. If this occurs during debug, it
    Trenton> would occur during a normal run too, wouldn't it? I know
    Trenton> we talked about this before, but this just seems really
    Trenton> weird to me! I never did show anyone this before so I
    Trenton> thought I would give it a try.

    Trenton> How do I make the config tool allow me to specify
    Trenton> different compiler options for my driver? Is it a CDL
    Trenton> thing?

This is expected behaviour if you are compiling with optimisation:
the compiler is supposed to reorganise your code in any way that
improves performance, while still meeting the exact conformance
criteria described in the ISO specification. For example, given
two lines:

    *(unsigned *)PMPCON     |= 0x0002;
    *(unsigned *)SYSCON2    |= SYSCON2_PCMCIA1;

The compiler is entirely at liberty to rearrange these instructions
if it thinks that is a good idea.

The solution here is to make proper use of the "volatile" qualifier.
The compiler is not allowed to reorder accesses to volatile memory
locations, so if you rewrite the above as:


    *(volatile unsigned *)PMPCON     |= 0x0002;
    *(volatile unsigned *)SYSCON2    |= SYSCON2_PCMCIA1;

then the compiler cannot reorder these accesses. Typically PMPCON will
be #define'd such that it includes the type and volatile qualifier,
and then you can just go:

    *PMPCON |= 0x0002;

without having to worry about casts all over the place.

Bart

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [ECOS] code optimizations
  2001-08-23  8:32 [ECOS] code optimizations Trenton D. Adams
                   ` (2 preceding siblings ...)
  2001-08-23  8:43 ` Bart Veer
@ 2001-08-23  8:52 ` Grant Edwards
  2001-08-23  9:02   ` Gary Thomas
  2001-08-23  8:57 ` Trenton D. Adams
  4 siblings, 1 reply; 17+ messages in thread
From: Grant Edwards @ 2001-08-23  8:52 UTC (permalink / raw)
  To: Trenton D. Adams; +Cc: 'eCos Discussion'

On Thu, Aug 23, 2001 at 09:32:20AM -0600, Trenton D. Adams wrote:

> Here's some output from my stepping through my pc-controller
> driver I'm making.  Notice how the code jumps back and forth?
> This shouldn't happen should it?

It is allowed to happen according to the C standard.

> My hardware is supposed to be initialized in a specific order,
> not jump around.

Declare all your hardware registers as volatile.  That will
prevent the compiler from re-ordering the access:

 #define foo 0x7ff8005

 *(volatile unsigned*)foo = 0x12345678;


<pet peeve>

Personally, I think that addresses should be assigned to
objects by the linker, so I prefer this:

  extern volatile unsigned foo;
  
  foo = 0x12345678;  

Then assign an address to foo at link time.

However, that's not the standard eCos idiom.  Rather, putting
peripheral addresses in the source code seems to be the way
it's usually done in eCos HAL and drivers.

</pet peeve>


> If this occurs during debug, it would occur during a normal run
> too, wouldn't it?

Yes.

> I know we talked about this before, but this just seems really
> weird to me!  I never did show anyone this before so I thought
> I would give it a try.
> 
> How do I make the config tool allow me to specify different
> compiler options for my driver?  Is it a CDL thing?

Nope, it's a bug in your source code.  The compiler is
generating legal object code for the source it has been given.

Two statements with no interdependacies may be re-ordered by
the compiler if it so wishes.  Accessing a volatile object will
cause a "sequence point" to be placed before and after the
expression, which will prevent the compiler from moving that
expression when it optimizes code.  I'm sure somebody has a
pointer to a good C language reference, but I don't have one
handy.

-- 
Grant Edwards
grante@visi.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [ECOS] code optimizations
  2001-08-23  8:32 [ECOS] code optimizations Trenton D. Adams
                   ` (3 preceding siblings ...)
  2001-08-23  8:52 ` Grant Edwards
@ 2001-08-23  8:57 ` Trenton D. Adams
  4 siblings, 0 replies; 17+ messages in thread
From: Trenton D. Adams @ 2001-08-23  8:57 UTC (permalink / raw)
  To: 'Trenton D. Adams', 'eCos Discussion'

Here's my attempt at changing my build options.  Will this get the
config tool to actually change my build options if I specify them in the
text boxes?  Do I have to remake the project in order for it to work?

    cdl_component CYGPKG_DEVS_PCMCIA_EDB7XXX_OPTIONS {
        display "PCMCIA Build options"
        flavor  none
        description   "
	    Package specific build options including control over
	    compiler flags used only in building this package."


        cdl_option CYGPKG_DEVS_PCMCIA_EDB7XXX_CFLAGS_ADD {
            display "Additional compiler flags"
            flavor  data
            no_define
            default_value { "" }
            description   "
                This option modifies the set of compiler flags for
                building the eCos edb7xxx pcmcia package. These flags
are used
                in addition to the set of global flags."
        }

        cdl_option CYGPKG_DEVS_PCMCIA_EDB7XXX_CFLAGS_REMOVE {
            display "Suppressed compiler flags"
            flavor  data
            no_define
            default_value { "" }
            description   "
                This option modifies the set of compiler flags for
                building the eCos edb7xxx pcmcia package. These flags
are removed from
                the set of global flags if present."
        }
    }

-----Original Message-----
From: ecos-discuss-owner@sources.redhat.com
[ mailto:ecos-discuss-owner@sources.redhat.com ] On Behalf Of Trenton D.
Adams
Sent: Thursday, August 23, 2001 9:32 AM
To: 'eCos Discussion'
Subject: [ECOS] code optimizations


Here's some output from my stepping through my pc-controller driver I'm
making.  Notice how the code jumps back and forth?  This shouldn't
happen should it?  My hardware is supposed to be initialized in a
specific order, not jump around.  If this occurs during debug, it would
occur during a normal run too, wouldn't it?  I know we talked about this
before, but this just seems really weird to me!  I never did show anyone
this before so I thought I would give it a try.

How do I make the config tool allow me to specify different compiler
options for my driver?  Is it a CDL thing?


195         *(unsigned *)PMPCON     |= 0x0002;          // +12V DC-DC
converter on
(gdb) next
197         *(unsigned *)SYSCON2    |= SYSCON2_PCMCIA1; // PCMCIA Slot 1
on
(gdb) next
198
(gdb) list
193         *(unsigned *)PEDDR      |= 0x02;            // +5V on
194         *(unsigned *)PEDR       |= 0x02;            // +5V on
195         *(unsigned *)PMPCON     |= 0x0002;          // +12V DC-DC
converter on
196         *(unsigned *)SYSCON1    |= SYSCON1_EXCKEN;  // EXPCLK on
197         *(unsigned *)SYSCON2    |= SYSCON2_PCMCIA1; // PCMCIA Slot 1
on
198
199         // Disable byte swapping and notify when 2 slots in fifo are
ready
200         *(unsigned*)PCSICR  &=
201             ~(PCSICR_ENDIAN_CONVERSION |
PCSICR_TRANSQUEUE_THRHOLD_CTRL);
202
(gdb) next
201             ~(PCSICR_ENDIAN_CONVERSION |
PCSICR_TRANSQUEUE_THRHOLD_CTRL);
(gdb) next
204             PCPMR_AUTO_POWERDOWN_ON_REMOVAL |
(gdb) next
194         *(unsigned *)PEDR       |= 0x02;            // +5V on
(gdb) list
189         static int int_init = 0;
190         unsigned long new_state = 0;
191
192         // Initialize the controller
193         *(unsigned *)PEDDR      |= 0x02;            // +5V on
194         *(unsigned *)PEDR       |= 0x02;            // +5V on
195         *(unsigned *)PMPCON     |= 0x0002;          // +12V DC-DC
converter on
196         *(unsigned *)SYSCON1    |= SYSCON1_EXCKEN;  // EXPCLK on
197         *(unsigned *)SYSCON2    |= SYSCON2_PCMCIA1; // PCMCIA Slot 1
on
198
(gdb) next
204             PCPMR_AUTO_POWERDOWN_ON_REMOVAL |
(gdb) list
199         // Disable byte swapping and notify when 2 slots in fifo are
ready
200         *(unsigned*)PCSICR  &=
201             ~(PCSICR_ENDIAN_CONVERSION |
PCSICR_TRANSQUEUE_THRHOLD_CTRL);
202
203         *(unsigned*)PCPMR   |= 0x3<<10 | // weak pull-up
204             PCPMR_AUTO_POWERDOWN_ON_REMOVAL |
205             PCPMR_AUTO_DISABLE_ON_REMOVAL |
206             PCPMR_STANDBY_DISABLE |
207             PCPMR_STANDBY_CARD_ACCESS |
208             PCPMR_PDREQ_GPIO_ENABLE |
(gdb) next
194         *(unsigned *)PEDR       |= 0x02;            // +5V on
(gdb) next
196         *(unsigned *)SYSCON1    |= SYSCON1_EXCKEN;  // EXPCLK on
(gdb) next
195         *(unsigned *)PMPCON     |= 0x0002;          // +12V DC-DC
converter on
(gdb) next
196         *(unsigned *)SYSCON1    |= SYSCON1_EXCKEN;  // EXPCLK on
(gdb) next
195         *(unsigned *)PMPCON     |= 0x0002;          // +12V DC-DC
converter on
(gdb) next
196         *(unsigned *)SYSCON1    |= SYSCON1_EXCKEN;  // EXPCLK on
(gdb) next
189         static int int_init = 0;
(gdb) next
197         *(unsigned *)SYSCON2    |= SYSCON2_PCMCIA1; // PCMCIA Slot 1
on
(gdb) next
212
(gdb) list
207             PCPMR_STANDBY_CARD_ACCESS |
208             PCPMR_PDREQ_GPIO_ENABLE |
209             PCPMR_AUTO_IDLE;
210
211         *(unsigned*)PCCICR |= PCCICR_CARD_RESETOUTPUT_ENABLE;
212
213         cyg_thread_delay (5);
214
215         new_state = *(unsigned*)PCCIILR;
216
(gdb) next
198
(gdb) next
197         *(unsigned *)SYSCON2    |= SYSCON2_PCMCIA1; // PCMCIA Slot 1
on
(gdb) next
198
(gdb) next
212
(gdb) next
201             ~(PCSICR_ENDIAN_CONVERSION |
PCSICR_TRANSQUEUE_THRHOLD_CTRL);
(gdb) next
214
(gdb) next
204             PCPMR_AUTO_POWERDOWN_ON_REMOVAL |
(gdb) next
201             ~(PCSICR_ENDIAN_CONVERSION |
PCSICR_TRANSQUEUE_THRHOLD_CTRL);
(gdb) next
204             PCPMR_AUTO_POWERDOWN_ON_REMOVAL |
(gdb) next
212
(gdb) next
204             PCPMR_AUTO_POWERDOWN_ON_REMOVAL |
(gdb) next
212
(gdb) next

Trenton D. Adams
Extreme Engineering
#17, 6025 - 12 St. SE
Calgary, Alberta, Canada
T2H 2K1

Phone: 403 640 9494 ext-208
Fax: 403 640 9599

http://www.extremeeng.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [ECOS] code optimizations
  2001-08-23  8:52 ` Grant Edwards
@ 2001-08-23  9:02   ` Gary Thomas
  2001-08-23  9:10     ` Grant Edwards
  2001-08-23  9:10     ` Trenton D. Adams
  0 siblings, 2 replies; 17+ messages in thread
From: Gary Thomas @ 2001-08-23  9:02 UTC (permalink / raw)
  To: Grant Edwards; +Cc: eCos Discussion, Trenton D. Adams

On 23-Aug-2001 Grant Edwards wrote:
> <pet peeve>
> 
> Personally, I think that addresses should be assigned to
> objects by the linker, so I prefer this:
> 
>   extern volatile unsigned foo;
>   
>   foo = 0x12345678;  
> 
> Then assign an address to foo at link time.
> 
> However, that's not the standard eCos idiom.  Rather, putting
> peripheral addresses in the source code seems to be the way
> it's usually done in eCos HAL and drivers.
> 
> </pet peeve>

Why?  I don't see any advantage - in fact there could be major
code generation/optimization disadvantages.  Having the actual
addresses in header files (the eCos custom) also provides an
additional level of documentation, however bleak.

Note: I doubt that you'll find any addresses in actual code, but
rather in header files which can be easily manipulated allowing
for the additional flexibility I feel you seek.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [ECOS] code optimizations
  2001-08-23  9:02   ` Gary Thomas
  2001-08-23  9:10     ` Grant Edwards
@ 2001-08-23  9:10     ` Trenton D. Adams
  1 sibling, 0 replies; 17+ messages in thread
From: Trenton D. Adams @ 2001-08-23  9:10 UTC (permalink / raw)
  To: 'Gary Thomas', 'Grant Edwards'; +Cc: 'eCos Discussion'

Screw optimizations.  My CDL thing did work, and I changed to -O0.  This
didn't have any affect on whether my driver works or not as was
suggested by some people a few weeks ago! :(



-----Original Message-----
From: ecos-discuss-owner@sources.redhat.com
[ mailto:ecos-discuss-owner@sources.redhat.com ] On Behalf Of Gary Thomas
Sent: Thursday, August 23, 2001 10:08 AM
To: Grant Edwards
Cc: eCos Discussion; eCos Discussion; Trenton D. Adams
Subject: Re: [ECOS] code optimizations



On 23-Aug-2001 Grant Edwards wrote:
> <pet peeve>
> 
> Personally, I think that addresses should be assigned to
> objects by the linker, so I prefer this:
> 
>   extern volatile unsigned foo;
>   
>   foo = 0x12345678;  
> 
> Then assign an address to foo at link time.
> 
> However, that's not the standard eCos idiom.  Rather, putting
> peripheral addresses in the source code seems to be the way
> it's usually done in eCos HAL and drivers.
> 
> </pet peeve>

Why?  I don't see any advantage - in fact there could be major
code generation/optimization disadvantages.  Having the actual
addresses in header files (the eCos custom) also provides an
additional level of documentation, however bleak.

Note: I doubt that you'll find any addresses in actual code, but
rather in header files which can be easily manipulated allowing
for the additional flexibility I feel you seek.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [ECOS] code optimizations
  2001-08-23  9:02   ` Gary Thomas
@ 2001-08-23  9:10     ` Grant Edwards
  2001-08-23  9:10     ` Trenton D. Adams
  1 sibling, 0 replies; 17+ messages in thread
From: Grant Edwards @ 2001-08-23  9:10 UTC (permalink / raw)
  To: Gary Thomas; +Cc: eCos Discussion, Trenton D. Adams

On Thu, Aug 23, 2001 at 10:08:03AM -0600, Gary Thomas wrote:

> Why?  I don't see any advantage - in fact there could be major
> code generation/optimization disadvantages.  Having the actual
> addresses in header files (the eCos custom) also provides an
> additional level of documentation, however bleak.

I agree that it's easier for most people to find the addresses
when they're in a header file.

It's mostly a philosphical thing I have stuck in my head about
at what stage in the build addresses get assigned.  I think
that should happen at the link stage. If you assign addresses
to peripherals in the linker file (where the reset of the
memory addresses are defined), then all of the memory layout is
defined in a single place.  I've always thought that a nice
thing.

There aren't many other benefits, though. 

Having the debugger know the addresses of peripherals is nice
sometimes.

And there was that one time a many years ago when I was
maintaining a common set of code for two platforms. By
assigning peripheral addresses in the linker, I could avoid
re-compiling source files and only have to link twice to
support two platforms.  That was sort of an odd case, though.

> Note: I doubt that you'll find any addresses in actual code, but
> rather in header files which can be easily manipulated allowing
> for the additional flexibility I feel you seek.

Right -- by "source code" I meant the header files.

-- 
Grant Edwards
grante@visi.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [ECOS] code optimizations
  2001-08-23  8:50   ` Trenton D. Adams
@ 2001-08-23  9:59     ` Bart Veer
  2001-08-28  6:34     ` Hugo Tyson
  1 sibling, 0 replies; 17+ messages in thread
From: Bart Veer @ 2001-08-23  9:59 UTC (permalink / raw)
  To: tadams; +Cc: ecos-discuss

>>>>> "Trenton" == Trenton D Adams <tadams@theone.dnsalias.com> writes:

    Trenton> Does it matter whether voltatile or unsigned goes first?
    Trenton> Because I'm still getting the jumping around with
    Trenton> (unsigned volatile)

Yes, it matters:

    volatile unsigned*	ptr_to_volatile_uint;

This declares a pointer to a volatile memory location. The pointer
itself will not change at the whim of the hardware, but the memory
location may. Usually this is what is required.

    unsigned volatile* volatile_ptr_to_uint;
    unsigned *volatile volatile_ptr_to_uint;

These declare a volatile pointer to a non-volatile memory location.
The memory location will not change at the whim of the hardware, but
the pointer may change at any time. This is less common, an example
might be a DMA controller where one of the registers points at memory.

    volatile unsigned volatile* volatile_ptr_to_volatile_uint;

The pointer may change at any time, and so can the memory location
pointed out. Very unusual.

This is why I specified (volatile unsigned *) in my message, not
the (unsigned volatile*) which you have used.

>>>>> "Trenton" == Trenton D Adams <tadams@theone.dnsalias.com> writes:

    Trenton> Screw optimizations. My CDL thing did work, and I changed
    Trenton> to -O0. This didn't have any affect on whether my driver
    Trenton> works or not as was suggested by some people a few weeks
    Trenton> ago! :(

It may work with the current compiler. It may or may not work with the
next version of the compiler, even at -O0. I am not aware of any
compiler work going on that would stop it working at -O0. However if
you are not using volatile correctly when accessing hardware registers
then the source code is broken, and you cannot depend on the compiler
generating code that behaves the way you would like it to.

Bart

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [ECOS] code optimizations
  2001-08-23  8:43 ` Bart Veer
  2001-08-23  8:50   ` Trenton D. Adams
@ 2001-08-23 11:18   ` Grant Edwards
  1 sibling, 0 replies; 17+ messages in thread
From: Grant Edwards @ 2001-08-23 11:18 UTC (permalink / raw)
  To: Bart Veer; +Cc: tadams, ecos-discuss

On Thu, Aug 23, 2001 at 04:43:02PM +0100, Bart Veer wrote:

>     Trenton> Here's some output from my stepping through my
>     Trenton> pc-controller driver I'm making. Notice how the code
>     Trenton> jumps back and forth? This shouldn't happen should it?
[...]
> This is expected behaviour if you are compiling with optimisation:

And I think it is always _allowed_ behavior.  This version of
this compiler for this target happens to not re-arrange code
with -O0, but that's not gauranteed.  It may stop working in
the future if you take that route.

There are already enough places where one almost has to depend
on compiler/platform assumptions -- you don't want to do it when
you don't have to.  ;)

-- 
Grant Edwards
grante@visi.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [ECOS] code optimizations
  2001-08-23  8:50   ` Trenton D. Adams
  2001-08-23  9:59     ` Bart Veer
@ 2001-08-28  6:34     ` Hugo Tyson
  1 sibling, 0 replies; 17+ messages in thread
From: Hugo Tyson @ 2001-08-28  6:34 UTC (permalink / raw)
  To: ecos-discuss

"Trenton D. Adams" <tadams@theone.dnsalias.com> writes:
> Does it matter whether voltatile or unsigned goes first?  Because I'm
> still getting the jumping around with (unsigned volatile)

(Other msgs have covered that volatile unsigned int * is best, but...)

You can still appear to get "jumping around."
Going back to Bart's example:

> For example, given two lines:
> 
>     *(unsigned *)PMPCON     |= 0x0002;
>     *(unsigned *)SYSCON2    |= SYSCON2_PCMCIA1;

On a random made-up CPU, that might turn into 10 instructions:
Naively compiled:

	LOAD	r1, =PMPCON
	LOAD	r3, [r1]
	MOVE	r2, #2
	OR	r3, r2
	STORE   r3, [r1]

	LOAD	r4, =SYSCON2
	LOAD	r6, [r4]
	MOVE	r5, #SYSCON2_PCMCIA1
	OR	r6, r5
	STORE   r6, [r4]

Note that we happen to have plenty of registers here.

Often, there is a delay after a load instruction before you can use the
data you loaded.  The CPU hardware looks after this for you by waiting
until the load has completed.  So the 2nd and 4th loads above might be
delayed waiting for the 1st and 3rd respectively loads of the addresses to
complete.

But optimized code can make use of that delay to "do other stuff" in time
that might otherwise be a delay.  So it's perfectly OK to intermingle those
loads and stores as much as we're allowed to make better use of the load
path from memory or the cache or whatever.  So you might actually get:

	# these two are independent so no mutual delay:
        LOAD    r1, =PMPCON             # first line address
        LOAD    r4, =SYSCON2            # 2nd line address

        MOVE    r2, #2                  # 1st line setup
        LOAD    r3, [r1]                # 1st line read

        MOVE    r5, #SYSCON2_PCMCIA1    # 2nd line setup

        OR      r3, r2                  # 1st line "arithmetic"
        STORE   r3, [r1]                # 1st line write

        LOAD    r6, [r4]                # 2nd line as required
        OR      r6, r5                  #   by "volatile", all after
        STORE   r6, [r4]                #   1st line completes

So if you single-step through you still might see the "setup" instructions
- getting addresses and constants - intermingled, even though the actual
manipulation of the hardware (LOADs and STORES of volatile memory
locations) must be ordered and non-overlapping.

HTH,
	- Huge

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [ECOS] code optimizations
@ 2001-08-23 13:26 Dan Conti
  0 siblings, 0 replies; 17+ messages in thread
From: Dan Conti @ 2001-08-23 13:26 UTC (permalink / raw)
  To: ecos-discuss

> -----Original Message-----
> From: Mark Salter [ mailto:msalter@redhat.com ]
> Subject: Re: [ECOS] code optimizations
>
> Why is there an extra load? I would think that using compile time
> constants would allow for more optimizations than link time fixups.
> Assume mips like architecture, you either have something like:
> 
>    ori r2, r0, 0xabc
>    lui r1, %hi(foo)
>    sw  r2, %lo(foo)(r1)
> 
> or
> 
>    ori r2, r0, 0xabc
>    lui r1, 0x7ffe
>    sw  r2, 0x1110(r1)

I know i should finish my coffee before i touch email in the morning.

Yes you are correct. I was thinking of two different situations at once
and got confused :)

> Both are equal in size and running time. Better optimization is
> possible with constants if you do a series of stores to different
> addresses. Lets say foo1 is 0x7ffe1114. Then you'd have:
> 
>    ori r2, r0, 0xabc
>    lui r1, %hi(foo)
>    sw  r2, %lo(foo)(r1)
>    lui r1, %hi(foo1)
>    sw  r2, %lo(foo1)(r1)
> 
> or
> 
>    ori r2, r0, 0xabc
>    lui r1, 0x7ffe
>    sw  r2, 0x1110(r1)
>    sw  r2, 0x1114(r1)
> 
> Here, using compile time constants saved you an insn.

Just off the top of my head, you can have the same benefit given the
linker method:

extern volatile unsigned int foo;

foo = 0;
*( &foo + 4 ) = 0;

on arm this generates:

ldr	r1, [pc, #8]
str	r2, [r1]
str	r2, [r1, #16]


I'm guessing i get PC relative addressing because this is a small
program where foo is only referenced in one place, but i dont really
know. It seems to do this in my small test program regardless of the
complexity of the address. Also the code clarity just dropped
tremendously :)
 
> --Mark
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [ECOS] code optimizations
  2001-08-23 11:34 Dan Conti
  2001-08-23 11:59 ` Grant Edwards
@ 2001-08-23 12:11 ` Mark Salter
  1 sibling, 0 replies; 17+ messages in thread
From: Mark Salter @ 2001-08-23 12:11 UTC (permalink / raw)
  To: danc; +Cc: ecos-discuss

>>>>> Dan Conti writes:

> By the way, there's another slight benefit to your method in terms of
> performance. Chances are when you're talking to a peripheral it wont
> matter, but on some of the boards i've worked with (which have 0 wait
> state peripherals but 4 wait state ram), the extra load for the pointer
> in the case of:

> #define foo 0x7ffe1110

> *(volatile unsigned int*)foo = 0xabc;

> can be painful. :)

Why is there an extra load? I would think that using compile time
constants would allow for more optimizations than link time fixups.
Assume mips like architecture, you either have something like:

   ori r2, r0, 0xabc
   lui r1, %hi(foo)
   sw  r2, %lo(foo)(r1)

or

   ori r2, r0, 0xabc
   lui r1, 0x7ffe
   sw  r2, 0x1110(r1)

Both are equal in size and running time. Better optimization is
possible with constants if you do a series of stores to different
addresses. Lets say foo1 is 0x7ffe1114. Then you'd have:

   ori r2, r0, 0xabc
   lui r1, %hi(foo)
   sw  r2, %lo(foo)(r1)
   lui r1, %hi(foo1)
   sw  r2, %lo(foo1)(r1)

or

   ori r2, r0, 0xabc
   lui r1, 0x7ffe
   sw  r2, 0x1110(r1)
   sw  r2, 0x1114(r1)

Here, using compile time constants saved you an insn.

--Mark

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [ECOS] code optimizations
  2001-08-23 11:34 Dan Conti
@ 2001-08-23 11:59 ` Grant Edwards
  2001-08-23 12:11 ` Mark Salter
  1 sibling, 0 replies; 17+ messages in thread
From: Grant Edwards @ 2001-08-23 11:59 UTC (permalink / raw)
  To: Dan Conti; +Cc: eCos Discussion

On Thu, Aug 23, 2001 at 11:34:48AM -0700, Dan Conti wrote:

> > It's mostly a philosphical thing I have stuck in my head about
> > at what stage in the build addresses get assigned.  I think
> > that should happen at the link stage. If you assign addresses
> > to peripherals in the linker file (where the reset of the
> > memory addresses are defined), then all of the memory layout is
> > defined in a single place.  I've always thought that a nice
> > thing.
> 
> That's an interesting thought. We actually have a lot of revs of similar
> hardware layouts here, and up wrestling with this problem. Putting
> memory locations in the linker file would simplify base address changes,
> but what about register offsets? We've had situations where on one
> board, the address leads are flat, and on another, A0 on the peripheral
> is tied to A5 on the processor, so now all the registers are at
> different offsets. It seems like this could snowball to the point of
> having huge amounts of information in your linker file.

That's a problem.  It only helps in situations where only the
base address changes.

> By the way, there's another slight benefit to your method in terms of
> performance. Chances are when you're talking to a peripheral it wont
> matter, but on some of the boards i've worked with (which have 0 wait
> state peripherals but 4 wait state ram), the extra load for the pointer
> in the case of:
> 
> #define foo 0x7ffe1110
> 
> *(volatile unsigned int*)foo = 0xabc;
> 
> can be painful. :)

It depends on the architecture.  For some, derefrencing the
pointer is more expensive, for others it isn't. ARM, for
example can't fit a complete direct address in an instruction,
so all external references end up being equivalent to
dereferencing a pointer that was statically initialized.

-- 
Grant Edwards
grante@visi.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

* RE: [ECOS] code optimizations
@ 2001-08-23 11:34 Dan Conti
  2001-08-23 11:59 ` Grant Edwards
  2001-08-23 12:11 ` Mark Salter
  0 siblings, 2 replies; 17+ messages in thread
From: Dan Conti @ 2001-08-23 11:34 UTC (permalink / raw)
  To: eCos Discussion

> -----Original Message-----
> From: Grant Edwards [ mailto:grante@visi.com ]
> Subject: Re: [ECOS] code optimizations
> 
> 
> On Thu, Aug 23, 2001 at 10:08:03AM -0600, Gary Thomas wrote:
> 
> > Why?  I don't see any advantage - in fact there could be major
> > code generation/optimization disadvantages.  Having the actual
> > addresses in header files (the eCos custom) also provides an
> > additional level of documentation, however bleak.
> 
> I agree that it's easier for most people to find the addresses
> when they're in a header file.
> 
> It's mostly a philosphical thing I have stuck in my head about
> at what stage in the build addresses get assigned.  I think
> that should happen at the link stage. If you assign addresses
> to peripherals in the linker file (where the reset of the
> memory addresses are defined), then all of the memory layout is
> defined in a single place.  I've always thought that a nice
> thing.

That's an interesting thought. We actually have a lot of revs of similar
hardware layouts here, and up wrestling with this problem. Putting
memory locations in the linker file would simplify base address changes,
but what about register offsets? We've had situations where on one
board, the address leads are flat, and on another, A0 on the peripheral
is tied to A5 on the processor, so now all the registers are at
different offsets. It seems like this could snowball to the point of
having huge amounts of information in your linker file.

By the way, there's another slight benefit to your method in terms of
performance. Chances are when you're talking to a peripheral it wont
matter, but on some of the boards i've worked with (which have 0 wait
state peripherals but 4 wait state ram), the extra load for the pointer
in the case of:

#define foo 0x7ffe1110

*(volatile unsigned int*)foo = 0xabc;

can be painful. :)

-Dan

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2001-08-28  6:34 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-08-23  8:32 [ECOS] code optimizations Trenton D. Adams
2001-08-23  8:37 ` Andrew Lunn
2001-08-23  8:39 ` Gary Thomas
2001-08-23  8:43 ` Bart Veer
2001-08-23  8:50   ` Trenton D. Adams
2001-08-23  9:59     ` Bart Veer
2001-08-28  6:34     ` Hugo Tyson
2001-08-23 11:18   ` Grant Edwards
2001-08-23  8:52 ` Grant Edwards
2001-08-23  9:02   ` Gary Thomas
2001-08-23  9:10     ` Grant Edwards
2001-08-23  9:10     ` Trenton D. Adams
2001-08-23  8:57 ` Trenton D. Adams
2001-08-23 11:34 Dan Conti
2001-08-23 11:59 ` Grant Edwards
2001-08-23 12:11 ` Mark Salter
2001-08-23 13:26 Dan Conti

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).