473,395 Members | 1,456 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Token-pasting trouble

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

Apr 6 '06 #1
8 1600

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

}

Apr 6 '06 #2
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

Apr 6 '06 #3

Mark Odell wrote:
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.

Apr 6 '06 #4
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] */
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.
Apr 6 '06 #5

Ivanna Pee wrote:
Mark Odell wrote:
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.


or some self modifying code

Apr 6 '06 #6
Skarmander 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] */
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:
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);
}


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,

--
- Mark

Apr 6 '06 #7
Ivanna Pee wrote:
Ivanna Pee wrote:
Mark Odell wrote:
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.
--
- Mark

Apr 6 '06 #8
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.
--
- Mark

Apr 6 '06 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

5
by: Andrew James | last post by:
Gentlemen, I'm running into a problem whilst testing the parsing of a language I've created with TPG . It seems that for some reason, TPG balks when I try to parse an expression whose first...
9
by: Peter Ammon | last post by:
As we know, due to C++'s "longest match" rule, the >> token causes headaches when working with nested templates, e.g. vector<vector<int>> will not parse correctly without inserting a space...
14
by: Simon Morgan | last post by:
I'm trying to write a function to parse a Reverse Polish Notation string from stdin and return 1 token at a time. For those of you who are unaware an RPN string looks like this: 1 2 + 4 * 3 + ...
1
by: Joel Rondeau | last post by:
I am building a mixed-mode DLL with VS.NET 2003 and have run across some link errors. (I have looked at the MS Help articles about LNK2020 errors with mixed-mode C++ and that has not helped)...
10
by: Ian Lazarus | last post by:
Hello. How do "unresolved token" link errors occur. How do I fix them? Linking... LINK : error LNK2020: unresolved token (0A000015) ??_7type_info@@6B@ LINK : error LNK2020: unresolved token...
0
by: Jay C. | last post by:
Jay 3 Jan. 11:38 Optionen anzeigen Newsgroups: microsoft.public.dotnet.framework.webservices.enhancements Von: "Jay" <p.brunm...@nusurf.at> - Nachrichten dieses Autors suchen Datum: 3 Jan...
3
by: Manuel | last post by:
I'm trying to compile glut 3.7.6 (dowbloaded from official site)using devc++. So I've imported the glut32.dsp into devc++, included manually some headers, and start to compile. It return a very...
12
by: Joriveek | last post by:
Hi, I have a little piece of program here Basically what it does is, it copies the strings of variable widths. The basis is until it finds a comma ",". The input is a CSV/Comma Separated...
0
by: Sid DeLuca | last post by:
I'm modifying the WSE2 HOL sample to develop my web service. I'm able to get the client application's username token encrypted on the way out (outputTrace.webinfo), but not on receipt from the...
2
by: Lan Mind | last post by:
Hello again everybody, My page: http://www.dockhawk.com/ I'm trying to implement some "session security" PHP script mentioned in the "Cross-site request forgery" section of this tutorials...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.