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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Minor feature for ld


On Tue, Sep 03, 2002 at 02:07:49PM -0400, Pete Gonzalez wrote:
> At 12:03 PM 9/3/2002, you wrote:
> >>    __attribute__((section("/0x123456/"))) int IOPort;
> >>    IOPort = x;
> >>    *(int *)0x123456 = x;
> >
> >It's easy enough to do this in C by doing
> >    int* IOPort = (int*) 0x123456;
> >    *IOPort = x;
> >
> >In most uses you will want volatile, as in
> >    volatile int* IOPort = (int*) 0x123456;
> >
> >What's the advantage of doing it in a linker section?
> 
> I'm working on an embedded system whose only input and output is
> through a large number of DMA ports.  Your suggestion above would
> allocate memory to store each global variable.  The obvious workaround
> is to use macros like this:
> 
>   #define SOME_PORT (*(int *)0x123456)
> 
> This is the C approach.  However, my problem is a little more complex
> because the ports are bit-fields.  So I have definitions (in C++)
> like this:
> 
>   PORTDEF_BEGIN(0x400000C,REG_BG2CNT);
>     PORTDEF_FIELD_O ( 0, 2, int,               priority);
>     PORTDEF_FIELD_O ( 2, 2, REG_BG::TDataPage, tileDataPage);
>     PORTDEF_FIELD_O ( 6, 1, bool,              enableMosaic);
>     PORTDEF_FIELD_O ( 7, 1, bool,              useGlobalPalette);
>     PORTDEF_FIELD_O ( 8, 5, REG_BG::TMapPage,  tileMapPage);
>     PORTDEF_FIELD_O (13, 1, bool,              areaOverflow);
>     PORTDEF_FIELD_O (14, 2, REG_BG::TTileMode, tileMode);
>   PORTDEF_END;
> 
>   void test() {
>     // BG2CNT is a 16-bit register at 0x400000C
>     REG_BG2CNT::priority = 3;  // assigns to bits 0..1
>     REG_BG2CNT::useGlobalPalette = true;  // assigns to bit 7
>     REG_BG2CNT::tileMode = MODE_TEXT_32x64; // assigns to bits 14..15
>   }
> 
> These macros are implemented using template classes and preprocessor
> hacks.  They also depend on the linker to discard ("/DISCARD/")
> a lot of auxiliary allocations which exist because of an ANSI
> requirement that memory be allocated for variables with sizeof(x) = 0.
> There are more hacks so that it compiles optimally (under -O2)
> and handles volatile addresses, etc.
> 
> All this complexity was worth it, because it dramatically simplifies
> the rest of the code, which previously was littered with C macros
> and error-prone bit twiddling.
> 
> But then it occurred to me that the hacks could be eliminated,
> if you could just map variables onto the ports.  In fact, most of
> cases could be handled with ordinary C bitfields:
> 
>   __attribute__((section("/0x400000C/"))) struct {
>     int priority : 2;
>     TDataPage tileDataPage : 2;
>     bool enableMosaic : 1;
>     // etc.
>   } REG_BG2CNT __attribute__((packed));
> 
> Well, you asked!  :-)

You can still do this... you need to define types for the variables in
a header, and declare them as "extern", then define them to the right
address in a linker script.  No need to use sections at all.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


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