Token-pasting trouble

M

Mark Odell

I've read the FAQ and I still can't see how to get what I want. Here's
what I'd like to do:

I have a list of register numbers that the CPU's instruction set
requires be literal constants, e.g.

#define DMA_CR0 0x100
#define DMA_CR1 0x108
#define DMA_CR2 0x110
#define DMA_CR3 0x118

I'd like to call another function with a one of these but make it
indexed like

dmaCr = dmaRdCr(channel); /* where channel = [0,..,3] */

and, logically, dmaRdCr() is implemented like this:

dmaRdCr(DMA_MAKE_REG_NUM(DMA_CR, channel);

I've got DMA_MAKE_REG_NUM defined as:
#define DMA_MAKE_REG_NUM(reg, ch) (ch == DMA_CHAN_0 ? reg##0 : \
ch == DMA_CHAN_1 ? reg##1 : \
ch == DMA_CHAN_2 ? reg##2 : \
ch == DMA_CHAN_3 ? reg##3 : -1)

But the compiler is unhappy with this. Is there a simpler way? Do I
simply have a substitution error?

Thanks,
 
I

Ivanna Pee

Mark said:
I've read the FAQ and I still can't see how to get what I want. Here's
what I'd like to do:

I have a list of register numbers that the CPU's instruction set
requires be literal constants, e.g.

#define DMA_CR0 0x100
#define DMA_CR1 0x108
#define DMA_CR2 0x110
#define DMA_CR3 0x118

I'd like to call another function with a one of these but make it
indexed like

dmaCr = dmaRdCr(channel); /* where channel = [0,..,3] */

and, logically, dmaRdCr() is implemented like this:

dmaRdCr(DMA_MAKE_REG_NUM(DMA_CR, channel);

I've got DMA_MAKE_REG_NUM defined as:
#define DMA_MAKE_REG_NUM(reg, ch) (ch == DMA_CHAN_0 ? reg##0 : \
ch == DMA_CHAN_1 ? reg##1 : \
ch == DMA_CHAN_2 ? reg##2 : \
ch == DMA_CHAN_3 ? reg##3 : -1)

But the compiler is unhappy with this. Is there a simpler way? Do I
simply have a substitution error?

Thanks,

This is a poor approach for embedded programming.
Use Memory Mapped I/O. I shall assume that these are 32bit registers
and and int is 32 bits on your processor.

#define IOBASE 0x100

typedef struct {
int dmacr0;
int pad0;
int dmacr1;
int pad1;
int dmacr2;
int pad2;
int dmacr3;
int pad3;
} my_iomap_t;

my_iomap_t *my_ioptr = IOBASE;

now ya dont need dmaRdCr() , ya just do

int reg2;
reg2 = my_ioptr->dmacr2;
--------------------------------------------
if you are not happy with this reccomendation, and really want to use
your literals,

int dmaRdCr(int chan)
{
return( *(int *) (DMA_CR0 + (8*chan))

}
 
M

Mark Odell

Ivanna said:
Mark said:
I've read the FAQ and I still can't see how to get what I want. Here's
what I'd like to do:

I have a list of register numbers that the CPU's instruction set
requires be literal constants, e.g.

#define DMA_CR0 0x100
#define DMA_CR1 0x108
#define DMA_CR2 0x110
#define DMA_CR3 0x118

I'd like to call another function with a one of these but make it
indexed like

dmaCr = dmaRdCr(channel); /* where channel = [0,..,3] */

and, logically, dmaRdCr() is implemented like this:

dmaRdCr(DMA_MAKE_REG_NUM(DMA_CR, channel);

I've got DMA_MAKE_REG_NUM defined as:
#define DMA_MAKE_REG_NUM(reg, ch) (ch == DMA_CHAN_0 ? reg##0 : \
ch == DMA_CHAN_1 ? reg##1 : \
ch == DMA_CHAN_2 ? reg##2 : \
ch == DMA_CHAN_3 ? reg##3 : -1)

But the compiler is unhappy with this. Is there a simpler way? Do I
simply have a substitution error?

Thanks,

This is a poor approach for embedded programming.

[snip]

You'd be right if the registers were memory mapped. They are accessed
via special CPU instructions only, e.g. mtdcr and mfdcr. That is, they
are Device Control Registers accessed over a custom DCR bus, thus the
Move To and Move From instructions. What's worse, is that these two
instructions *require* constant values, not values passed in registers
for the DCR, e.g.

mfdcr r3,0x108 ## Leagal

li r11,0x108
mfrdcr r3,r11 ## Illegal

So, since I can't do it the way you and I would like to do it I'd like
to reduce my maintenance overhead by using the C pre-proc. to generate
the literal constants on the flie.

And, yes, all the registers are 32-bits wide.

Thanks,

- Mark
 
S

Skarmander

Mark said:
I've read the FAQ and I still can't see how to get what I want. Here's
what I'd like to do:

I have a list of register numbers that the CPU's instruction set
requires be literal constants, e.g.

#define DMA_CR0 0x100
#define DMA_CR1 0x108
#define DMA_CR2 0x110
#define DMA_CR3 0x118

I'd like to call another function with a one of these but make it
indexed like

dmaCr = dmaRdCr(channel); /* where channel = [0,..,3] */
Vwl shrtg, n fn.
and, logically, dmaRdCr() is implemented like this:

dmaRdCr(DMA_MAKE_REG_NUM(DMA_CR, channel);
We encourage people to post actual code, not retyped code, for just this
sort of occurrence. This is not an implementation. And how are we supposed
to know your problem is not a missing parenthesis?
I've got DMA_MAKE_REG_NUM defined as:
#define DMA_MAKE_REG_NUM(reg, ch) (ch == DMA_CHAN_0 ? reg##0 : \
ch == DMA_CHAN_1 ? reg##1 : \
ch == DMA_CHAN_2 ? reg##2 : \
ch == DMA_CHAN_3 ? reg##3 : -1)

But the compiler is unhappy with this. Is there a simpler way? Do I
simply have a substitution error?
Again: post actual code and the error you get, not what you think
exemplifies the problem. The following compiles fine on my machine:

#define DMA_CHAN_0 0
#define DMA_CHAN_1 1
#define DMA_CHAN_2 2
#define DMA_CHAN_3 3
#define DMA_CR0 0x100
#define DMA_CR1 0x108
#define DMA_CR2 0x110
#define DMA_CR3 0x118

#define DMA_MAKE_REG_NUM(reg, ch) (ch == DMA_CHAN_0 ? reg##0 : \
ch == DMA_CHAN_1 ? reg##1 : \
ch == DMA_CHAN_2 ? reg##2 : \
ch == DMA_CHAN_3 ? reg##3 : -1)

#define dmaRdCr(channel) DMA_MAKE_REG_NUM(DMA_CR, channel)

void f(int channel) {
int dmaCr = dmaRdCr(channel);
}

This preprocesses to:

void f(int channel) {
int dmaCr = (channel == 0 ? 0x100 : channel == 1 ? 0x108 : channel == 2
? 0x110 : channel == 3 ? 0x118 : -1);
}

This in turn can be replaced with simple arithmetic, which may or may not be
desirable (a line of comment to explain it wouldn't hurt, but that line
saves you half a dozen lines of preprocessor magic).

Note that the expression above is not a literal, and never will be, even if
"channel" is. The preprocessor does not evaluate expressions. If for some
reason you need a literal there (and not just a constant expression), then
you have to skip a level and write out all the DMA_MAKE_REG_NUMs for every
value of "reg". That probably is more trouble than it's worth.

S.
 
I

Ivanna Pee

Mark said:
Ivanna said:
Mark said:
I've read the FAQ and I still can't see how to get what I want. Here's
what I'd like to do:

I have a list of register numbers that the CPU's instruction set
requires be literal constants, e.g.

#define DMA_CR0 0x100
#define DMA_CR1 0x108
#define DMA_CR2 0x110
#define DMA_CR3 0x118

I'd like to call another function with a one of these but make it
indexed like

dmaCr = dmaRdCr(channel); /* where channel = [0,..,3] */

and, logically, dmaRdCr() is implemented like this:

dmaRdCr(DMA_MAKE_REG_NUM(DMA_CR, channel);

I've got DMA_MAKE_REG_NUM defined as:
#define DMA_MAKE_REG_NUM(reg, ch) (ch == DMA_CHAN_0 ? reg##0 : \
ch == DMA_CHAN_1 ? reg##1 : \
ch == DMA_CHAN_2 ? reg##2 : \
ch == DMA_CHAN_3 ? reg##3 : -1)

But the compiler is unhappy with this. Is there a simpler way? Do I
simply have a substitution error?

Thanks,

This is a poor approach for embedded programming.

[snip]

You'd be right if the registers were memory mapped. They are accessed
via special CPU instructions only, e.g. mtdcr and mfdcr. That is, they
are Device Control Registers accessed over a custom DCR bus, thus the
Move To and Move From instructions. What's worse, is that these two
instructions *require* constant values, not values passed in registers
for the DCR, e.g.

mfdcr r3,0x108 ## Leagal

li r11,0x108
mfrdcr r3,r11 ## Illegal

So, since I can't do it the way you and I would like to do it I'd like
to reduce my maintenance overhead by using the C pre-proc. to generate
the literal constants on the flie.

And, yes, all the registers are 32-bits wide.

Thanks,

- Mark

You gonna hafta write an assembly function to read each register.
 
I

Ivanna Pee

Ivanna said:
Mark said:
Ivanna said:
Mark Odell wrote:
I've read the FAQ and I still can't see how to get what I want. Here's
what I'd like to do:

I have a list of register numbers that the CPU's instruction set
requires be literal constants, e.g.

#define DMA_CR0 0x100
#define DMA_CR1 0x108
#define DMA_CR2 0x110
#define DMA_CR3 0x118

I'd like to call another function with a one of these but make it
indexed like

dmaCr = dmaRdCr(channel); /* where channel = [0,..,3] */

and, logically, dmaRdCr() is implemented like this:

dmaRdCr(DMA_MAKE_REG_NUM(DMA_CR, channel);

I've got DMA_MAKE_REG_NUM defined as:
#define DMA_MAKE_REG_NUM(reg, ch) (ch == DMA_CHAN_0 ? reg##0 : \
ch == DMA_CHAN_1 ? reg##1 : \
ch == DMA_CHAN_2 ? reg##2 : \
ch == DMA_CHAN_3 ? reg##3 : -1)

But the compiler is unhappy with this. Is there a simpler way? Do I
simply have a substitution error?

Thanks,

[snip]

You'd be right if the registers were memory mapped. They are accessed
via special CPU instructions only, e.g. mtdcr and mfdcr. That is, they
are Device Control Registers accessed over a custom DCR bus, thus the
Move To and Move From instructions. What's worse, is that these two
instructions *require* constant values, not values passed in registers
for the DCR, e.g.

mfdcr r3,0x108 ## Leagal

li r11,0x108
mfrdcr r3,r11 ## Illegal

So, since I can't do it the way you and I would like to do it I'd like
to reduce my maintenance overhead by using the C pre-proc. to generate
the literal constants on the flie.

And, yes, all the registers are 32-bits wide.

Thanks,

- Mark

You gonna hafta write an assembly function to read each register.

or some self modifying code
 
M

Mark Odell

Skarmander said:
Mark said:
I've read the FAQ and I still can't see how to get what I want. Here's
what I'd like to do:

I have a list of register numbers that the CPU's instruction set
requires be literal constants, e.g.

#define DMA_CR0 0x100
#define DMA_CR1 0x108
#define DMA_CR2 0x110
#define DMA_CR3 0x118

I'd like to call another function with a one of these but make it
indexed like

dmaCr = dmaRdCr(channel); /* where channel = [0,..,3] */
Vwl shrtg, n fn.
and, logically, dmaRdCr() is implemented like this:

dmaRdCr(DMA_MAKE_REG_NUM(DMA_CR, channel);
We encourage people to post actual code, not retyped code, for just this
sort of occurrence. This is not an implementation. And how are we supposed
to know your problem is not a missing parenthesis?

This is pasted actual code:
Again: post actual code and the error you get, not what you think
exemplifies the problem. The following compiles fine on my machine:

#define DMA_CHAN_0 0
#define DMA_CHAN_1 1
#define DMA_CHAN_2 2
#define DMA_CHAN_3 3
#define DMA_CR0 0x100
#define DMA_CR1 0x108
#define DMA_CR2 0x110
#define DMA_CR3 0x118

#define DMA_MAKE_REG_NUM(reg, ch) (ch == DMA_CHAN_0 ? reg##0 : \
ch == DMA_CHAN_1 ? reg##1 : \
ch == DMA_CHAN_2 ? reg##2 : \
ch == DMA_CHAN_3 ? reg##3 : -1)

#define dmaRdCr(channel) DMA_MAKE_REG_NUM(DMA_CR, channel)

void f(int channel) {
int dmaCr = dmaRdCr(channel);
}

The implementation of the underlying macro is not ANSI C so I didn't
include that. I am lead to the conclusion that the assembler macro is
the source of the problem, not the run-time ?: (if-else) ladder.
This preprocesses to:

void f(int channel) {
int dmaCr = (channel == 0 ? 0x100 : channel == 1 ? 0x108 : channel == 2
? 0x110 : channel == 3 ? 0x118 : -1);
}

This in turn can be replaced with simple arithmetic, which may or may not be
desirable (a line of comment to explain it wouldn't hurt, but that line
saves you half a dozen lines of preprocessor magic).

Note that the expression above is not a literal, and never will be, even if
"channel" is. The preprocessor does not evaluate expressions. If for some
reason you need a literal there (and not just a constant expression), then
you have to skip a level and write out all the DMA_MAKE_REG_NUMs for every
value of "reg". That probably is more trouble than it's worth.

Ah, that's it. Since the evaluation of the ?: sequence is run-time, the
result is going to go into a register (e.g. not literal). So I cannot
do what I thought I could. Thank you for the analysis. It was trivial
to create accessors for every register using an editor macro but the
usage of those requires that I switch out on every use of them.

So, I suppose to make the usage easier for the programmer, I'll create
a switcher function that calls the correct worker function, e.g.

unsigned long dmaRdCr(DmaChanId chanId)
{
unsigned long regVal;

switch (chanId)
{
case DMA_CHAN_0: regVal = dmaRdCr0(); break;
case DMA_CHAN_1: regVal = dmaRdCr1(); break;
case DMA_CHAN_2: regVal = dmaRdCr2(); break;
case DMA_CHAN_3: regVal = dmaRdCr3(); break;
default; regVal = -1; break;
}

return regVal;
}

I already have all the worker functions written.

Thanks again,
 
M

Mark Odell

Ivanna said:
Ivanna said:
Mark said:
Ivanna Pee wrote:
Mark Odell wrote:
I've read the FAQ and I still can't see how to get what I want. Here's
what I'd like to do:

I have a list of register numbers that the CPU's instruction set
requires be literal constants, e.g.

#define DMA_CR0 0x100
#define DMA_CR1 0x108
#define DMA_CR2 0x110
#define DMA_CR3 0x118

I'd like to call another function with a one of these but make it
indexed like

dmaCr = dmaRdCr(channel); /* where channel = [0,..,3] */

and, logically, dmaRdCr() is implemented like this:

dmaRdCr(DMA_MAKE_REG_NUM(DMA_CR, channel);

I've got DMA_MAKE_REG_NUM defined as:
#define DMA_MAKE_REG_NUM(reg, ch) (ch == DMA_CHAN_0 ? reg##0 : \
ch == DMA_CHAN_1 ? reg##1 : \
ch == DMA_CHAN_2 ? reg##2 : \
ch == DMA_CHAN_3 ? reg##3 : -1)

But the compiler is unhappy with this. Is there a simpler way? Do I
simply have a substitution error?

Thanks,
--
- Mark

This is a poor approach for embedded programming.

[snip]

You'd be right if the registers were memory mapped. They are accessed
via special CPU instructions only, e.g. mtdcr and mfdcr. That is, they
are Device Control Registers accessed over a custom DCR bus, thus the
Move To and Move From instructions. What's worse, is that these two
instructions *require* constant values, not values passed in registers
for the DCR, e.g.

mfdcr r3,0x108 ## Leagal

li r11,0x108
mfrdcr r3,r11 ## Illegal

So, since I can't do it the way you and I would like to do it I'd like
to reduce my maintenance overhead by using the C pre-proc. to generate
the literal constants on the flie.

And, yes, all the registers are 32-bits wide.

Thanks,

- Mark

You gonna hafta write an assembly function to read each register.

Done that.
or some self modifying code

Hmm... that wouldn't be very hard actually. Thanks for the replies.
 
M

Mark Odell

So, just to close this out, I came up with this implementation template
(for example I use the CR register):

typedef unsigned long uint32;

#define DMA0_CR0 0x100
#define DMA0_CR1 0x108
#define DMA0_CR2 0x110
#define DMA0_CR3 0x118

__asm uint32 DMA_RD_REG(uint32 REG_DCR)
{
% con REG_DCR
! /* no unexpected regs altered */
mfdcr r3,REG_DCR
}

uint32 dmaRdCr0(void) { return DMA_RD_REG(DMA0_CR0); }
uint32 dmaRdCr1(void) { return DMA_RD_REG(DMA0_CR1); }
uint32 dmaRdCr2(void) { return DMA_RD_REG(DMA0_CR2); }
uint32 dmaRdCr3(void) { return DMA_RD_REG(DMA0_CR3); }
uint32 (*dmaRdCrChan[])(void) = { dmaRdCr0, dmaRdCr1, dmaRdCr2,
dmaRdCr3 };

/* For caller convenienc
*/
#define dmaRdCr(x) dmaRdCrChan[x]()

Thanks again for the help.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top