_GLOBAL_$F$
Kai Ruottu
kai.ruottu@luukku.com
Sun Oct 28 12:39:00 GMT 2001
When being out of town during the last week (north of the arctic circle seeing
nice aurora borealis...) this a little late but perhaps not too much...
Nik Ilijic wrote:
>
> I'm working with gcc ver 2.95.3 on a linux box, compiling to an embedded
> 68360 target (m68k-coff target). So far I have managed to compile & link my
> project, but have come across a problem with the size of the binary.
AFAIK, the m68k-coff target doesn't use things related to DWARF2, which is
quite ELF-related, referring to the reply from Dave Korn...
> the entire code (.text) and .data sections are about twice the size as I get
> with the SDS toolset. After examining the map file produced by the linker,
> the biggest blowout seems to be in the data section and it is caused by
> these _GLOBAL_$F$ references (see section of map file below).
The thread "Can't build gcc-3.0.1 for m68k-coff" on this list discussed about
the problems with the '__EH_FRAME_BEGIN__' appearing as undefined with gcc-3.0.1
but whether the same kind of problem (DWARF2-unwind stuff tried with COFF) already
existed in gcc-2.95.3 is unclear.
> What are these _GLOBAL_$F$'s and how do I get rid of them to reduce my
> code/data size so that it fits into the rom & ram.
I will try to see how the C++ parts in my gcc-2.95.3 behave, whether I get those
_GLOBAL_$F$'s too. Not toyed with the C++ and m68k much...
Meanwhile there are that very famous and much talked-about problem with the
'volatile' causing code-bloat with m68k, and another problem related to the
missing '__attribute__((interrupt))' with the m68k-targets. The following code
sample (stupid and not much related to m68k) should tell about these:
-------------------------- clip -------------------------------------
#include <stdio.h>
#ifndef ISR_FUNC
#define ISR_FUNC __attribute__((interrupt))
#endif
#define PBDR (*(volatile char *) (0xff60))
#define ITU_TSR0 (*(volatile char *) (0xff61))
#define ITU_TSR1 (*(volatile char *) (0xff62))
#define ITU_TSR2 (*(volatile char *) (0xff63))
/*
#define PBDR (*(char *) (0xff60))
#define ITU_TSR0 (*(char *) (0xff61))
#define ITU_TSR1 (*(char *) (0xff62))
#define ITU_TSR2 (*(char *) (0xff63))
*/
int count;
void set_itu_tsr12(void)
{
ITU_TSR1 |= 0x01;
ITU_TSR2 |= 0x02;
}
void clr_itu_tsr12(void)
{
ITU_TSR1 &= 0xFE;
ITU_TSR2 &= 0xFD;
}
void onoff_itu_tsr12(void)
{
ITU_TSR1 |= 0x01;
ITU_TSR2 |= 0x02;
ITU_TSR1 &= 0xFE;
ITU_TSR2 &= 0xFD;
}
void ISR_FUNC handle_intr(void)
{
count++;
if (count == 400)
{
PBDR ^= 0x01;
count = 0;
}
ITU_TSR0 |= 0x04;
/*
ITU_TSR0 &= 0xFE;
set_itu_tsr12();
clr_itu_tsr12();
*/
}
int main(void)
{
do {
puts("Thinking hard...\n");
} while (1);
return 0;
}
-------------------------- clip -------------------------------------
This could produce something like:
-------------------------- clip -------------------------------------
.file "isr_demo1.c"
gcc2_compiled.:
.text
.globl set_itu_tsr12
.type set_itu_tsr12,@function
set_itu_tsr12:
bset #0,65378
bset #1,65379
rts
nop
.Lfe1:
.size set_itu_tsr12,.Lfe1-set_itu_tsr12
.globl clr_itu_tsr12
.type clr_itu_tsr12,@function
clr_itu_tsr12:
bclr #0,65378
bclr #1,65379
rts
nop
.Lfe2:
.size clr_itu_tsr12,.Lfe2-clr_itu_tsr12
.globl onoff_itu_tsr12
.type onoff_itu_tsr12,@function
onoff_itu_tsr12:
move.l #65378,%a1
bset #0,(%a1)
move.l #65379,%a0
bset #1,(%a0)
bclr #0,(%a1)
bclr #1,(%a0)
rts
nop
.Lfe3:
.size onoff_itu_tsr12,.Lfe3-onoff_itu_tsr12
.globl handle_intr
.type handle_intr,@function
handle_intr:
move.l %d1,-(%sp)
move.l %d0,-(%sp)
move.l count,%d0
move.l %d0,%d1
addq.l #1,%d1
move.l %d1,count
cmp.l #399,%d0
jbne .L6
eor.b #1,65376
clr.l count
.L6:
bset #2,65377
move.l (%sp)+,%d0
move.l (%sp)+,%d1
rte
.Lfe4:
.size handle_intr,.Lfe4-handle_intr
.globl __main
.section .rodata
.LC0:
.string "Thinking hard...\n"
.text
.globl main
.type main,@function
main:
jsr __main
.L11:
pea .LC0
jsr puts
addq.l #4,%sp
jbra .L11
nop
.Lfe5:
.size main,.Lfe5-main
.comm count,4,2
.ident "GCC: (GNU) 2.95.3-1 20010315 (release)"
-------------------------- clip -------------------------------------
for cpu32, as my compiler does, but the plain vanilla gcc-2.95.3 for
m68k-coff/-elf doesn't understand the '__attribute__' and doesn't
generate the 'bset', 'bclr' etc. bit-operations with the 'volatile'...
If you try this test, you will see...
Ok, the patches for adding the '__attribute__' have appeared on this
list now and then but here they are again (attached). And I would suggest
trying the following hack for the 'gcc-2.95.3/gcc/recog.c' to solve the
'volatile' one :
-------------------------- clip -------------------------------------
*** recog.c.orig Sat Oct 28 22:21:47 2001
--- recog.c Sat Oct 28 22:21:46 2001
***************
*** 969,976 ****
--- 969,980 ----
if (code == MEM)
{
register rtx y = XEXP (op, 0);
+ /*
+ This hack should remove the 'volatile bug' !
+
if (! volatile_ok && MEM_VOLATILE_P (op))
return 0;
+ */
if (GET_CODE (y) == ADDRESSOF)
return 1;
/* Use the mem's mode, since it will be reloaded thus. */
-------------------------- clip -------------------------------------
I would be very curious to hear what this hack will break if anything...
Somehow I think it cannot be this easy, otherwise someone else would have
invented this years ago... The funny thing is that it seems to work and I
haven't found the things this would break...
Cheers, Kai
*** gcc/config/m68k/m68k.c.orig Mon Aug 7 19:21:51 2000
--- gcc/config/m68k/m68k.c Fri Aug 4 21:06:04 2000
***************
*** 1,5 ****
/* Subroutines for insn-output.c for Motorola 68000 family.
! Copyright (C) 1987, 93-98, 1999 Free Software Foundation, Inc.
This file is part of GNU CC.
--- 1,10 ----
/* Subroutines for insn-output.c for Motorola 68000 family.
! Copyright (C) 1987, 93-99, 2000 Free Software Foundation, Inc.
!
! Modified by (interrupt attribute patch):
! Michael Schwingen <rincewind@discworld.dascon.de>
! Kai Ruottu <karuottu@freenet.hut.fi>
! Ken Desmet <ken@sdt.be>
This file is part of GNU CC.
***************
*** 38,43 ****
--- 43,61 ----
/* Needed for use_return_insn. */
#include "flags.h"
+ /* Flag to tell if the current function is an interrupt handler. */
+ int interrupt_handler;
+
+ #define MUST_SAVE_REGISTER(regno) \
+ (! TREE_THIS_VOLATILE (current_function_decl) \
+ && (regno != STACK_POINTER_REGNUM) \
+ /* Save any call saved register that was used. */ \
+ && (regs_ever_live[regno] && !call_used_regs[regno]) \
+ /* Save any register used in an interrupt handler. */ \
+ || (regs_ever_live[regno] && interrupt_handler) \
+ /* Save call clobbered registers in non-leaf interrupt handlers. */ \
+ || (call_used_regs[regno] && interrupt_handler && !current_function_is_leaf))
+
#ifdef SUPPORT_SUN_FPA
/* Index into this array by (register number >> 3) to find the
***************
*** 152,157 ****
--- 170,188 ----
int cfa_offset = INCOMING_FRAME_SP_OFFSET, cfa_store_offset = cfa_offset;
+ interrupt_handler = m68k_interrupt_function_p (current_function_decl);
+ /* Save the floating point unit context in case of an interrupt (exception) */
+ if (TARGET_68881 && TARGET_EFPUCS && !current_function_is_leaf && interrupt_handler)
+ {
+ #ifdef MOTOROLA
+ asm_fprintf (stream, "\tfsave -(%Rsp)\n");
+ asm_fprintf (stream, "\tfmoveml %Rfpcr/%Rfpsr/%Rfpiar,-(%Rsp)\n");
+ #else
+ asm_fprintf (stream, "\tfsave -Rsp@-\n");
+ asm_fprintf (stream, "\tfmoveml %Rfpcr/%Rfpsr/%Rfpiar,%Rsp@-\n");
+ #endif
+ }
+
if (frame_pointer_needed)
{
if (fsize == 0 && TARGET_68040)
***************
*** 287,293 ****
}
#ifdef SUPPORT_SUN_FPA
for (regno = 24; regno < 56; regno++)
! if (regs_ever_live[regno] && ! call_used_regs[regno])
{
#ifdef MOTOROLA
asm_fprintf (stream, "\tfpmovd %s,-(%Rsp)\n",
--- 318,324 ----
}
#ifdef SUPPORT_SUN_FPA
for (regno = 24; regno < 56; regno++)
! if (MUST_SAVE_REGISTER(regno))
{
#ifdef MOTOROLA
asm_fprintf (stream, "\tfpmovd %s,-(%Rsp)\n",
***************
*** 310,319 ****
}
}
#endif
! if (TARGET_68881)
! {
for (regno = 16; regno < 24; regno++)
! if (regs_ever_live[regno] && ! call_used_regs[regno])
{
mask |= 1 << (regno - 16);
num_saved_regs++;
--- 341,351 ----
}
}
#endif
! if ((TARGET_68881 && !interrupt_handler) ||
! (TARGET_68881 && TARGET_EFPUCS && interrupt_handler ))
! {
for (regno = 16; regno < 24; regno++)
! if (MUST_SAVE_REGISTER(regno))
{
mask |= 1 << (regno - 16);
num_saved_regs++;
***************
*** 346,352 ****
num_saved_regs = 0;
}
for (regno = 0; regno < 16; regno++)
! if (regs_ever_live[regno] && ! call_used_regs[regno])
{
mask |= 1 << (15 - regno);
num_saved_regs++;
--- 378,384 ----
num_saved_regs = 0;
}
for (regno = 0; regno < 16; regno++)
! if (MUST_SAVE_REGISTER(regno))
{
mask |= 1 << (15 - regno);
num_saved_regs++;
***************
*** 484,489 ****
--- 516,522 ----
{
int regno;
+ interrupt_handler = m68k_interrupt_function_p (current_function_decl);
if (!reload_completed || frame_pointer_needed || get_frame_size () != 0)
return 0;
***************
*** 491,497 ****
separate layout routine to perform the common work. */
for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++)
! if (regs_ever_live[regno] && ! call_used_regs[regno])
return 0;
return 1;
--- 524,530 ----
separate layout routine to perform the common work. */
for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++)
! if (MUST_SAVE_REGISTER(regno))
return 0;
return 1;
***************
*** 519,525 ****
int big = 0;
rtx insn = get_last_insn ();
int restore_from_sp = 0;
!
/* If the last insn was a BARRIER, we don't have to write any code. */
if (GET_CODE (insn) == NOTE)
insn = prev_nonnote_insn (insn);
--- 552,559 ----
int big = 0;
rtx insn = get_last_insn ();
int restore_from_sp = 0;
!
! int interrupt_handler = m68k_interrupt_function_p (current_function_decl);
/* If the last insn was a BARRIER, we don't have to write any code. */
if (GET_CODE (insn) == NOTE)
insn = prev_nonnote_insn (insn);
***************
*** 544,558 ****
nregs = 0; fmask = 0; fpoffset = 0;
#ifdef SUPPORT_SUN_FPA
for (regno = 24 ; regno < 56 ; regno++)
! if (regs_ever_live[regno] && ! call_used_regs[regno])
nregs++;
fpoffset = nregs * 8;
#endif
nregs = 0;
! if (TARGET_68881)
{
for (regno = 16; regno < 24; regno++)
! if (regs_ever_live[regno] && ! call_used_regs[regno])
{
nregs++;
fmask |= 1 << (23 - regno);
--- 578,594 ----
nregs = 0; fmask = 0; fpoffset = 0;
#ifdef SUPPORT_SUN_FPA
for (regno = 24 ; regno < 56 ; regno++)
! if (MUST_SAVE_REGISTER(regno))
nregs++;
fpoffset = nregs * 8;
#endif
nregs = 0;
!
! if ((TARGET_68881 && !interrupt_handler) ||
! (TARGET_68881 && TARGET_EFPUCS && interrupt_handler ))
{
for (regno = 16; regno < 24; regno++)
! if (MUST_SAVE_REGISTER(regno))
{
nregs++;
fmask |= 1 << (23 - regno);
***************
*** 563,569 ****
if (frame_pointer_needed)
regs_ever_live[FRAME_POINTER_REGNUM] = 0;
for (regno = 0; regno < 16; regno++)
! if (regs_ever_live[regno] && ! call_used_regs[regno])
{
nregs++;
mask |= 1 << regno;
--- 599,605 ----
if (frame_pointer_needed)
regs_ever_live[FRAME_POINTER_REGNUM] = 0;
for (regno = 0; regno < 16; regno++)
! if (MUST_SAVE_REGISTER(regno))
{
nregs++;
mask |= 1 << regno;
***************
*** 718,724 ****
}
if (fpoffset != 0)
for (regno = 55; regno >= 24; regno--)
! if (regs_ever_live[regno] && ! call_used_regs[regno])
{
if (big)
{
--- 754,760 ----
}
if (fpoffset != 0)
for (regno = 55; regno >= 24; regno--)
! if (MUST_SAVE_REGISTER(regno))
{
if (big)
{
***************
*** 828,837 ****
#endif
}
}
! if (current_function_pops_args)
! asm_fprintf (stream, "\trtd %0I%d\n", current_function_pops_args);
else
! fprintf (stream, "\trts\n");
}
/* Similar to general_operand, but exclude stack_pointer_rtx. */
--- 864,890 ----
#endif
}
}
! if (interrupt_handler)
! {
! if (TARGET_68881 && TARGET_EFPUCS && !current_function_is_leaf)
! {
! #ifdef MOTOROLA
! asm_fprintf (stream, "\tfmoveml (%Rsp)+,%Rfpcr/%Rfpsr/%Rfpiar\n");
! asm_fprintf (stream, "\tfrestore (%Rsp)+\n");
! #else
! asm_fprintf (stream, "\tfmoveml %Rsp@+,%Rfpcr/%Rfpsr/%Rfpiar\n");
! asm_fprintf (stream, "\tfrestore %Rsp@+\n");
! #endif
! }
! fprintf (stream, "\trte\n");
! }
else
! {
! if (current_function_pops_args)
! asm_fprintf (stream, "\trtd %0I%d\n", current_function_pops_args);
! else
! fprintf (stream, "\trts\n");
! }
}
/* Similar to general_operand, but exclude stack_pointer_rtx. */
***************
*** 3397,3399 ****
--- 3450,3496 ----
}
return "eor%.l %2,%0";
}
+
+
+ /* Return nonzero if ATTR is a valid attribute for DECL.
+ ATTRIBUTES are any existing attributes and ARGS are the arguments
+ supplied with ATTR.
+
+ Supported attributes:
+
+ interrupt -- specifies this function is an interrupt handler.
+ */
+
+ int
+ m68k_valid_machine_decl_attribute (decl, attributes, attr, args)
+ tree decl;
+ tree attributes;
+ tree attr;
+ tree args;
+ {
+ if (args != NULL_TREE)
+ return 0;
+
+ if (is_attribute_p ("interrupt", attr))
+ return TREE_CODE (decl) == FUNCTION_DECL;
+
+ return 0;
+ }
+
+ /* Return nonzero if FUNC is an interrupt function as specified by the
+ "interrupt" attribute. */
+
+ int
+ m68k_interrupt_function_p(func)
+ tree func;
+ {
+ tree a;
+
+ if (TREE_CODE (func) != FUNCTION_DECL)
+ return 0;
+
+ a = lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (func));
+ return (a != NULL_TREE);
+ }
+
+
*** gcc/config/m68k/m68k.h.orig Mon Aug 7 19:21:57 2000
--- gcc/config/m68k/m68k.h Fri Aug 4 19:56:56 2000
***************
*** 119,124 ****
--- 119,131 ----
#define MASK_ALIGN_INT 4096
#define TARGET_ALIGN_INT (target_flags & MASK_ALIGN_INT)
+ /* When a floating point unit is used during an exception
+ (with the __attribute__ ((interrupt)) ), its context must be saved.
+ This has only effect when a 68881, 68882, 68040 or 68060 is used. */
+
+ #define MASK_EFPUCS 8192
+ #define TARGET_EFPUCS (target_flags & MASK_EFPUCS)
+
/* Compile for a CPU32 */
/* A 68020 without bitfields is a good heuristic for a CPU32 */
#define TARGET_CPU32 (TARGET_68020 && !TARGET_BITFIELD)
***************
*** 140,145 ****
--- 147,154 ----
|MASK_68020|MASK_BITFIELD|MASK_68881)}, \
{ "bitfield", MASK_BITFIELD}, \
{ "nobitfield", - MASK_BITFIELD}, \
+ { "noefpucs", -MASK_EFPUCS}, \
+ { "efpucs", MASK_EFPUCS}, \
{ "rtd", MASK_RTD}, \
{ "nortd", - MASK_RTD}, \
{ "short", MASK_SHORT}, \
***************
*** 152,157 ****
--- 161,168 ----
{ "nosky", - MASK_SKY}, \
{ "68881", - (MASK_FPA|MASK_SKY)}, \
{ "68881", MASK_68881}, \
+ { "68882", - (MASK_FPA|MASK_SKY)}, \
+ { "68882", MASK_68881}, \
{ "soft-float", - (MASK_FPA|MASK_SKY|MASK_68040_ONLY|MASK_68881)}, \
{ "68020-40", -(MASK_5200|MASK_68060|MASK_68040_ONLY)}, \
{ "68020-40", (MASK_BITFIELD|MASK_68881|MASK_68020|MASK_68040)}, \
***************
*** 2130,2135 ****
--- 2141,2158 ----
extern void notice_update_cc ();
extern void finalize_pic ();
extern void override_options ();
+
+ /* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS
+ is a valid machine specific attribute for DECL.
+ The attributes in ATTRIBUTES have previously been assigned to DECL. */
+
+ extern int m68k_valid_machine_decl_attribute ();
+
+ #define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \
+ m68k_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS)
+
+ extern int interrupt_handler;
+ extern int m68k_interrupt_function_p();
/*
*** gcc/config/m68k/m68k.md.orig Mon Aug 7 19:22:03 2000
--- gcc/config/m68k/m68k.md Fri Aug 4 19:24:58 2000
***************
*** 6964,6969 ****
--- 6964,6971 ----
"USE_RETURN_INSN"
"*
{
+ if (interrupt_handler)
+ return \"rte\";
if (current_function_pops_args == 0)
return \"rts\";
operands[0] = GEN_INT (current_function_pops_args);
More information about the crossgcc
mailing list