How can I instruct the compiler to write
whatever value it finds handy in that moment?
P.S.
That won't make the code much better, I'm just curious.
> Some memory-mapped devices require a write to a specific
> memory address in order to do something.
> The data written is of no importance.
>
> How can I instruct the compiler to write
> whatever value it finds handy in that moment?
This may work:
unsigned char x;
*p = x;
--
Ben Pfaff
http://benpfaff.org
They typically are;-)
> How can I instruct the compiler to write
> whatever value it finds handy in that moment?
What means "handy at that moment"? That's a bit unspecific.
If you want to write just a single byte then, as Ben Pfaff
pointed out, using an unsigned char pointer (with the ad-
dress cast to that) would do. If you want to write more than
a single byte (but that would, of course, also work for a
single byte) you could use memcpy() to the target address,
cast to a void pointer. But there could be problems with
that: many devices want e.g. a single 16-bit or 32-bit wide
write or they won't do what you expect from such an access.
memcpy() is under no obligation to do it that way (even though
there's some chance that it copies in larger than 1-byte wide
chunks if possible). In device drivers you will often find
several functions for different wide accesses. If you need
e.g. to read or write 16-bit or 32-bit wide data instead of
an unsigned char (or uint8_t) pointer you'd use uint16_t or
uint32_t pointers. You have to carefully read the specifi-
cations for the hardware and decide which function to use
in each case - there's no fit-it-all function you could use
without further thought.
Regards, Jens
--
\ Jens Thoms Toerring ___ j...@toerring.de
\__________________________ http://toerring.de
Yes, but I'd be more comfortable with something like this:
#define ARBITRARY_DATA 42
*p = ARBITRARY_DATA;
For something other than a character type, reading an uninitialized
variable could allow the compiler to make certain assumptions that
could break your code. I think Ben's point is that the standard
makes certain extra guarantees about character types, but I wouldn't
want to depend on those guarantees without a good reason.
In either case, I'd say it's important to clearly document what you're
doing. (The name "ARBITRARY_DATA" is intended to do this.)
--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
> What means "handy at that moment"?
Writing whatever value is stored at that moment in whatever CPU
register.
And how is that better than, for example, always writing 42?
I was actually trying to avoid that approach,
because it requires the CPU to load a register with a
specific value, which isn't really necessary.
As I said to Jens:
"Writing whatever value is stored at that moment in whatever CPU
register",
without the need to initialize it first.
Maybe it is doable with in-line assembly, but I'm not sure how.
Maybe someone can adjust this (assuming DWORD access):
__asm *p = eax; // IA-32, write whatever was stored in EAX register.
__asm *p = R0; // ARM arch
> aleksa <alek...@gmail.com> writes:
>> On Feb 21, 7:23 pm, j...@toerring.de (Jens Thoms Toerring) wrote:
>>> What means "handy at that moment"?
>>
>> Writing whatever value is stored at that moment in whatever CPU
>> register.
>
> And how is that better than, for example, always writing 42?
It shaves a whole instruction cycle off the write to the watchdog
register :)
I read the OP's question as "I know this won't make any difference,
but as an academic excersize, how could it be done?"
--
/Wegge
Leder efter redundant peering af dk.*,linux.debian.*
> I read the OP's question as "I know this won't make any difference,
> but as an academic excersize, how could it be done?"
Exactly :)
> On Feb 21, 8:05 pm, Keith Thompson <ks...@mib.org> wrote:
>> #define ARBITRARY_DATA 42
>> *p = ARBITRARY_DATA;
>
> I was actually trying to avoid that approach,
> because it requires the CPU to load a register with a
> specific value, which isn't really necessary.
Not necessarily - all of the assembler languages I'm familiar with have
an instruction to store a literal value, and I assume any decent compiler
would emit such an instruction if given the above code.
sherm--
--
Sherm Pendley
<http://camelbones.sourceforge.net>
Cocoa Developer
> aleksa <alek...@gmail.com> writes:
>
>> On Feb 21, 8:05 pm, Keith Thompson <ks...@mib.org> wrote:
>>> #define ARBITRARY_DATA 42
>>> *p = ARBITRARY_DATA;
>>
>> I was actually trying to avoid that approach,
>> because it requires the CPU to load a register with a
>> specific value, which isn't really necessary.
>
> Not necessarily - all of the assembler languages I'm familiar with have
> an instruction to store a literal value, and I assume any decent compiler
> would emit such an instruction if given the above code.
Based on a few minutes looking around the Internet, I don't think
that ARM has a "store immediate" instruction.
--
"Give me a couple of years and a large research grant,
and I'll give you a receipt." --Richard Heathfield
Yes, I've forgotten about that...
But that is usually a 1 byte longer instruction :)
Yes, I've forgotten about that...
But that is usually a 1 byte longer instruction :)
And I'm not sure if ARM can do that, especially if its
base + offset = data
There's no way to do this in C. There may be ways to do it in
a particular implementation of C, with a particular set of compiler
options, under a particular set of conditions that enable or prevent
particular optimizations, if you're a left-handed seventh son of a
seventh son programming in an abandoned churchyard by the light of
the second full Moon of an odd-numbered month.
(In short, if you're counting the individual instructions that
the machine executes to carry out the intent of your code, C is not
the way to express that intent. Wrong tool; use another.)
--
Eric Sosman
eso...@ieee-dot-org.invalid
> Yes, but I'd be more comfortable with something like this:
>
> #define ARBITRARY_DATA 42
> *p = ARBITRARY_DATA;
It just occurred to me, that noone have mentioned the volatile
keyword yet. Especially this case, where the same value is written
repeatedly, is warranting a volatile declaration of p. Otherwise te
compile may end up optimizing any but the first write into oblibion.
> It just occurred to me, that noone have mentioned the volatile
> keyword yet.
Hardware registers are to be defined as volatile, yes.
(not that it changes the original question, though)
It doesn't as I would like.
My compiler stores 0 in reg, then reg to memory.
(as opposed to just storing a reg to memory)
Does your compiler generate code to store 0, or does the register
just happen to contain 0?
> Does your compiler generate code to store 0, or does the register
> just happen to contain 0?
The first one.
The whole point was to not give x a value; please read back to
the beginning of the thread.
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa67f6aaa,0xaa9aa9f6,0x11f6},*p
=b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}
Did you read the OP?
"Some memory-mapped devices require a write to a specific
memory address in order to do something.
The data written is of no importance."
Hardware watchdogs are a common example of this.
--
Ian Collins
> Did you read the OP?
>
> "Some memory-mapped devices require a write to a specific
> memory address in order to do something.
> The data written is of no importance."
>
> Hardware watchdogs are a common example of this.
Some 16-color EGA/VGA display modes were another case. Here's
the comment that I put into the Linux 16-color framebuffer driver
many years ago when I wrote it:
/* The VGA's weird architecture often requires that we read a byte and
write a byte to the same location. It doesn't matter *what* byte
we write, however. This is because all the action goes on behind
the scenes in the VGA's 32-bit latch register, and reading and writing
video memory just invokes latch behavior.
To avoid race conditions (is this necessary?), reading and writing
the memory byte should be done with a single instruction. One
suitable instruction is the x86 bitwise OR. The following
read-modify-write routine should optimize to one such bitwise
OR. */
(It seems that someone modified the code and didn't update the
comment, though, since the code no longer uses a single
instruction to do it. I guess it wasn't necessary.)
The OP doesn't care what value is written, and just
wants a write to occur to a specific address. This is
a common paradigm in embedded systems, where you may
need to strobe an address via a read or write, and the
data involved is don't-care.
I have a 525-line C program that runs on an AT90S2313
(2K program memory, 128 byte SRAM) clocked at 500KHz
and if making changes occasionally have to look at the
assembly listing to figure out where I can save a few
cycles -- so I can understand the OP's concern about
unnecessarily loading a register. It's a bit more
difficult to understand the expectation of doing so
in a portable way.
--
jiw
That's a very politic inference ;)
My guess is that the compiler is generating code to initialize x.
I'd just leave it alone; we're talking like a billionth of a second
here.
By the way, more importantly:
volatile unsigned char *p;
--
-Ed Falk, fa...@despams.r.us.com
http://thespamdiaries.blogspot.com/
Two suggestions:
1. Use the value of the last assignment statement you used, which may
still be lying around in a register.
E.g. change:
++count;
*io_port_pointer = 0;
to
*io_port_pointer = (++count);
Some things to watch out for, though:
1. Make sure it doesn't have to sign-extend (or even 0-extend)
the value. This might slow things down instead of
speeding something up.
2. Watch out for order-of-evaluation problems, such as
the previous expression also doing something with the same port.
3. Watch out for nasty type clashes, such as io_port_pointer being
a pointer to an 8-bit quantity and count being a pointer or
float.
2. Use 0. I have noticed that some embedded compilers (specifically,
gcc-avr for Atmel 8-bit microcontrollers) tend to keep the value 0
around by loading a register with it and keeping it there. It's
handy for such things as 0-extends, var16bit += var8bit, and
var32bit += var16bit. Even if the compiler has to load the value,
an instruction like "clear r1", "subtract r1, r1" or "xor r1,r1"
may be shorter and faster than an instruction like "load immediate r1, 0".
3. Ask the user (if there is one) to press any key (if there is one),
read its value, and use that. Just kidding.
This might do what you want:
volatile register int junk;
volatile int *p = /* ... */;
*p = junk;
But there are no guarantees. You're trying to generate specific machine
code. A compiler's job is to generate machine code that has a specified
effect.
> It's a bit more difficult to understand the
> expectation of doing so in a portable way.
I didn't know if this is doable in portable C,
so I've asked here to be sure.
Since it looks like it is not,
I could post it somewhere else.
> Since it looks like it is not,
> I could post it somewhere else.
I've wrote this before seeing that
there is a next page in google.
Gordon Burditt's "last assignment statement"
and Keith Thompson's "register" are good ideas.
Thanks, everyone.
Andreas B. has an excellent idea - storing the pointer to itself!
http://embdev.net/topic/209508
*p = p;
or
BYTE *adr = ...; // or WORD / DWORD
*adr = adr;
Tested it on ARM and am quite sure it works on IA32:
mov [eax],al
mov [eax],ax
mov [eax],eax
> mov [eax],al
> mov [eax],ax
> mov [eax],eax
I'm more interested in ARM and
didn't think much about IA32.
IA32 could just store immediate to
direct address - one instruction only.
> aleksa <alek...@gmail.com> writes:
>
>> Some memory-mapped devices require a write to a specific
>> memory address in order to do something.
>> The data written is of no importance.
>>
>> How can I instruct the compiler to write
>> whatever value it finds handy in that moment?
>
> This may work:
>
> unsigned char x;
>
> *p = x;
Be warned! Even using 'unsigned char', under C1X this will be
undefined behavior. One way to fix that:
unsigned char x[1];
*p = *x;
"aleksa" <alek...@gmail.com> wrote in message
news:81128877-408d-4e35...@d16g2000yqd.googlegroups.com...
> Some memory-mapped devices require a write to a specific
> memory address in order to do something.
> The data written is of no importance.
>
> How can I instruct the compiler to write
> whatever value it finds handy in that moment?
Surely for anything like this, you'd just use some inline assembly (perhaps
wrapped in a macro).
I wouldn't trust the compiler; it might do it once, then the next time won't
bother because it thinks that location already contains the same value!
--
Bartc
> I wouldn't trust the compiler; it might do it once, then the next
> time won't bother because it thinks that location already contains
> the same value!
That's why we have the volatile keyword.
"Anders Wegge Keller" <we...@wegge.dk> wrote in message
news:87zkpnv...@huddi.jernurt.dk...
> "BartC" <b...@freeuk.com> writes:
>
>> I wouldn't trust the compiler; it might do it once, then the next
>> time won't bother because it thinks that location already contains
>> the same value!
>
> That's why we have the volatile keyword.
OK, but I'd still be wary of pretending i/o locations are really variables.
--
Bartc
Why?
A volatile declaration may be used to describe an object
corresponding to a memory-mapped input/output port or an object
accessed by an asynchronously interrupting function. Actions on
objects so declared shall not be ‘‘optimized out’’ by an
implementation or reordered except as permitted by the rules for
evaluating expressions.
> Ben Pfaff <b...@cs.stanford.edu> writes:
>
>> aleksa <alek...@gmail.com> writes:
>>
>>> Some memory-mapped devices require a write to a specific
>>> memory address in order to do something.
>>> The data written is of no importance.
>>>
>>> How can I instruct the compiler to write
>>> whatever value it finds handy in that moment?
>>
>> This may work:
>>
>> unsigned char x;
>>
>> *p = x;
>
> Be warned! Even using 'unsigned char', under C1X this will be
> undefined behavior.
Can you point to the change please? I had a look in what seemed like
the obvious places but did not find any smoking gun.
> One way to fix that:
>
> unsigned char x[1];
>
> *p = *x;
--
Ben.
One problem is that "What constitutes an access to an object that
has volatile-qualified type is implementation-defined" (6.7.3p6). It
is often the case that a magical memory address performs its magic
only if accessed by the right kind of instruction: For example, an
"I/O register" at location 0xFF001010 might respond to a four-byte
load or store at that address but not even notice a one-byte access
to location 0xFF001012. Since there's no way to get C-the-language
to generate any particular hardware instruction, there's no way to be
sure C-the-language will use the one you desire.
(This is not a theoretical matter, by the way. I once asked a lead
kernel engineer for a large computer vendor why none of their device
drivers were written in C. Her answer amounted to essentially this
issue: The special locations in the hardware worked only when accessed
as a unit, not when accessed byte-by-byte, and there was no reliable way
to ensure that C would use the former -- *especially* if somebody chose
to compile with a "tolerate misaligned pointers" switch enabled...)
On a given implementation there may be ways to ensure that C uses
the desired instructions -- it could be as simple as reading the
implementation's documents. But you can't just shout `volatile' and
expect that all problems are solved, nor should you assume that the
solution for one machine will behave as desired on another.
--
Eric Sosman
eso...@ieee-dot-org.invalid
> One problem is that "What constitutes an access to an object
> that has volatile-qualified type is implementation-defined"
> (6.7.3p6).
Yes, and I don't see that as a problem. After all, in the case where
any particular register is mapped into the address space, the
situation is already very specific.
...
> (This is not a theoretical matter, by the way.
I know. BTDTGTT, and all that.
> On a given implementation there may be ways to ensure that C
> uses the desired instructions -- it could be as simple as reading
> the implementation's documents. But you can't just shout `volatile'
> and expect that all problems are solved, nor should you assume that
> the solution for one machine will behave as desired on another.
Will you please decide if you want to discuss a specific
implementatio, or if you want to talk about a general case?
In the general case, adress 0x0842 has no universal meaning beyond
beaing an address. Thus, we never get to the point of having to worry
about different compilers ways with memory access.
In the specific case, on the other hand, where we acutally have a
well-defined meaning for that adress, I see no problem in acessing
it. I take it as a given that anyone doing low-level programming that
involves any amount of bit-baning will be competent enough to do so.
Sorry, I should have mentioned this - last sentence of 6.3.2.1p2:
If the lvalue designates an object of automatic storage
duration that could have been declared with the register
storage class (never had its address taken), and that object
is uninitialized (not declared with an initializer and no
assignment to it has been performed prior to use), the
behavior is undefined.
In the general case, 0x0842 is not an address at all; it's of
type int. It can be *converted* to some pointer type, and such
a conversion is "intended to be consistent with the addressing
structure of the execution environment".
We often refer to things like " address 0x0842", but that's either a
convenient verbal shorthand for the above conversion, or something
outside the scope of the C language. (Address 0x0842 might well
be a meaningful concept in the context of a particular CPU.)
> Anders Wegge Keller <we...@wegge.dk> writes:
> [...]
>> In the general case, adress 0x0842 has no universal meaning beyond
>> beaing an address. Thus, we never get to the point of having to worry
>> about different compilers ways with memory access.
> [...]
>
> In the general case, 0x0842 is not an address at all; it's of
> type int. It can be *converted* to some pointer type, and such
> a conversion is "intended to be consistent with the addressing
> structure of the execution environment".
Sorry for not being nit-picky enough do write (unsigned char
*0x0842). Quoting one of my colleagues, when we were at a Coccinelle
workshop "We're not C-linguists. We just use the language".
> We often refer to things like " address 0x0842", but that's either a
> convenient verbal shorthand for the above conversion, or something
> outside the scope of the C language. (Address 0x0842 might well
> be a meaningful concept in the context of a particular CPU.)
A lot of the things we do with C *is* outside the language proper. At
least, that's the case for me, and I expect that more and more of the
remaining C development is targeted at either freestanding
implementations in toasters etc. or low-level bit banging.
That will give some imprecise language that isn't proper in this
group, but please bear with me. I'm doubly challenged by also not
being a native english speaker.
Yes, and the Rationale recognizes this explicitly. So does the
Standard itself, albeit only in non-normative material.
There is nothing -- *nothing* -- wrong with crossing the line
between fully portable C and system-specific C. In my opinion, it
is both common and laudable to cross that line at need. But in my
opinion it is also important to know where the line is, to know what
parts of the code will require effort to port and what parts will
"port themselves," and to take appropriate precautionary measures.
Like, for example, wrapping those `volatile' pointer-from-integer
constructs inside easily-segregated functions instead of just letting
them float free throughout the code. You questioned BartC's advice
to "be wary" of raw access to memory-mapped registers; I think his
wariness is good engineering practice.
> At
> least, that's the case for me, and I expect that more and more of the
> remaining C development is targeted at either freestanding
> implementations in toasters etc. or low-level bit banging.
I betcha, I betcha, I betchamillionbucks that next year's toaster
will use a different CPU. Quite likely (but not certainly) a CPU in
the same family as this year's, but enhanced/cost-reduced/spiffed-up
in some way or other. And, lo! the code will have to be ported.
We have arrived at a situation where "soft"ware is something of a
misnomer. It used to be "soft" because it was malleable, it could be
changed cheaply without modifying the expensive and hard-to-change
hardware that it ran on. Well, nowadays the "hard"ware changes have
become faster than they were, while "soft"ware changes have grown more
and more difficult. An investment in "soft"ware can only be justified
if it can be amortized over several generations of "hard"ware -- or, in
short, your code *will* be ported. If you do not prepare for that
inevitability, you make yourself a net resource drain and not a net
contributor.
As for bit-banging -- well, I liked your earlier message about
"bit-baning" better! Bits have been the bane of most of us, and I
imagine they'll continue to be so. :-)
(A European colleague once gave me his business card, which
described him as a "System-Berater," a German title we might render in
English as "System Advisor" or "System Consultant." But the English
verb "berate" means to scold or chastise, and I immediately pictured
the fellow wagging an admonitory forefinger at a recalcitrant computer
and saying "Bad system! Baaadddd system! No dessert for you!!!")
> That will give some imprecise language that isn't proper in this
> group, but please bear with me. I'm doubly challenged by also not
> being a native english speaker.
Anders, your English is one helluvalot better than my Norwegian!
There's a saying: If you speak many languages you're "multilingual,"
if you speak two languages you're "bilingual," and if you speak one
language you're "American."
--
Eric Sosman
eso...@ieee-dot-org.invalid