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


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!  :-)

-Pete


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