public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Prettify assembly output on SPARC (part #2)
@ 2004-07-09 11:39 Eric Botcazou
  2004-07-09 17:02 ` Richard Sandiford
  2004-09-05 15:25 ` Hans-Peter Nilsson
  0 siblings, 2 replies; 8+ messages in thread
From: Eric Botcazou @ 2004-07-09 11:39 UTC (permalink / raw)
  To: gcc-patches; +Cc: dave.anglin, joern.rennecke

[-- Attachment #1: Type: text/plain, Size: 3125 bytes --]

The patch tweaks final.c to let it output insns in a delay slot with a 
1-space indentation over the normal ones.  This makes it easier for humans 
to parse the assembly output:

sdbm__splpage:
        save    %sp, -1168, %sp
        add     %fp, -1056, %l4
        mov     %i0, %o1
        mov     1024, %o2
        call    memcpy, 0
         mov    %l4, %o0
        mov     %i0, %o0
        mov     0, %o1
        mov     1024, %o2
        call    memset, 0
         add    %fp, -1054, %l3
        mov     %i1, %o0
        mov     0, %o1
        call    memset, 0
         mov    1024, %o2
        ldsh    [%fp-1056], %l2
        cmp     %l2, 0
        ble,pn  %icc, .LL10
         nop
        mov     1024, %o1
        add     %fp, -1064, %l6
        add     %fp, -1072, %l5
.LL4:
        ldsh    [%l3], %g1
        add     %l2, -2, %l2
        ldsh    [%l3+2], %o5
        add     %l4, %g1, %l0
        sub     %o1, %g1, %o1
        st      %o1, [%fp-20]
        sub     %g1, %o5, %g1
        mov     %l0, %o0
        st      %g1, [%fp-28]
        add     %l4, %o5, %o5
        call    sdbm_hash, 0
         st     %o5, [%fp-32]
        st      %l0, [%fp-24]
        ldd     [%fp-24], %o4
        mov     %l6, %o1
        andcc   %o0, %i2, %g0
        mov     %i0, %o0
        ldd     [%fp-32], %l0
        mov     %l5, %o2
        movne   %icc, %i1, %o0
        std     %o4, [%fp-1064]
        call    sdbm__putpair, 0
         std    %l0, [%fp-1072]
        ldsh    [%l3+2], %o1
        cmp     %l2, 0
        bg,pt   %icc, .LL4
         add    %l3, 4, %l3
.LL10:
        return  %i7+8
         nop


final_scan_insn already had an argument to track the "delayslot-ness" so I 
simply made that more explicit by renaming it.  I checked all the back-ends 
and final_scan_insn is only called by targets using delay slots, and only 
invoked from within delay slots (with the argument set to 1 except on PA, 
which should probably be corrected).  The only exception is in sh.c:

/* Print an instruction which would have gone into a delay slot after
   another instruction, but couldn't because the other instruction expanded
   into a sequence where putting the slot insn at the end wouldn't work.  */

static void
print_slot (rtx insn)
{
  final_scan_insn (XVECEXP (insn, 0, 1), asm_out_file, optimize, 0, 1, NULL);

  INSN_DELETED_P (XVECEXP (insn, 0, 1)) = 1;
}

I'm not sure, but I think the "1" could be turned into "0" safely.

I added a static global because output_asm_insn is used all over the place in 
the back-ends and only a minority of targets uses delay slots.

Bootstrapped/regtested on sparc64-sun-solaris2.9 and sparc-sun-solaris2.8.  
OK for mainline?


2004-07-09  Eric Botcazou  <ebotcazou@libertysurf.fr>

	* final.c (output_in_slot): New global variable.
	(final_scan_insn): Rename 'nopeepholes' parameter into 'inslot'.
	Pass zero as 'inslot' for the first insn of a SEQUENCE.  Adjust
	for above renaming.  Set 'output_in_slot' to the value of 'inslot'
	before invoking output_asm_insn and unset it after.
	(output_asm_insn): Add a space after the tab if 'output_in_slot'
	is set.


-- 
Eric Botcazou

[-- Attachment #2: sparc_prettify-2.diff --]
[-- Type: text/x-diff, Size: 3139 bytes --]

Index: final.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/final.c,v
retrieving revision 1.318
diff -u -p -r1.318 final.c
--- final.c	1 Jul 2004 17:09:31 -0000	1.318
+++ final.c	9 Jul 2004 10:07:03 -0000
@@ -200,6 +200,10 @@ static int app_on;
 
 rtx final_sequence;
 
+/* True if we are outputting insns in a delay slot.  This is used to prettify
+   the assembly output.  */
+static bool output_in_slot;
+
 #ifdef ASSEMBLER_DIALECT
 
 /* Number of the assembler dialect to use, starting at 0.  */
@@ -1663,8 +1667,8 @@ scan_ahead_for_unlikely_executed_note (r
    is the insn being scanned.
    Value returned is the next insn to be scanned.
 
-   NOPEEPHOLES is the flag to disallow peephole processing (currently
-   used for within delayed branch sequence output).
+   INSLOT is used to specify that we are in the
+   slot of a delayed branch.
 
    SEEN is used to track the end of the prologue, for emitting
    debug information.  We force the emission of a line note after
@@ -1674,8 +1678,7 @@ scan_ahead_for_unlikely_executed_note (r
 
 rtx
 final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
-		 int prescan, int nopeepholes ATTRIBUTE_UNUSED,
-		 int *seen)
+		 int prescan, int inslot, int *seen)
 {
 #ifdef HAVE_cc0
   rtx set;
@@ -2187,7 +2190,7 @@ final_scan_insn (rtx insn, FILE *file, i
 	       thought unnecessary.  If that happens, cancel this sequence
 	       and cause that insn to be restored.  */
 
-	    next = final_scan_insn (XVECEXP (body, 0, 0), file, 0, prescan, 1, seen);
+	    next = final_scan_insn (XVECEXP (body, 0, 0), file, 0, prescan, 0, seen);
 	    if (next != XVECEXP (body, 0, 1))
 	      {
 		final_sequence = 0;
@@ -2394,7 +2397,7 @@ final_scan_insn (rtx insn, FILE *file, i
 #ifdef HAVE_peephole
 	/* Do machine-specific peephole optimizations if desired.  */
 
-	if (optimize && !flag_no_peephole && !nopeepholes)
+	if (optimize && !flag_no_peephole && !inslot)
 	  {
 	    rtx next = peephole (insn);
 	    /* When peepholing, if there were notes within the peephole,
@@ -2405,7 +2408,7 @@ final_scan_insn (rtx insn, FILE *file, i
 
 		for (note = NEXT_INSN (insn); note != next;
 		     note = NEXT_INSN (note))
-		  final_scan_insn (note, file, optimize, prescan, nopeepholes, seen);
+		  final_scan_insn (note, file, optimize, prescan, inslot, seen);
 
 		/* In case this is prescan, put the notes
 		   in proper position for later rescan.  */
@@ -2529,8 +2532,9 @@ final_scan_insn (rtx insn, FILE *file, i
 	IA64_UNWIND_EMIT (asm_out_file, insn);
 #endif
 	/* Output assembler code from the template.  */
-
+	output_in_slot = inslot;
 	output_asm_insn (template, recog_data.operand);
+	output_in_slot = false;
 
 	/* If necessary, report the effect that the instruction has on
 	   the unwind info.   We've already done this for delay slots
@@ -3001,6 +3005,8 @@ output_asm_insn (const char *template, r
   memset (opoutput, 0, sizeof opoutput);
   p = template;
   putc ('\t', asm_out_file);
+  if (output_in_slot)
+    putc (' ', asm_out_file);
 
 #ifdef ASM_OUTPUT_OPCODE
   ASM_OUTPUT_OPCODE (asm_out_file, p);

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

* Re: [PATCH] Prettify assembly output on SPARC (part #2)
  2004-07-09 11:39 [PATCH] Prettify assembly output on SPARC (part #2) Eric Botcazou
@ 2004-07-09 17:02 ` Richard Sandiford
  2004-09-05 15:25 ` Hans-Peter Nilsson
  1 sibling, 0 replies; 8+ messages in thread
From: Richard Sandiford @ 2004-07-09 17:02 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, dave.anglin, joern.rennecke

Eric Botcazou <ebotcazou@libertysurf.fr> writes:
> 	* final.c (output_in_slot): New global variable.
> 	(final_scan_insn): Rename 'nopeepholes' parameter into 'inslot'.
> 	Pass zero as 'inslot' for the first insn of a SEQUENCE.  Adjust
> 	for above renaming.  Set 'output_in_slot' to the value of 'inslot'
> 	before invoking output_asm_insn and unset it after.
> 	(output_asm_insn): Add a space after the tab if 'output_in_slot'
> 	is set.

Sorry for making such a moronic "contribution", but mips already
emphasises delay slots by writing a newline after the delay slot
insn.  I kind-of like the output the way it is now.

Not trying to stand in the way of your patch though.  Just thought
I'd mention it...

Richard

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

* Re: [PATCH] Prettify assembly output on SPARC (part #2)
  2004-07-09 11:39 [PATCH] Prettify assembly output on SPARC (part #2) Eric Botcazou
  2004-07-09 17:02 ` Richard Sandiford
@ 2004-09-05 15:25 ` Hans-Peter Nilsson
  2004-09-06  7:14   ` Eric Botcazou
  1 sibling, 1 reply; 8+ messages in thread
From: Hans-Peter Nilsson @ 2004-09-05 15:25 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, dave.anglin, joern.rennecke

On Fri, 9 Jul 2004, Eric Botcazou wrote:
> The patch tweaks final.c to let it output insns in a delay slot with a
> 1-space indentation over the normal ones.  This makes it easier for humans
> to parse the assembly output:

But breaks targets using #NO_APP.  Consider adding a newline
afterwards instead, or make this change target-tweakable.  (A
space isn't "prettyfying".)

Anyway, you can definitely do this in your target instead (see
CRIS) and I think that's much preferrable.  What's "pretty" is
in the eye of the target maintainer.

Now that the patch has been approved, you broke cris-*.
Please revert.

I wouldn't have thought the patch would be accepted without the
targetification, so I didn't voice concern... :-(

brgds, H-P

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

* Re: [PATCH] Prettify assembly output on SPARC (part #2)
  2004-09-05 15:25 ` Hans-Peter Nilsson
@ 2004-09-06  7:14   ` Eric Botcazou
  2004-09-06 12:28     ` Hans-Peter Nilsson
  0 siblings, 1 reply; 8+ messages in thread
From: Eric Botcazou @ 2004-09-06  7:14 UTC (permalink / raw)
  To: Hans-Peter Nilsson; +Cc: gcc-patches, dave.anglin, joern.rennecke

> Anyway, you can definitely do this in your target instead (see
> CRIS) and I think that's much preferrable.  What's "pretty" is
> in the eye of the target maintainer.

Ok, I obviously didn't choose the right approach to attack the problem.

> Now that the patch has been approved, you broke cris-*.
> Please revert.

Would you mind doing it on my behalf?  I now suffer from technical glitches
that prevent me from doing any checkin in the tree.  Thanks in advance.

--
Eric Botcazou

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

* Re: [PATCH] Prettify assembly output on SPARC (part #2)
  2004-09-06  7:14   ` Eric Botcazou
@ 2004-09-06 12:28     ` Hans-Peter Nilsson
  2004-09-06 15:50       ` Eric Botcazou
  0 siblings, 1 reply; 8+ messages in thread
From: Hans-Peter Nilsson @ 2004-09-06 12:28 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, dave.anglin, joern.rennecke

On Mon, 6 Sep 2004, Eric Botcazou wrote:
> > Anyway, you can definitely do this in your target instead (see
> > CRIS) and I think that's much preferrable.  What's "pretty" is
> > in the eye of the target maintainer.
>
> Ok, I obviously didn't choose the right approach to attack the problem.
>
> > Now that the patch has been approved, you broke cris-*.
> > Please revert.
>
> Would you mind doing it on my behalf?  I now suffer from technical glitches
> that prevent me from doing any checkin in the tree.  Thanks in advance.

I'll try and do better than that: I'll target-hookize this
functionality for you, but then I'll also ask you to
bootstrap+test my patch on a sparc target.  Film at 11.

brgds, H-P

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

* Re: [PATCH] Prettify assembly output on SPARC (part #2)
  2004-09-06 12:28     ` Hans-Peter Nilsson
@ 2004-09-06 15:50       ` Eric Botcazou
  2004-09-06 17:39         ` Hans-Peter Nilsson
  0 siblings, 1 reply; 8+ messages in thread
From: Eric Botcazou @ 2004-09-06 15:50 UTC (permalink / raw)
  To: Hans-Peter Nilsson; +Cc: gcc-patches, dave.anglin, joern.rennecke

> I'll try and do better than that: I'll target-hookize this
> functionality for you, but then I'll also ask you to
> bootstrap+test my patch on a sparc target.  Film at 11.

I've now recovered so I can revert it.  You mentioned that the cris back-end 
already does some kind of prettifying.  Can I not do it for SPARC the same 
way?

As we'd say in French, too many hooks kill hooks.

-- 
Eric Botcazou

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

* Re: [PATCH] Prettify assembly output on SPARC (part #2)
  2004-09-06 15:50       ` Eric Botcazou
@ 2004-09-06 17:39         ` Hans-Peter Nilsson
  2004-09-08 19:34           ` Eric Botcazou
  0 siblings, 1 reply; 8+ messages in thread
From: Hans-Peter Nilsson @ 2004-09-06 17:39 UTC (permalink / raw)
  To: Eric Botcazou; +Cc: gcc-patches, dave.anglin, joern.rennecke

On Mon, 6 Sep 2004, Eric Botcazou wrote:
> > I'll try and do better than that: I'll target-hookize this
> > functionality for you, but then I'll also ask you to
> > bootstrap+test my patch on a sparc target.  Film at 11.
>
> I've now recovered so I can revert it.  You mentioned that the cris back-end
> already does some kind of prettifying.  Can I not do it for SPARC the same
> way?

If you just want to output something *after* (the whole
output of) a filled delay-slot, there's DBR_OUTPUT_SEQEND.

Alternatively, if you settle for outputting something *before*
the *whole* insn-line for an filled delay-slot you can do it
in the existing sparc.c:print_operand case for '#'.
Obviously you can already do whatever you please for an unfilled
one there.  (Hmm, there's already a space there before the
"nop".)

If that doesn't fit, you can supposedly use ASM_OUTPUT_OPCODE
(perhaps together with global flags set at the '#' case as above
or just use dbr_sequence_length () if it's available) to also
handle (at least) special output of the insn part of a filled
delay-slot.

I think that covers all cases.

For CRIS, I just output a '\n' in DBR_OUTPUT_SEQEND, which is
enough to make filled delay-slots catch my eye.  Nop's (output
for unfilled delay-slots) are enough of an eye-catcher by
themselves.

> As we'd say in French, too many hooks kill hooks.

A clear hook (instead of three different ones) to cater to
target-needs for outputting an insn in a delay-slot, whether
something special is needed before, on the line or after the
insn-line, seems appropriate to me.  Mais si vous voulez.

brgds, H-P

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

* Re: [PATCH] Prettify assembly output on SPARC (part #2)
  2004-09-06 17:39         ` Hans-Peter Nilsson
@ 2004-09-08 19:34           ` Eric Botcazou
  0 siblings, 0 replies; 8+ messages in thread
From: Eric Botcazou @ 2004-09-08 19:34 UTC (permalink / raw)
  To: gcc-patches; +Cc: Hans-Peter Nilsson

[-- Attachment #1: Type: text/plain, Size: 2245 bytes --]

> If you just want to output something *after* (the whole
> output of) a filled delay-slot, there's DBR_OUTPUT_SEQEND.

Not pretty enough ;-)

> Alternatively, if you settle for outputting something *before*
> the *whole* insn-line for an filled delay-slot you can do it
> in the existing sparc.c:print_operand case for '#'.
> Obviously you can already do whatever you please for an unfilled
> one there.  (Hmm, there's already a space there before the
> "nop".)
>
> If that doesn't fit, you can supposedly use ASM_OUTPUT_OPCODE
> (perhaps together with global flags set at the '#' case as above
> or just use dbr_sequence_length () if it's available) to also
> handle (at least) special output of the insn part of a filled
> delay-slot.

It turned out that I indeed needed both.  I also took the opportunity to do a 
last stage2 clean-up.  Bootstrapped/regtested (c,c++,objc,f95) on 
sparc64-sun-solaris2.9 and sparc-sun-solaris2.8.  Applied to mainline.

Thanks for your help.


2004-09-08  Eric Botcazou  <ebotcazou@libertysurf.fr>

	* config/sparc/sparc.c (sparc_indent_opcode): New variable.
	(output_return): Do not test for the presence of the 'unimp' insn.
	Use 'current_function_uses_only_leaf_regs' and 'final_sequence'
	as predicates instead of custom ones.  Return raw strings when
	possible.
	(output_sibcall): Likewise.  Concatenate strings.
	(output_ubranch): Remove kludge for TurboSPARC.
	(output_cbranch): Remove 'noop' parameter.  Do not output 'nop'.
	(output_v9branch): Likewise.
	(print_operand): Use 'final_sequence' instead of 'dbr_sequence_length'.
	<#>: Set sparc_indent_opcode if the delay slot is filled.
	<(>: Likewise.
	<)>: New operand to emit the displacement from the saved PC on return.
	<@>: Remove.
	* config/sparc/sparc.h (sparc_indent_opcode): Declare it.
	(ASM_OUTPUT_OPCODE): New macro.
	(PRINT_OPERAND_PUNCT_VALID_P): Remove '^' and add ')'.
	* config/sparc/sparc.md (normal_branch, inverted_branch,
	normal_fp_branch, inverted_fp_branch, normal_fpe_branch,
	inverted_fpe_branch): Adjust call to output_cbranch.
	(normal_int_branch_sp64, inverted_int_branch_sp64): Adjust
	call to output_v9branch.
	* config/sparc/sparc-protos.h (output_cbranch): Adjust.
	(output_v9branch): Likewise.


-- 
Eric Botcazou

[-- Attachment #2: sparc_prettify-3.diff --]
[-- Type: text/x-diff, Size: 25400 bytes --]

Index: config/sparc/sparc-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc-protos.h,v
retrieving revision 1.47
diff -c -p -r1.47 sparc-protos.h
*** config/sparc/sparc-protos.h	14 Jul 2004 06:24:26 -0000	1.47
--- config/sparc/sparc-protos.h	7 Sep 2004 13:12:39 -0000
*************** extern void sparc_emit_set_symbolic_cons
*** 81,91 ****
  extern int sparc_splitdi_legitimate (rtx, rtx);
  extern int sparc_absnegfloat_split_legitimate (rtx, rtx);
  extern const char *output_ubranch (rtx, int, rtx);
! extern const char *output_cbranch (rtx, rtx, int, int, int, int, rtx);
  extern const char *output_return (rtx);
  extern const char *output_sibcall (rtx, rtx);
  extern const char *output_v8plus_shift (rtx *, rtx, const char *);
! extern const char *output_v9branch (rtx, rtx, int, int, int, int, int, rtx);
  extern void emit_v9_brxx_insn (enum rtx_code, rtx, rtx);
  extern void print_operand (FILE *, rtx, int);
  extern int mems_ok_for_ldd_peep (rtx, rtx, rtx);
--- 81,91 ----
  extern int sparc_splitdi_legitimate (rtx, rtx);
  extern int sparc_absnegfloat_split_legitimate (rtx, rtx);
  extern const char *output_ubranch (rtx, int, rtx);
! extern const char *output_cbranch (rtx, rtx, int, int, int, rtx);
  extern const char *output_return (rtx);
  extern const char *output_sibcall (rtx, rtx);
  extern const char *output_v8plus_shift (rtx *, rtx, const char *);
! extern const char *output_v9branch (rtx, rtx, int, int, int, int, rtx);
  extern void emit_v9_brxx_insn (enum rtx_code, rtx, rtx);
  extern void print_operand (FILE *, rtx, int);
  extern int mems_ok_for_ldd_peep (rtx, rtx, rtx);
Index: config/sparc/sparc.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.c,v
retrieving revision 1.331
diff -c -p -r1.331 sparc.c
*** config/sparc/sparc.c	6 Sep 2004 19:59:30 -0000	1.331
--- config/sparc/sparc.c	7 Sep 2004 13:13:06 -0000
*************** struct machine_function GTY(())
*** 276,285 ****
     Normally, this is %fp, but if we are in a leaf procedure, this
     is %sp+"something".  We record "something" separately as it may
     be too big for reg+constant addressing.  */
- 
  static rtx frame_base_reg;
  static HOST_WIDE_INT frame_base_offset;
  
  static void sparc_init_modes (void);
  static void scan_record_type (tree, int *, int *, int *);
  static int function_arg_slotno (const CUMULATIVE_ARGS *, enum machine_mode,
--- 276,287 ----
     Normally, this is %fp, but if we are in a leaf procedure, this
     is %sp+"something".  We record "something" separately as it may
     be too big for reg+constant addressing.  */
  static rtx frame_base_reg;
  static HOST_WIDE_INT frame_base_offset;
  
+ /* 1 if the next opcode is to be specially indented.  */
+ int sparc_indent_opcode = 0;
+ 
  static void sparc_init_modes (void);
  static void scan_record_type (tree, int *, int *, int *);
  static int function_arg_slotno (const CUMULATIVE_ARGS *, enum machine_mode,
*************** output_restore (rtx pat)
*** 4675,4718 ****
  const char *
  output_return (rtx insn)
  {
!   int leaf_function_p = current_function_uses_only_leaf_regs;
!   bool delay_slot_filled_p = dbr_sequence_length () > 0;
!   /* True if the caller has placed an "unimp" insn immediately after the call.
!      This insn is used in the 32-bit ABI when calling a function that returns
!      a non zero-sized structure. The 64-bit ABI doesn't have it.  Be careful
!      to have this test be the same as that used on the call.  */
!   bool sparc_skip_caller_unimp
!     = ! TARGET_ARCH64
!       && current_function_returns_struct
!       && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl)))
! 	  == INTEGER_CST)
!       && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl)));
! 
!   if (leaf_function_p)
      {
        /* This is a leaf function so we don't have to bother restoring the
  	 register window, which frees us from dealing with the convoluted
  	 semantics of restore/return.  We simply output the jump to the
! 	 return address and the insn in the delay slot, which usually is
! 	 the substraction restoring the stack pointer %sp.  */
  
        if (current_function_calls_eh_return)
  	abort ();
  
!       fprintf (asm_out_file, "\tjmp\t%%o7+%d\n", sparc_skip_caller_unimp ? 12 : 8);
! 
!       if (delay_slot_filled_p)
! 	{
! 	  rtx delay = NEXT_INSN (insn);
! 	  if (! delay)
! 	    abort ();
! 
! 	  final_scan_insn (delay, asm_out_file, 1, 0, 1, NULL);
! 	  PATTERN (delay) = gen_blockage ();
! 	  INSN_CODE (delay) = -1;
! 	}
!       else
! 	fputs ("\t nop\n", asm_out_file);
      }
    else
      {
--- 4677,4693 ----
  const char *
  output_return (rtx insn)
  {
!   if (current_function_uses_only_leaf_regs)
      {
        /* This is a leaf function so we don't have to bother restoring the
  	 register window, which frees us from dealing with the convoluted
  	 semantics of restore/return.  We simply output the jump to the
! 	 return address and the insn in the delay slot (if any).  */
  
        if (current_function_calls_eh_return)
  	abort ();
  
!       return "jmp\t%%o7+%)%#";
      }
    else
      {
*************** output_return (rtx insn)
*** 4725,4731 ****
  	{
  	  /* If the function uses __builtin_eh_return, the eh_return
  	     machinery occupies the delay slot.  */
! 	  if (delay_slot_filled_p || sparc_skip_caller_unimp)
  	    abort ();
  
  	  if (! flag_delayed_branch)
--- 4700,4706 ----
  	{
  	  /* If the function uses __builtin_eh_return, the eh_return
  	     machinery occupies the delay slot.  */
! 	  if (final_sequence)
  	    abort ();
  
  	  if (! flag_delayed_branch)
*************** output_return (rtx insn)
*** 4741,4747 ****
  	  else
  	    fputs ("\t nop\n", asm_out_file);
  	}
!       else if (delay_slot_filled_p)
  	{
  	  rtx delay, pat;
  
--- 4716,4722 ----
  	  else
  	    fputs ("\t nop\n", asm_out_file);
  	}
!       else if (final_sequence)
  	{
  	  rtx delay, pat;
  
*************** output_return (rtx insn)
*** 4754,4785 ****
  	  if (TARGET_V9 && ! epilogue_renumber (&pat, 1))
  	    {
  	      epilogue_renumber (&pat, 0);
! 	      fprintf (asm_out_file, "\treturn\t%%i7+%d\n",
! 		       sparc_skip_caller_unimp ? 12 : 8);
! 	      final_scan_insn (delay, asm_out_file, 1, 0, 1, NULL);
  	    }
  	  else
  	    {
! 	      fprintf (asm_out_file, "\tjmp\t%%i7+%d\n",
! 		       sparc_skip_caller_unimp ? 12 : 8);
  	      output_restore (pat);
  	    }
- 
- 	  PATTERN (delay) = gen_blockage ();
- 	  INSN_CODE (delay) = -1;
  	}
        else
          {
  	  /* The delay slot is empty.  */
  	  if (TARGET_V9)
! 	    fprintf (asm_out_file, "\treturn\t%%i7+%d\n\t nop\n",
! 		     sparc_skip_caller_unimp ? 12 : 8);
  	  else if (flag_delayed_branch)
! 	    fprintf (asm_out_file, "\tjmp\t%%i7+%d\n\t restore\n",
! 		     sparc_skip_caller_unimp ? 12 : 8);
  	  else
! 	    fprintf (asm_out_file, "\trestore\n\tjmp\t%%o7+%d\n\t nop\n",
! 		     sparc_skip_caller_unimp ? 12 : 8);
  	}
      }
  
--- 4729,4753 ----
  	  if (TARGET_V9 && ! epilogue_renumber (&pat, 1))
  	    {
  	      epilogue_renumber (&pat, 0);
! 	      return "return\t%%i7+%)%#";
  	    }
  	  else
  	    {
! 	      output_asm_insn ("jmp\t%%i7+%)", NULL);
  	      output_restore (pat);
+ 	      PATTERN (delay) = gen_blockage ();
+ 	      INSN_CODE (delay) = -1;
  	    }
  	}
        else
          {
  	  /* The delay slot is empty.  */
  	  if (TARGET_V9)
! 	    return "return\t%%i7+%)\n\t nop";
  	  else if (flag_delayed_branch)
! 	    return "jmp\t%%i7+%)\n\t restore";
  	  else
! 	    return "restore\n\tjmp\t%%o7+%)\n\t nop";
  	}
      }
  
*************** output_return (rtx insn)
*** 4791,4798 ****
  const char *
  output_sibcall (rtx insn, rtx call_operand)
  {
-   int leaf_function_p = current_function_uses_only_leaf_regs;
-   bool delay_slot_filled_p = dbr_sequence_length () > 0;
    rtx operands[1];
  
    if (! flag_delayed_branch)
--- 4759,4764 ----
*************** output_sibcall (rtx insn, rtx call_opera
*** 4800,4835 ****
  
    operands[0] = call_operand;
  
!   if (leaf_function_p)
      {
        /* This is a leaf function so we don't have to bother restoring the
  	 register window.  We simply output the jump to the function and
  	 the insn in the delay slot (if any).  */
  
!       if (LEAF_SIBCALL_SLOT_RESERVED_P && delay_slot_filled_p)
  	abort();
  
!       if (delay_slot_filled_p)
! 	{
! 	  rtx delay = NEXT_INSN (insn);
! 	  if (! delay)
! 	    abort ();
! 
! 	  output_asm_insn ("sethi\t%%hi(%a0), %%g1", operands);
! 	  output_asm_insn ("jmp\t%%g1 + %%lo(%a0)", operands);
! 	  final_scan_insn (delay, asm_out_file, 1, 0, 1, NULL);
! 
! 	  PATTERN (delay) = gen_blockage ();
! 	  INSN_CODE (delay) = -1;
! 	}
!       else
! 	{
! 	  /* Use or with rs2 %%g0 instead of mov, so that as/ld can optimize
! 	     it into branch if possible.  */
! 	  output_asm_insn ("or\t%%o7, %%g0, %%g1", operands);
! 	  output_asm_insn ("call\t%a0, 0", operands);
! 	  output_asm_insn (" or\t%%g1, %%g0, %%o7", operands);
! 	}
      }
    else
      {
--- 4766,4788 ----
  
    operands[0] = call_operand;
  
!   if (current_function_uses_only_leaf_regs)
      {
        /* This is a leaf function so we don't have to bother restoring the
  	 register window.  We simply output the jump to the function and
  	 the insn in the delay slot (if any).  */
  
!       if (LEAF_SIBCALL_SLOT_RESERVED_P && final_sequence)
  	abort();
  
!       if (final_sequence)
! 	output_asm_insn ("sethi\t%%hi(%a0), %%g1\n\tjmp\t%%g1 + %%lo(%a0)%#",
! 			 operands);
!       else
! 	/* Use or with rs2 %%g0 instead of mov, so that as/ld can optimize
! 	   it into branch if possible.  */
! 	output_asm_insn ("or\t%%o7, %%g0, %%g1\n\tcall\t%a0, 0\n\t or\t%%g1, %%g0, %%o7",
! 			 operands);
      }
    else
      {
*************** output_sibcall (rtx insn, rtx call_opera
*** 4839,4845 ****
  
        output_asm_insn ("call\t%a0, 0", operands);
  
!       if (delay_slot_filled_p)
  	{
  	  rtx delay = NEXT_INSN (insn);
  	  if (! delay)
--- 4792,4798 ----
  
        output_asm_insn ("call\t%a0, 0", operands);
  
!       if (final_sequence)
  	{
  	  rtx delay = NEXT_INSN (insn);
  	  if (! delay)
*************** const char *
*** 6118,6168 ****
  output_ubranch (rtx dest, int label, rtx insn)
  {
    static char string[64];
!   bool noop = false;
    char *p;
  
!   /* TurboSPARC is reported to have problems with
!      with
! 	foo: b,a foo
!      i.e. an empty loop with the annul bit set.  The workaround is to use 
!         foo: b foo; nop
!      instead.  */
! 
!   if (! TARGET_V9 && flag_delayed_branch
!       && (INSN_ADDRESSES (INSN_UID (dest))
! 	  == INSN_ADDRESSES (INSN_UID (insn))))
      {
!       strcpy (string, "b\t");
!       noop = true;
      }
-   else
-     {
-       bool v9_form = false;
- 
-       if (TARGET_V9 && INSN_ADDRESSES_SET_P ())
- 	{
- 	  int delta = (INSN_ADDRESSES (INSN_UID (dest))
- 		       - INSN_ADDRESSES (INSN_UID (insn)));
- 	  /* Leave some instructions for "slop".  */
- 	  if (delta >= -260000 && delta < 260000)
- 	    v9_form = true;
- 	}
  
!       if (v9_form)
! 	strcpy (string, "ba%*,pt\t%%xcc, ");
!       else
! 	strcpy (string, "b%*\t");
!     }
  
    p = strchr (string, '\0');
    *p++ = '%';
    *p++ = 'l';
    *p++ = '0' + label;
    *p++ = '%';
!   if (noop)
!     *p++ = '#';
!   else
!     *p++ = '(';
    *p = '\0';
  
    return string;
--- 6071,6099 ----
  output_ubranch (rtx dest, int label, rtx insn)
  {
    static char string[64];
!   bool v9_form = false;
    char *p;
  
!   if (TARGET_V9 && INSN_ADDRESSES_SET_P ())
      {
!       int delta = (INSN_ADDRESSES (INSN_UID (dest))
! 		   - INSN_ADDRESSES (INSN_UID (insn)));
!       /* Leave some instructions for "slop".  */
!       if (delta >= -260000 && delta < 260000)
! 	v9_form = true;
      }
  
!   if (v9_form)
!     strcpy (string, "ba%*,pt\t%%xcc, ");
!   else
!     strcpy (string, "b%*\t");
  
    p = strchr (string, '\0');
    *p++ = '%';
    *p++ = 'l';
    *p++ = '0' + label;
    *p++ = '%';
!   *p++ = '(';
    *p = '\0';
  
    return string;
*************** output_ubranch (rtx dest, int label, rtx
*** 6177,6189 ****
  
     REVERSED is nonzero if we should reverse the sense of the comparison.
  
!    ANNUL is nonzero if we should generate an annulling branch.
! 
!    NOOP is nonzero if we have to follow this branch by a noop.  */
  
  const char *
  output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
! 		int noop, rtx insn)
  {
    static char string[64];
    enum rtx_code code = GET_CODE (op);
--- 6108,6118 ----
  
     REVERSED is nonzero if we should reverse the sense of the comparison.
  
!    ANNUL is nonzero if we should generate an annulling branch.  */
  
  const char *
  output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
! 		rtx insn)
  {
    static char string[64];
    enum rtx_code code = GET_CODE (op);
*************** output_cbranch (rtx op, rtx dest, int la
*** 6406,6423 ****
    if (far)
      {
        strcpy (p, ".+12\n\t nop\n\tb\t");
!       if (annul || noop)
          p[3] = '6';
        p += 14;
      }
    *p++ = '%';
    *p++ = 'l';
-   /* Set the char indicating the number of the operand containing the
-      label_ref.  */
    *p++ = label + '0';
    *p = '\0';
-   if (noop)
-     strcpy (p, "\n\t nop");
  
    return string;
  }
--- 6335,6352 ----
    if (far)
      {
        strcpy (p, ".+12\n\t nop\n\tb\t");
!       /* Skip the next insn if requested or
! 	 if we know that it will be a nop.  */
!       if (annul || ! final_sequence)
          p[3] = '6';
        p += 14;
      }
    *p++ = '%';
    *p++ = 'l';
    *p++ = label + '0';
+   *p++ = '%';
+   *p++ = '#';
    *p = '\0';
  
    return string;
  }
*************** sparc_emit_fixunsdi (rtx *operands, enum
*** 6644,6656 ****
  
     REVERSED is nonzero if we should reverse the sense of the comparison.
  
!    ANNUL is nonzero if we should generate an annulling branch.
! 
!    NOOP is nonzero if we have to follow this branch by a noop.  */
  
  const char *
  output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
! 		 int annul, int noop, rtx insn)
  {
    static char string[64];
    enum rtx_code code = GET_CODE (op);
--- 6573,6583 ----
  
     REVERSED is nonzero if we should reverse the sense of the comparison.
  
!    ANNUL is nonzero if we should generate an annulling branch.  */
  
  const char *
  output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
! 		 int annul, rtx insn)
  {
    static char string[64];
    enum rtx_code code = GET_CODE (op);
*************** output_v9branch (rtx op, rtx dest, int r
*** 6759,6765 ****
  	}
  
        strcpy (p, ".+12\n\t nop\n\t");
!       if (annul || noop)
          p[3] = '6';
        p += 12;
        if (veryfar)
--- 6686,6694 ----
  	}
  
        strcpy (p, ".+12\n\t nop\n\t");
!       /* Skip the next insn if requested or
! 	 if we know that it will be a nop.  */
!       if (annul || ! final_sequence)
          p[3] = '6';
        p += 12;
        if (veryfar)
*************** output_v9branch (rtx op, rtx dest, int r
*** 6776,6786 ****
    *p++ = '%';
    *p++ = 'l';
    *p++ = '0' + label;
    *p = '\0';
  
-   if (noop)
-     strcpy (p, "\n\t nop");
- 
    return string;
  }
  
--- 6705,6714 ----
    *p++ = '%';
    *p++ = 'l';
    *p++ = '0' + label;
+   *p++ = '%';
+   *p++ = '#';
    *p = '\0';
  
    return string;
  }
  
*************** print_operand (FILE *file, rtx x, int co
*** 7077,7119 ****
    switch (code)
      {
      case '#':
!       /* Output a 'nop' if there's nothing for the delay slot.  */
!       if (dbr_sequence_length () == 0)
  	fputs ("\n\t nop", file);
        return;
      case '*':
        /* Output an annul flag if there's nothing for the delay slot and we
! 	 are optimizing.  This is always used with '(' below.  */
!       /* Sun OS 4.1.1 dbx can't handle an annulled unconditional branch;
! 	 this is a dbx bug.  So, we only do this when optimizing.  */
!       /* On UltraSPARC, a branch in a delay slot causes a pipeline flush.
  	 Always emit a nop in case the next instruction is a branch.  */
!       if (dbr_sequence_length () == 0
! 	  && (optimize && (int)sparc_cpu < PROCESSOR_V9))
  	fputs (",a", file);
        return;
      case '(':
        /* Output a 'nop' if there's nothing for the delay slot and we are
  	 not optimizing.  This is always used with '*' above.  */
!       if (dbr_sequence_length () == 0
! 	  && ! (optimize && (int)sparc_cpu < PROCESSOR_V9))
  	fputs ("\n\t nop", file);
        return;
      case '_':
        /* Output the Embedded Medium/Anywhere code model base register.  */
        fputs (EMBMEDANY_BASE_REG, file);
        return;
-     case '@':
-       /* Print out what we are using as the frame pointer.  This might
- 	 be %fp, or might be %sp+offset.  */
-       /* ??? What if offset is too big? Perhaps the caller knows it isn't? */
-       fprintf (file, "%s+"HOST_WIDE_INT_PRINT_DEC,
- 	       reg_names[REGNO (frame_base_reg)], frame_base_offset);
-       return;
      case '&':
        /* Print some local dynamic TLS name.  */
        assemble_name (file, get_some_local_dynamic_name ());
        return;
      case 'Y':
        /* Adjust the operand to take into account a RESTORE operation.  */
        if (GET_CODE (x) == CONST_INT)
--- 7005,7059 ----
    switch (code)
      {
      case '#':
!       /* Output an insn in a delay slot.  */
!       if (final_sequence)
!         sparc_indent_opcode = 1;
!       else
  	fputs ("\n\t nop", file);
        return;
      case '*':
        /* Output an annul flag if there's nothing for the delay slot and we
! 	 are optimizing.  This is always used with '(' below.
!          Sun OS 4.1.1 dbx can't handle an annulled unconditional branch;
! 	 this is a dbx bug.  So, we only do this when optimizing.
!          On UltraSPARC, a branch in a delay slot causes a pipeline flush.
  	 Always emit a nop in case the next instruction is a branch.  */
!       if (! final_sequence && (optimize && (int)sparc_cpu < PROCESSOR_V9))
  	fputs (",a", file);
        return;
      case '(':
        /* Output a 'nop' if there's nothing for the delay slot and we are
  	 not optimizing.  This is always used with '*' above.  */
!       if (! final_sequence && ! (optimize && (int)sparc_cpu < PROCESSOR_V9))
  	fputs ("\n\t nop", file);
+       else if (final_sequence)
+         sparc_indent_opcode = 1;
+       return;
+     case ')':
+       /* Output the right displacement from the saved PC on function return.
+ 	 The caller may have placed an "unimp" insn immediately after the call
+ 	 so we have to account for it.  This insn is used in the 32-bit ABI
+ 	 when calling a function that returns a non zero-sized structure. The
+ 	 64-bit ABI doesn't have it.  Be careful to have this test be the same
+ 	 as that used on the call.  */
+      if (! TARGET_ARCH64
+ 	 && current_function_returns_struct
+ 	 && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl)))
+ 	     == INTEGER_CST)
+ 	 && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl))))
+ 	fputs ("12", file);
+       else
+         fputc ('8', file);
        return;
      case '_':
        /* Output the Embedded Medium/Anywhere code model base register.  */
        fputs (EMBMEDANY_BASE_REG, file);
        return;
      case '&':
        /* Print some local dynamic TLS name.  */
        assemble_name (file, get_some_local_dynamic_name ());
        return;
+ 
      case 'Y':
        /* Adjust the operand to take into account a RESTORE operation.  */
        if (GET_CODE (x) == CONST_INT)
Index: config/sparc/sparc.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.h,v
retrieving revision 1.265
diff -c -p -r1.265 sparc.h
*** config/sparc/sparc.h	18 Aug 2004 17:05:13 -0000	1.265
--- config/sparc/sparc.h	7 Sep 2004 13:13:18 -0000
*************** do {									\
*** 2517,2522 ****
--- 2517,2535 ----
  #define ASM_OUTPUT_IDENT(FILE, NAME) \
    fprintf (FILE, "%s\"%s\"\n", IDENT_ASM_OP, NAME);
  
+ /* Prettify the assembly.  */
+ 
+ extern int sparc_indent_opcode;
+ 
+ #define ASM_OUTPUT_OPCODE(FILE, PTR)	\
+   do {					\
+     if (sparc_indent_opcode)		\
+       {					\
+ 	putc (' ', FILE);		\
+ 	sparc_indent_opcode = 0;	\
+       }					\
+   } while (0)
+ 
  /* Emit a dtp-relative reference to a TLS variable.  */
  
  #ifdef HAVE_AS_TLS
*************** do {									\
*** 2525,2532 ****
  #endif
  
  #define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
!   ((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^'		\
!    || (CHAR) == '(' || (CHAR) == '_' || (CHAR) == '&')
  
  /* Print operand X (an rtx) in assembler syntax to file FILE.
     CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
--- 2538,2545 ----
  #endif
  
  #define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
!   ((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '('		\
!    || (CHAR) == ')' || (CHAR) == '_' || (CHAR) == '&')
  
  /* Print operand X (an rtx) in assembler syntax to file FILE.
     CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
Index: config/sparc/sparc.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sparc/sparc.md,v
retrieving revision 1.213
diff -c -p -r1.213 sparc.md
*** config/sparc/sparc.md	13 Jul 2004 13:14:06 -0000	1.213
--- config/sparc/sparc.md	7 Sep 2004 13:13:32 -0000
***************
*** 1549,1555 ****
  {
    return output_cbranch (operands[0], operands[1], 1, 0,
  			 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! 			 ! final_sequence, insn);
  }
    [(set_attr "type" "branch")
     (set_attr "branch_type" "icc")])
--- 1549,1555 ----
  {
    return output_cbranch (operands[0], operands[1], 1, 0,
  			 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! 			 insn);
  }
    [(set_attr "type" "branch")
     (set_attr "branch_type" "icc")])
***************
*** 1565,1571 ****
  {
    return output_cbranch (operands[0], operands[1], 1, 1,
  			 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! 			 ! final_sequence, insn);
  }
    [(set_attr "type" "branch")
     (set_attr "branch_type" "icc")])
--- 1565,1571 ----
  {
    return output_cbranch (operands[0], operands[1], 1, 1,
  			 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! 			 insn);
  }
    [(set_attr "type" "branch")
     (set_attr "branch_type" "icc")])
***************
*** 1582,1588 ****
  {
    return output_cbranch (operands[1], operands[2], 2, 0,
  			 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! 			 ! final_sequence, insn);
  }
    [(set_attr "type" "branch")
     (set_attr "branch_type" "fcc")])
--- 1582,1588 ----
  {
    return output_cbranch (operands[1], operands[2], 2, 0,
  			 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! 			 insn);
  }
    [(set_attr "type" "branch")
     (set_attr "branch_type" "fcc")])
***************
*** 1599,1605 ****
  {
    return output_cbranch (operands[1], operands[2], 2, 1,
  			 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! 			 ! final_sequence, insn);
  }
    [(set_attr "type" "branch")
     (set_attr "branch_type" "fcc")])
--- 1599,1605 ----
  {
    return output_cbranch (operands[1], operands[2], 2, 1,
  			 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! 			 insn);
  }
    [(set_attr "type" "branch")
     (set_attr "branch_type" "fcc")])
***************
*** 1616,1622 ****
  {
    return output_cbranch (operands[1], operands[2], 2, 0,
  			 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! 			 ! final_sequence, insn);
  }
    [(set_attr "type" "branch")
     (set_attr "branch_type" "fcc")])
--- 1616,1622 ----
  {
    return output_cbranch (operands[1], operands[2], 2, 0,
  			 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! 			 insn);
  }
    [(set_attr "type" "branch")
     (set_attr "branch_type" "fcc")])
***************
*** 1633,1639 ****
  {
    return output_cbranch (operands[1], operands[2], 2, 1,
  			 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! 			 ! final_sequence, insn);
  }
    [(set_attr "type" "branch")
     (set_attr "branch_type" "fcc")])
--- 1633,1639 ----
  {
    return output_cbranch (operands[1], operands[2], 2, 1,
  			 final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! 			 insn);
  }
    [(set_attr "type" "branch")
     (set_attr "branch_type" "fcc")])
***************
*** 1655,1661 ****
  {
    return output_v9branch (operands[0], operands[2], 1, 2, 0,
  			  final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! 			  ! final_sequence, insn);
  }
    [(set_attr "type" "branch")
     (set_attr "branch_type" "reg")])
--- 1655,1661 ----
  {
    return output_v9branch (operands[0], operands[2], 1, 2, 0,
  			  final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! 			  insn);
  }
    [(set_attr "type" "branch")
     (set_attr "branch_type" "reg")])
***************
*** 1672,1678 ****
  {
    return output_v9branch (operands[0], operands[2], 1, 2, 1,
  			  final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! 			  ! final_sequence, insn);
  }
    [(set_attr "type" "branch")
     (set_attr "branch_type" "reg")])
--- 1672,1678 ----
  {
    return output_v9branch (operands[0], operands[2], 1, 2, 1,
  			  final_sequence && INSN_ANNULLED_BRANCH_P (insn),
! 			  insn);
  }
    [(set_attr "type" "branch")
     (set_attr "branch_type" "reg")])

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

end of thread, other threads:[~2004-09-08 19:19 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-07-09 11:39 [PATCH] Prettify assembly output on SPARC (part #2) Eric Botcazou
2004-07-09 17:02 ` Richard Sandiford
2004-09-05 15:25 ` Hans-Peter Nilsson
2004-09-06  7:14   ` Eric Botcazou
2004-09-06 12:28     ` Hans-Peter Nilsson
2004-09-06 15:50       ` Eric Botcazou
2004-09-06 17:39         ` Hans-Peter Nilsson
2004-09-08 19:34           ` Eric Botcazou

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).