Bill Auerbach wrote: >> -----Original Message----- >> From: [EMAIL PROTECTED] >> [mailto:[EMAIL PROTECTED] On >> Behalf Of Jonathan Larmour >> Sent: Thursday, August 28, 2008 6:39 PM >> To: Mailing list for lwIP users >> Subject: Re: [lwip-users] Problem With dns.c Using 32-Bit Compilers >> >> Alain M. wrote: >>>> It would be really handy, if, somehow, there could be a sys_arch >>>> style hook or macro for protocol fragment encoding/decoding that >>>> would default to structure overlaying, but let you override it with >>>> byte-by-byte copying to a compiler friendly data structure if you >> need to. >>> I have seen a comm packet long time ago that used macros with >>> pointers, and I used that for some small things. It is 100% portable >>> and performance would be hw dependent. Probably in chips like ARM7/9 >>> it would be bad, but on PCs and Cortex that have byte access it would >>> be better, no idea about 16 bits DSP. Also remember that 99% of >>> protocol header variables are contained in 32 bit words so it will >> not be too bad. >>> the example would be: >>> struct dns_answer { >>> /* DNS answer record starts with either a domain name or a pointer >>> to a name already present somewhere in the packet. */ >>> u16_t type; >>> u16_t class; >>> u32_t ttl; >>> u16_t len; >>> } PACK_STRUCT_STRUCT; >>> >>> char dns_answer[10]; >>> #define dns_answer_type (*((u16_t*)dns_answer)) #define >>> dns_answer_class (*((u16_t*)&dns_answer[2])) >>> #define dns_answer_ttl (*((u32_t*)&dns_answer[4])) >>> #define dns_answer_len (*((u16_t*)&dns_answer[8])) >>> >>> or with pointers: >>> #define dns_answer_type(p) (*((u16_t*)p)) #define >> dns_answer_class(p) >>> (*((u16_t*)(p+2))) >>> >>> or some variations... (or fixes, I may have it wrong) >> Unfortunately, the above is still not portable. That may well cause a >> mis-aligned access if dns_answer is not already aligned, and being char >> that isn't guaranteed. > > What about macros to make it portable and universal? > > #ifdef WORD_ACCESS_PROCESSOR > #if BYTE_ORDER == LITTLE_ENDIAN > #define _W(w) ((*(u8_t*) &(w))+(*(((u8_t*) &(w))+1)<<8)) > #endif > #if BYTE_ORDER == BIG_ENDIAN > #define _W(w) (*(((u8_t*) &(w))+1)+(*((u8_t*) &(w))<<8)) > #endif > #else > #define _W(w) w > #endif > > This could be expanded to u32_t if needed. It's not as nice reading to have > _W on all u16_t accesses, but once done, it's done. Not unlike all the MS > VC++ code using _T with string literals.
I know from bitter experience the above wouldn't quite work portably and reliably due to pointer aliasing issues. You would actually need an assignment rather than an rvalue expression (i.e. _W16(x,y) where the potentially unaligned 16-bit value at y gets assigned to u16_t x). But something along those lines could conceivably work. Of course it will take someone with the inclination and using an affected compiler+processor in order to do the work, and there would be a fair bit of it in the core stack when dealing with dismantling/assembling protocol headers. Patches welcome :-). Jifl -- eCosCentric Limited http://www.eCosCentric.com/ The eCos experts Barnwell House, Barnwell Drive, Cambridge, UK. Tel: +44 1223 245571 Registered in England and Wales: Reg No 4422071. ------["Si fractum non sit, noli id reficere"]------ Opinions==mine _______________________________________________ lwip-users mailing list [email protected] http://lists.nongnu.org/mailman/listinfo/lwip-users
