This is the mail archive of the crossgcc@sources.redhat.com mailing list for the crossgcc project.
See the CrossGCC FAQ for lots more information.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
Doug: Warning, OT! :^) > > Yep, structure-defined i/o is evil. But the alternatives are much worse... > > Do both? As in include/elf/external.h in binutils/gdb releases? > [or am I missing the point ...] This kind of stuff: unsigned char sh_size[4]; /* Size of section in bytes */ makes me wonder. I mean, I don't know much about BFD code, but I bet they're doing this because the endian ordering in a data file is consistent, and so they use some endian-neutral logic to parse the data: int sh_size = 0; int wbyte; Elf32_External_Shdr *shdr; for (wbyte = 0; wbyte < sizeof(shdr->sh_size); wbyte++) sh_size = (sh_size << 8) + shdr->sh_size[wbyte]; [note: off the top of my head, not taken from any particular example. ymmv] This is a good way to go about solving this particular class of problems, I think. The algorithm rigidly presumes a certain endian sense in the incoming data stream (in this case, big endian), but cleanly maps it to the host processor's integer endian orientation, whatever it happens to be, because the << operator in C is defined to be equivalent to a multiply, which is endian neutral. And what's more, the bitshift helps the compiler understand what's going on, so the optimizer can clean up the code if it can find a way to. The loop may get replaced with a single, 32-bit move on a big endian machine, for example. I came to this thread late, but I think Grant was considering using structure i/o to talk to external hardware devices vs. memcpy'ing the data around. Or, at least, that's what *I* was referring to. :^) I think that with few exceptions, the structure approach is the best way to go about talking to external hardware, because what you're doing is highly nonportable already (try switching endians on the host processor, changing processors, packed vs. unpacked, whatever), so you may as well go with something that's self-documenting so that when you have to go into the code to fix it, you can tell what the code is trying to do. The one exception I can think of is for using bitmaps in structures to talk to peripheral control registers that have "reserved, write zero" bit fields. I haven't come up with a clean way to deal with that one without resorting to some unions that let me mask the whole byte/word on the way out to the hardware, and *that* code starts looking pretty evil too. What would be cool is a language extension like this: typedef struct { unsigned int field1 : 1; /* read/write ok */ unsigned int field2 : 1; /* read/write ok */ unsigned int reserved : 2 = 0; /* reads garbage, write zero */ unsigned int field3 : 4 /* read/write ok */ } foo_hardware; So if I did this: foo_hardware *foo = FOO_ADDRESS; foo->field1 = 1; the underlying implementation would do this: *foo = (*foo | 0x80) & 0xcf; Now _that_ would be embedded friendly! /soapbox b.g. -- Bill Gatliff Affordable GNU and Linux training and consulting services. See http://billgatliff.com for details. etails. ------ Want more information? See the CrossGCC FAQ, http://www.objsw.com/CrossGCC/ Want to unsubscribe? Send a note to crossgcc-unsubscribe@sources.redhat.com
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |