Re: [Openocd-development] MIPS target, big endian host
On Mon, Jul 11, 2011 at 1:50 PM, Mahr, Stefan stefan.m...@sphairon.com wrote: Yes, if BE target shifts out an 32 bit value from address 0, it will begin with bit0:7, that is byte address 0x03 at targets memory. And host will do the same. When it shifts out 32-bit value , it will put contents of it's address 0x3 to output buffer[0] and send this first. I am talking about BE host, off course. LE host will put contents of it's 0x0 address to buffer[0] and send this out first. Yes, that's the way buf_get_u32 and buf_set_u32 works. OK, I think that things are clear now, and as I see it patching all the functions in PrAcc as you suggested seem to be realistic fix... BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
BTW, Stefan and all others, thank you very much for this long discussion and for the effort on explaining things. I think it was very useful. BR, Drasko On Tue, Aug 9, 2011 at 11:20 PM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: On Mon, Jul 11, 2011 at 1:50 PM, Mahr, Stefan stefan.m...@sphairon.com wrote: Yes, if BE target shifts out an 32 bit value from address 0, it will begin with bit0:7, that is byte address 0x03 at targets memory. And host will do the same. When it shifts out 32-bit value , it will put contents of it's address 0x3 to output buffer[0] and send this first. I am talking about BE host, off course. LE host will put contents of it's 0x0 address to buffer[0] and send this out first. Yes, that's the way buf_get_u32 and buf_set_u32 works. OK, I think that things are clear now, and as I see it patching all the functions in PrAcc as you suggested seem to be realistic fix... BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
buf_get_u32: return (((uint32_t)buffer[3]) 24) | (((uint32_t)buffer[2]) 16) | (((uint32_t)buffer[1]) 8) | (((uint32_t)buffer[0]) 0); I do not get this function at all... What I see is that it is presumed that host executing this code must be in the same endianess as the target who filled this buffer. Otherwise bytes get flipped. Here is an experiment : Let's imagine that target is BE. Then it will put word 0x12345678 read from the it's (target's) mem like this : buffer[0] = 0x12 buffer [1] = 0x34 buffer[2] = 0x56 buffer[3] = 0x78 Let's forget target endianness for a moment. If you buffer is filled like above, LE host will do following: result = (uint32_t)buffer[0] 0; // result = 0x0012 or in memory 0x12 0x00 0x00 0x00 result |= (uint32_t)buffer[1] 8; // result = 0x3412 or in memory 0x12 0x34 0x00 0x00 result |= (uint32_t)buffer[2] 16;// result = 0x00563412 or in memory 0x12 0x34 0x56 0x00 result |= (uint32_t)buffer[3] 24;// result = 0x78563412 or in memory 0x12 0x34 0x56 0x78 BE host will do: result = (uint32_t)buffer[0] 0; // result = 0x0012 or in memory 0x00 0x00 0x00 0x12 result |= (uint32_t)buffer[1] 8; // result = 0x3412 or in memory 0x00 0x00 0x34 0x12 result |= (uint32_t)buffer[2] 16;// result = 0x00563412 or in memory 0x00 0x56 0x34 0x12 result |= (uint32_t)buffer[3] 24;// result = 0x78563412 or in memory 0x78 0x56 0x34 0x12 As you see result is always the same, but order in memory differs depending on host endianness. This is what I mean when I say it's ensured the result is in host endianness. If you would simply cast the buffer, result would be swapped: LE host: result = (uint32_t)buffer[0];// result = 0x78563412 (memory 0x12 0x34 0x56 0x78) BE host: result = (uint32_t)buffer[0];// result = 0x12345678 (memory 0x12 0x34 0x56 0x78) What is funny however, is that I have BE target and LE host, and MIPS code seems to be working fine... Which would say that EJTAG somehow speaks LE with my host. Crazy thing. Byte 0 refers to bits 7:0, byte 1 refers to bits 15:8, byte 2 refers to bits 23:16, and byte 3 refers to bits 31:24, independent of endianess. My guess is, if you read out a 32bit value, target endianness doesn't matter. This is the only sane solution I can think of. It would say that EJTAG is a bi-endian machine that can read both BE and LE if we feed it fixed instr. size. No, there is no bi-endian machine. The sentence Byte 0 refers to bits 7:0, byte 1 refers to bits 15:8, byte 2 refers to bits 23:16, and byte 3 refers to bits 31:24, independent of endianess. says for me that EJTAG is always LE, no matter of target endianness setting. ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Mon, Jul 11, 2011 at 12:17 PM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: On Mon, Jul 11, 2011 at 7:31 AM, Øyvind Harboe oyvind.har...@zylin.com wrote: Now a sequence of 8 bit words happens to be identical to little endian representation In what way ? 8 bits is 8 bits - one byte, bits 7:0. I do not see BE or LE representation here... Consider a series of words in memory where the width is greater than 8. Clearly a BE series has a different representation than a LE version. For a series of words that are 8 bits long, then the BE series and LE series are identical. Further, if you have 32 bits stored in a series of bytes in memory, then the memory layout is identical to the memory layout of little endian layout. -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Mon, Jul 11, 2011 at 12:31 PM, Øyvind Harboe oyvind.har...@zylin.com wrote: On Mon, Jul 11, 2011 at 12:17 PM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: On Mon, Jul 11, 2011 at 7:31 AM, Øyvind Harboe oyvind.har...@zylin.com wrote: Now a sequence of 8 bit words happens to be identical to little endian representation In what way ? 8 bits is 8 bits - one byte, bits 7:0. I do not see BE or LE representation here... Consider a series of words in memory where the width is greater than 8. Clearly a BE series has a different representation than a LE version. For a series of words that are 8 bits long, then the BE series and LE series are identical. Further, if you have 32 bits stored in a series of bytes in memory, then the memory layout is identical to the memory layout of little endian layout. Sorry Øyvind, I did not get at first that you meant on this - a byte array in the mem. Yes, I agree, it has LE order when memory is observed (which is one of the main arguments of the LE camp why LE is natural). BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Mon, Jul 11, 2011 at 11:53 AM, Øyvind Harboe oyvind.har...@zylin.com wrote: I think there is a fundamental misunderstanding about JTAG and OpenOCD. Let me try to clarify: JTAG clocks in and out bits, not bytes, so the concept of big/small-endian does not enter the picture at the JTAG level. Sat that we have 0x12345678 at addr 0x0 on LE host. You will shift out byte 0x78 first, shifting out from LSB upwards. I.e. You will be starting with shifting out addr 0x0 on the host. Now, if the host is BE, you will again be shifting LSB first, but this time that means that you will be starting withs shifting out addr 0x3 (on the host) first. Am I correct so far ? At what addr will EJTAG on the other side write this byte ? At addr 0x0, or addr 0x03 - this is the main question. If it is LE, Byte0, as they say in manual, will be put to 0x0, and if it is BE MIPS, it will be put always to 0x3. So, the first 8 bits that MIPS EJTAG shifts in, which will be noted Byte0 in their terminology and represent bits 7:0, will be put to either addr 0x0 or 0x3 - depending on endianess of the MIPS target. That would say to me that MIPS EJTAG is actually doing following : 1) Takes the value of Byte0, in this case 0x78 2) Cast it to uint32_t, getting 0x0078 3) Stores the word in memory - and if it is BE MIPS, 0x78 byte will end-up on addr 0x3. This way, EJTAG is endianess-agnostic - it really do not care about your host endianess, as long as you are are sending it LSB fist. It will arrange then to store the Byte0 at appropriate address once it gathers bits 7:0. This is what I think. Now, when EJTAG is sending back data to the host, it will also send LSB first, i.e. it's Byte0. But in the case of BE, this Byte0 lives on the address 0x3, so it will start with sending addr 0x3. When receives data as a byte array, host can not give any conclusions about target endianess. It just know that it gets LSB first, and we have to use buf_get_u32() to make some meaning on the host of a byte array value that came. This way target endianess is completely unimportant to the OpenOCD, and we can not even know it by observing bytes that come we will always see LSB coming first. Does this all makes sense for you ? BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
Sorry, little mistake: wrong: LE host: result = (uint32_t)buffer[0]; // result = 0x78563412 (memory 0x12 0x34 0x56 0x78) BE host: result = (uint32_t)buffer[0]; // result = 0x12345678 (memory 0x12 0x34 0x56 0x78) corrected: LE host: result = *(uint32_t*)buffer[0];// result = 0x78563412 (memory 0x12 0x34 0x56 0x78) BE host: result = *(uint32_t*)buffer[0];// result = 0x12345678 (memory 0x12 0x34 0x56 0x78) ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Mon, Jul 11, 2011 at 12:45 PM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: On Mon, Jul 11, 2011 at 11:53 AM, Øyvind Harboe oyvind.har...@zylin.com wrote: I think there is a fundamental misunderstanding about JTAG and OpenOCD. Let me try to clarify: JTAG clocks in and out bits, not bytes, so the concept of big/small-endian does not enter the picture at the JTAG level. Sat that we have 0x12345678 at addr 0x0 on LE host. You will shift out byte 0x78 first, shifting out from LSB upwards. You're on the wrong track here. Shifting out happens with *bits*. So the situation is: - you have a host word. 8, 16, 32 or 64 bit wide. - that word must be copied over to an array of bytes to be shifted out. At this point any memory of host representation is gone. - the jtag layer now shifts out the bits, starting with bit 0 in byte 0. - the target receives the bits in order completely oblivious to how you put them on the wire. -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Mon, Jul 11, 2011 at 12:52 PM, Øyvind Harboe oyvind.har...@zylin.com wrote: On Mon, Jul 11, 2011 at 12:45 PM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: On Mon, Jul 11, 2011 at 11:53 AM, Øyvind Harboe oyvind.har...@zylin.com wrote: I think there is a fundamental misunderstanding about JTAG and OpenOCD. Let me try to clarify: JTAG clocks in and out bits, not bytes, so the concept of big/small-endian does not enter the picture at the JTAG level. Sat that we have 0x12345678 at addr 0x0 on LE host. You will shift out byte 0x78 first, shifting out from LSB upwards. You're on the wrong track here. Shifting out happens with *bits*. When I said LSB I meant Least Significant *Bit*, not *Byte*. So the situation is: - you have a host word. 8, 16, 32 or 64 bit wide. - that word must be copied over to an array of bytes to be shifted out. At this point any memory of host representation is gone. - the jtag layer now shifts out the bits, starting with bit 0 in byte 0. What is byte 0 for you ? I'd say, on a BE host it lives at addr 0x3. On LE host it lives at addr 0x0. When you start shifting out LSB (bit) from the BE host, will you start shifting out contents of address 0x3, or the address 0x0 ? In my opinion, it will be content of the addr 0x3 that will be shifted out first (as it holds bits 0:7 for on the BE host). - the target receives the bits in order completely oblivious to how you put them on the wire. Yes - it receives LSB (bit) first. BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Mon, Jul 11, 2011 at 1:10 PM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: On Mon, Jul 11, 2011 at 12:52 PM, Øyvind Harboe oyvind.har...@zylin.com wrote: On Mon, Jul 11, 2011 at 12:45 PM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: On Mon, Jul 11, 2011 at 11:53 AM, Øyvind Harboe oyvind.har...@zylin.com wrote: I think there is a fundamental misunderstanding about JTAG and OpenOCD. Let me try to clarify: JTAG clocks in and out bits, not bytes, so the concept of big/small-endian does not enter the picture at the JTAG level. Sat that we have 0x12345678 at addr 0x0 on LE host. You will shift out byte 0x78 first, shifting out from LSB upwards. You're on the wrong track here. Shifting out happens with *bits*. When I said LSB I meant Least Significant *Bit*, not *Byte*. So the situation is: - you have a host word. 8, 16, 32 or 64 bit wide. - that word must be copied over to an array of bytes to be shifted out. At this point any memory of host representation is gone. - the jtag layer now shifts out the bits, starting with bit 0 in byte 0. What is byte 0 for you ? An array of bytes as an unambiguous representation in memory and C programming model. When I say byte 0 of an array of bytes, there is no question about what that is. OpenOCD shifts out an array of bytes LSB first. -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
Øyvind Harboe wrote: Really OpenOCD could have stored the bits as a series of words larger than bytes in the host representation to be more efficient. This would probably be a source of much more confusion :-) ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Mon, Jul 11, 2011 at 1:30 PM, Øyvind Harboe oyvind.har...@zylin.com wrote: On Mon, Jul 11, 2011 at 1:10 PM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: On Mon, Jul 11, 2011 at 12:52 PM, Øyvind Harboe oyvind.har...@zylin.com wrote: On Mon, Jul 11, 2011 at 12:45 PM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: On Mon, Jul 11, 2011 at 11:53 AM, Øyvind Harboe oyvind.har...@zylin.com wrote: I think there is a fundamental misunderstanding about JTAG and OpenOCD. Let me try to clarify: JTAG clocks in and out bits, not bytes, so the concept of big/small-endian does not enter the picture at the JTAG level. Sat that we have 0x12345678 at addr 0x0 on LE host. You will shift out byte 0x78 first, shifting out from LSB upwards. You're on the wrong track here. Shifting out happens with *bits*. When I said LSB I meant Least Significant *Bit*, not *Byte*. So the situation is: - you have a host word. 8, 16, 32 or 64 bit wide. - that word must be copied over to an array of bytes to be shifted out. At this point any memory of host representation is gone. - the jtag layer now shifts out the bits, starting with bit 0 in byte 0. What is byte 0 for you ? An array of bytes as an unambiguous representation in memory and C programming model. When I say byte 0 of an array of bytes, there is no question about what that is. This is not arguable. What I am asking you here is how do you create this array of bytes you want to shift out ? I'd say - on BE host, when you want to shift out word you put addr 0x3 to be shifted out first, and then in the end addr 0x0, because LSB of your value lives on addr 0x3. Here is how you prepare your shift-out buffer of 8-bit long elements : buffer[0] = (contents_of_the_host_addr 0x3); buffer[1] = (contents_of_the_host_addr 0x2); buffer[2] = (contents_of_the_host_addr 0x1); buffer[3] = (contents_of_the_host_addr 0x0); And then you shift out buffer[0] first, then buffer[1], etc. Which would in the end say - when you want to shift 32-bit word from the BE host, it will be contents addr 0x3 that will be going out on the wire first, this is all I am trying to say. BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
When you start shifting out LSB (bit) from the BE host, will you start shifting out contents of address 0x3, or the address 0x0 ? In my opinion, it will be content of the addr 0x3 that will be shifted out first (as it holds bits 0:7 for on the BE host). Yes, if BE target shifts out an 32 bit value from address 0, it will begin with bit0:7, that is byte address 0x03 at targets memory. ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Mon, Jul 11, 2011 at 1:41 PM, Mahr, Stefan stefan.m...@sphairon.com wrote: When you start shifting out LSB (bit) from the BE host, will you start shifting out contents of address 0x3, or the address 0x0 ? In my opinion, it will be content of the addr 0x3 that will be shifted out first (as it holds bits 0:7 for on the BE host). Yes, if BE target shifts out an 32 bit value from address 0, it will begin with bit0:7, that is byte address 0x03 at targets memory. And host will do the same. When it shifts out 32-bit value , it will put contents of it's address 0x3 to output buffer[0] and send this first. ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Mon, Jul 11, 2011 at 1:43 PM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: Yes, if BE target shifts out an 32 bit value from address 0, it will begin with bit0:7, that is byte address 0x03 at targets memory. And host will do the same. When it shifts out 32-bit value , it will put contents of it's address 0x3 to output buffer[0] and send this first. I am talking about BE host, off course. LE host will put contents of it's 0x0 address to buffer[0] and send this out first. BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
Yes, if BE target shifts out an 32 bit value from address 0, it will begin with bit0:7, that is byte address 0x03 at targets memory. And host will do the same. When it shifts out 32-bit value , it will put contents of it's address 0x3 to output buffer[0] and send this first. I am talking about BE host, off course. LE host will put contents of it's 0x0 address to buffer[0] and send this out first. Yes, that's the way buf_get_u32 and buf_set_u32 works. ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Sat, Jul 9, 2011 at 10:44 AM, Mahr, Stefan stefan.m...@sphairon.com wrote: How do they convert then, when they do not know from which endianes to convert from ? Conversion is done from byte array of jtag chain. How ? buf_get_u32 does conversion from uint8* array example: mips_ejtag_get_impcode (mips_ejtag.c) field.in_value is filled by jtag_add_dr_scan with 4 times uint8. buf_get_u32 converts byte array to host endian uint32 How ? It does not convert anything. It just takes the data and puts it into array, in the order that it comes. No, you do *arithmetical* operations on host, so it is ensured that result is always in host endianness. buf_get_u32: return (((uint32_t)buffer[3]) 24) | (((uint32_t)buffer[2]) 16) | (((uint32_t)buffer[1]) 8) | (((uint32_t)buffer[0]) 0); I do not get this function at all... What I see is that it is presumed that host executing this code must be in the same endianess as the target who filled this buffer. Otherwise bytes get flipped. Here is an experiment : Let's imagine that target is BE. Then it will put word 0x12345678 read from the it's (target's) mem like this : buffer[0] = 0x12 buffer [1] = 0x34 buffer[2] = 0x56 buffer[3] = 0x78 Because BE keeps MSB on lower addr. On the LE host, function buf_get_u32() will shift 0x78 to addr 0x3, 0x56 to addr 0x2, etc and you will get : | 78 | 56 | 34 | 12 | --- value (hex) | 3 | 2 | 1 | 0 | --- addr i.e, you will have 0x78453412 as a return on a LE host, which is, ay you see, flipped value. It is because you kept MSB part put by the target in beuffer[0] on your host's addr 0x0, i.e. you did not shift it you addr 0x3. On LE arch MSB is kept on higher addresses. Similar will happen if you have LE target and BE host. That's why I do not think that this function was ever meant to do any conversion to host's endianess, as you say. What I thing is that it is a function that *must* be used locally on the host, and *only* on the data filled by the host, because then we are guaranteed that the person who fills the buffer[] is the same who reads it, i.e. endianess is same for the reader and for the writer. Do you agree with me on this, or am I missing something ? What is funny however, is that I have BE target and LE host, and MIPS code seems to be working fine... Which would say that EJTAG somehow speaks LE with my host. Crazy thing. The endianness of MIPS EJTAG tap seems to have always the same endianness, no matter of MIPS CPU memory endianness. What makes you think so ? Because openocd works in all combinations of BE and LE host and target. (If you revert commit 2482244b0788c007dd789c21a4416379c229ea5c.) So yes, it's just a guess. Which might mean that all commands are sent to EJTAG in appropriate target format in which CPU expects them (be it BE or LE, depends in which mode it runs). I can't find code that swaps target endianness in mips32_pracc.c or mips_ejtag.c Could this be the explanation: http://downloads.buffalo.nas-central.org/LS2_MIPSel/DevelopmentTools/JTAG/MD00047-2B-EJTAG-SPC-03.10.pdf Page 97: Byte 0 refers to bits 7:0, byte 1 refers to bits 15:8, byte 2 refers to bits 23:16, and byte 3 refers to bits 31:24, independent of endianess. This is _always_ the case in _all_ architectures. But, as you see, this Byte0 is put to lower addresses for LE and to higher for BE. This is always the case. Byte 0 refers to bits 7:0, byte 1 refers to bits 15:8, byte 2 refers to bits 23:16, and byte 3 refers to bits 31:24, independent of endianess. My guess is, if you read out a 32bit value, target endianness doesn't matter. This is the only sane solution I can think of. It would say that EJTAG is a bi-endian machine that can read both BE and LE if we feed it fixed instr. size. Do you know some examples of architectures (bi-endian) like this ? How can it exactly guess the endianess of the program and adopt itself appropriately ? If a 8bit value is read out, you get byte0 for address 0 in LE mode and byte3 at address 0 in BE mode. OK, but this does not change anything for any architecture in the world, as I said - this chapter is just the MIPS terminology, theirs notation, nothing significant there, IMHO. As I said, for value 0x12345678, on BE byte0 is bits 7..0 = 0x78. Reading addr 0x0 you will get MSB on BE, as it stores MSB on lower addr, so you will get 0x12, which is in MIPS (or any other notation) byte3 of the 4-byte value, as it holds MSB, i.e. bits 31..28. As I said, I do not see nothing special there, but it might be that I am missing something you want to point out. BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
buf_get_u32: return (((uint32_t)buffer[3]) 24) | (((uint32_t)buffer[2]) 16) | (((uint32_t)buffer[1]) 8) | (((uint32_t)buffer[0]) 0); I do not get this function at all... What I see is that it is presumed that host executing this code must be in the same endianess as the target who filled this buffer. Otherwise bytes get flipped. I'm jumping into this discussion with something I hope will be useful. The JTAG functions use a sequence of 8 bit words to represent the data that is being clocked in-out. It could have been a sequence of, say, 32 or 64 bit words. Now a sequence of 8 bit words happens to be identical to little endian representation, which is a source of much confusion, I'd say. -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
How do they convert then, when they do not know from which endianes to convert from ? Conversion is done from byte array of jtag chain. How ? buf_get_u32 does conversion from uint8* array example: mips_ejtag_get_impcode (mips_ejtag.c) field.in_value is filled by jtag_add_dr_scan with 4 times uint8. buf_get_u32 converts byte array to host endian uint32 How ? It does not convert anything. It just takes the data and puts it into array, in the order that it comes. No, you do *arithmetical* operations on host, so it is ensured that result is always in host endianness. buf_get_u32: return (((uint32_t)buffer[3]) 24) | (((uint32_t)buffer[2]) 16) | (((uint32_t)buffer[1]) 8) | (((uint32_t)buffer[0]) 0); The endianness of MIPS EJTAG tap seems to have always the same endianness, no matter of MIPS CPU memory endianness. What makes you think so ? Because openocd works in all combinations of BE and LE host and target. (If you revert commit 2482244b0788c007dd789c21a4416379c229ea5c.) So yes, it's just a guess. Which might mean that all commands are sent to EJTAG in appropriate target format in which CPU expects them (be it BE or LE, depends in which mode it runs). I can't find code that swaps target endianness in mips32_pracc.c or mips_ejtag.c Could this be the explanation: http://downloads.buffalo.nas-central.org/LS2_MIPSel/DevelopmentTools/JTAG/MD00047-2B-EJTAG-SPC-03.10.pdf Page 97: Byte 0 refers to bits 7:0, byte 1 refers to bits 15:8, byte 2 refers to bits 23:16, and byte 3 refers to bits 31:24, independent of endianess. This is _always_ the case in _all_ architectures. But, as you see, this Byte0 is put to lower addresses for LE and to higher for BE. This is always the case. Byte 0 refers to bits 7:0, byte 1 refers to bits 15:8, byte 2 refers to bits 23:16, and byte 3 refers to bits 31:24, independent of endianess. My guess is, if you read out a 32bit value, target endianness doesn't matter. If a 8bit value is read out, you get byte0 for address 0 in LE mode and byte3 at address 0 in BE mode. BR, Stefan ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 11:43 AM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: On Thu, Jul 7, 2011 at 11:58 AM, Øyvind Harboe oyvind.har...@zylin.com wrote: Note that this problem has cropped up many places over the OpenOCD code. I'd like to get rid of it once and for all I absolutely intend to fix it for MIPS, but I'd like a good long term solution. With jtag queue callbacks, a user data pointer to the callback is cast to a void pointer, then cast back to e.g. uint32_t *. Casting to/from void * does not yield a warning(should not anyway, right?), Why shouldn't it ? I mean, you can have unaligned acces by casting void* to unaligned addr to uint32* and then reference, right ? Such warnings would be hopelessly noisy. A callback generally takes a pointer to *something* and then inside the callback you cast back the pointer to whatever you *know* you passed in. Of course C++ the whole casting business is much more advanced than i C. From my point of view casting uint8_t* to uint32* is dangerous as casting void* to uint32_t*. Isee no difference, as void* can point to unaligned addr. There is no difference in danger, but what the compiler is telling you is that if you do need to have a generic pointer, then use void *, not uint8_t *. -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 11:47 AM, Øyvind Harboe oyvind.har...@zylin.com wrote: On Fri, Jul 8, 2011 at 11:43 AM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: On Thu, Jul 7, 2011 at 11:58 AM, Øyvind Harboe oyvind.har...@zylin.com wrote: Note that this problem has cropped up many places over the OpenOCD code. I'd like to get rid of it once and for all I absolutely intend to fix it for MIPS, but I'd like a good long term solution. With jtag queue callbacks, a user data pointer to the callback is cast to a void pointer, then cast back to e.g. uint32_t *. Casting to/from void * does not yield a warning(should not anyway, right?), Why shouldn't it ? I mean, you can have unaligned acces by casting void* to unaligned addr to uint32* and then reference, right ? Such warnings would be hopelessly noisy. A callback generally takes a pointer to *something* and then inside the callback you cast back the pointer to whatever you *know* you passed in. Of course C++ the whole casting business is much more advanced than i C. From my point of view casting uint8_t* to uint32* is dangerous as casting void* to uint32_t*. Isee no difference, as void* can point to unaligned addr. There is no difference in danger, but what the compiler is telling you is that if you do need to have a generic pointer, then use void *, not uint8_t *. OK, I am starting to get this... Thanks Øyvind. But looking from to the code, I see no explicit casting uint8_t* to uint32_t in mips_pracc code. Where did you exactly run into compiler warning ? BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Thu, Jul 7, 2011 at 11:52 AM, Øyvind Harboe oyvind.har...@zylin.com wrote: 011/7/7 Mahr, Stefan stefan.m...@sphairon.com: Øyvind Harboe wrote: It is not obvious at all from the context that there is an alignment guarantee. If alignment is not guaranteed, casting from uint32 to void would cause problems too, wouldn't it? Why? http://openocd.git.sourceforge.net/git/gitweb.cgi?p=openocd/openocd;a=blob;f=src/target/mips32_pracc.c;h=af60d321638652aad0a52a573add2aceacbfb7d9;hb=HEAD#l310 = this is strange, why cast to uint8_t ? return mips32_pracc_read_mem16(ejtag_info, addr, count, (uint8_t*)buf); There is no particular need to cast this into uint8_t* and this can be kept as a void*. Would that suppress the warnings ? BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
There is no particular need to cast this into uint8_t* and this can be kept as a void*. Would that suppress the warnings ? It does look like this code is using uint8_t * in lieu of void *... I think it would suppress the warnings, yes. -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 12:31 PM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: On Fri, Jul 8, 2011 at 12:14 PM, Øyvind Harboe oyvind.har...@zylin.com wrote: There is no particular need to cast this into uint8_t* and this can be kept as a void*. Would that suppress the warnings ? It does look like this code is using uint8_t * in lieu of void *... Why ? It is just an address of 1-byte placeholder to which you would like to copy byte read from the memory. It's not about what you do, it is about telling the compiler as much as possible about the types so that it can check for problems. I don't know the code too well to comment about which types should be used. Especially with big/small endian... -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 12:14 PM, Øyvind Harboe oyvind.har...@zylin.com wrote: There is no particular need to cast this into uint8_t* and this can be kept as a void*. Would that suppress the warnings ? It does look like this code is using uint8_t * in lieu of void *... Why ? It is just an address of 1-byte placeholder to which you would like to copy byte read from the memory. All you have to do late is to copy values read into each memeber of uint32_t array to each corresponding member of uint8_t array. This loop : for (i = 0; i count; i++) { buf[i] = param_out[i]; } I see no problem of alignment there, as actually uint32_t will be casted to uint8_t, which should be OK (while the other way around is dangerous). But even that can be avoided, as retval = mips32_pracc_exec(ejtag_info, ARRAY_SIZE(code), code, ARRAY_SIZE(param_in), param_in, count, param_out, 1); will get you values in param_out[] array. This array is an array of uint32_t values, I do not know for which reason... Actually, copy from RAM address to our buffer is done in this loop : /* loop */ MIPS32_BEQ(0,10,8), /* beq 0, $10, end */ MIPS32_NOP, MIPS32_LBU(8,0,9), /* lw $8,0($9), Load t4 with the byte @mem[t1] */ MIPS32_SW(8,0,11), /* sw $8,0($11) */ MIPS32_ADDI(10,10,NEG16(1)), /* $10-- */ MIPS32_ADDI(9,9,1), /* $9 += 1 */ MIPS32_ADDI(11,11,4), /* $11 += 4 */ MIPS32_B(NEG16(8)), /* b loop */ /* end */ Where $11 holds the adress of our buffer member (dst addr). Because we said that our destination buffer is consisted of uint32_t, this address is incremented by 4 in every pass: MIPS32_ADDI(11,11,4), /* $11 += 4 */ I think that using uint8_t array and using $11 += 1 in the loop should do the same thing... ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 12:10 PM, Øyvind Harboe oyvind.har...@zylin.com wrote: OK, I am starting to get this... Thanks Øyvind. But looking from to the code, I see no explicit casting uint8_t* to uint32_t in mips_pracc code. Where did you exactly run into compiler warning ? git revert 2482244b0788c007dd789c2 I reverted this commit : commit e442054bf9acf70cb2b9b2ac297cba2b15df5642 Author: Drasko DRASKOVIC drasko.drasko...@gmail.com Date: Fri Jul 8 12:32:42 2011 +0200 Revert mips4k: fix big-endian hosts and host alignment problems This reverts commit 2482244b0788c007dd789c21a4416379c229ea5c. I still can not reproduce a problem - it buidls just fine. No warnings whatsoever. gcc version 4.3.2 (Debian 4.3.2-1.1) BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 12:35 PM, Øyvind Harboe oyvind.har...@zylin.com wrote: On Fri, Jul 8, 2011 at 12:31 PM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: On Fri, Jul 8, 2011 at 12:14 PM, Øyvind Harboe oyvind.har...@zylin.com wrote: There is no particular need to cast this into uint8_t* and this can be kept as a void*. Would that suppress the warnings ? It does look like this code is using uint8_t * in lieu of void *... Why ? It is just an address of 1-byte placeholder to which you would like to copy byte read from the memory. It's not about what you do, it is about telling the compiler as much as possible about the types so that it can check for problems. I don't know the code too well to comment about which types should be used. Especially with big/small endian... I know this code, and I can change it. I just do not see any casting to unaligned access by visual inspection, and I can not reproduce the problem. So I do not know where to start changing - everything looks OK to me here. BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
I still can not reproduce a problem - it buidls just fine. No warnings whatsoever. libtool: compile: nios2-linux-gnu-gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I/home/oyvind/workspace/zy1000/build/../openocd/src/target -I../.. -I/home/oyvind/workspace/zy1000/build/../openocd/src -I../../src -DPKGDATADIR=\/opt/zy1000/share/openocd\ -DPKGLIBDIR=\/opt/zy1000/lib/openocd\ -O3 -g -I/home/oyvind/nios2-linux/uClinux-dist/staging/usr/include -I/opt/zy1000/include -Wall -Wstrict-prototypes -Wformat-security -Wshadow -Wextra -Wno-unused-parameter -Wbad-function-cast -Wcast-align -Wredundant-decls -Werror -MT mips_m4k.lo -MD -MP -MF .deps/mips_m4k.Tpo -c /home/oyvind/workspace/zy1000/build/../openocd/src/target/mips_m4k.c -o mips_m4k.o cc1: warnings being treated as errors /home/oyvind/workspace/zy1000/build/../openocd/src/target/mips_m4k.c: In function 'mips_m4k_read_memory': /home/oyvind/workspace/zy1000/build/../openocd/src/target/mips_m4k.c:880: warning: cast increases required alignment of target type /home/oyvind/workspace/zy1000/build/../openocd/src/target/mips_m4k.c:884: warning: cast increases required alignment of target type /home/oyvind/workspace/zy1000/build/../openocd/src/target/mips_m4k.c: In function 'mips_m4k_write_memory': /home/oyvind/workspace/zy1000/build/../openocd/src/target/mips_m4k.c:933: warning: cast increases required alignment of target type /home/oyvind/workspace/zy1000/build/../openocd/src/target/mips_m4k.c:937: warning: cast increases required alignment of target type /home/oyvind/workspace/zy1000/build/../openocd/src/target/mips_m4k.c: In function 'mips_m4k_bulk_write_memory': /home/oyvind/workspace/zy1000/build/../openocd/src/target/mips_m4k.c:1077: warning: cast increases required alignment of target type -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
What puzzles me is that there is no warning on x86, even if I the -Wcast-align option is there -Wcast-align Warn whenever a pointer is cast such that the required alignment of the target is increased. For example, warn if a char * is cast to an int * on machines where integers can only be accessed at two- or four-byte boundaries. -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 12:42 PM, Øyvind Harboe oyvind.har...@zylin.com wrote: I still can not reproduce a problem - it buidls just fine. No warnings whatsoever. libtool: compile: nios2-linux-gnu-gcc -std=gnu99 -DHAVE_CONFIG_H -I. -I/home/oyvind/workspace/zy1000/build/../openocd/src/target -I../.. -I/home/oyvind/workspace/zy1000/build/../openocd/src -I../../src -DPKGDATADIR=\/opt/zy1000/share/openocd\ -DPKGLIBDIR=\/opt/zy1000/lib/openocd\ -O3 -g -I/home/oyvind/nios2-linux/uClinux-dist/staging/usr/include -I/opt/zy1000/include -Wall -Wstrict-prototypes -Wformat-security -Wshadow -Wextra -Wno-unused-parameter -Wbad-function-cast -Wcast-align -Wredundant-decls -Werror -MT mips_m4k.lo -MD -MP -MF .deps/mips_m4k.Tpo -c /home/oyvind/workspace/zy1000/build/../openocd/src/target/mips_m4k.c -o mips_m4k.o cc1: warnings being treated as errors /home/oyvind/workspace/zy1000/build/../openocd/src/target/mips_m4k.c: In function 'mips_m4k_read_memory': /home/oyvind/workspace/zy1000/build/../openocd/src/target/mips_m4k.c:880: warning: cast increases required alignment of target type /home/oyvind/workspace/zy1000/build/../openocd/src/target/mips_m4k.c:884: warning: cast increases required alignment of target type /home/oyvind/workspace/zy1000/build/../openocd/src/target/mips_m4k.c: In function 'mips_m4k_write_memory': /home/oyvind/workspace/zy1000/build/../openocd/src/target/mips_m4k.c:933: warning: cast increases required alignment of target type /home/oyvind/workspace/zy1000/build/../openocd/src/target/mips_m4k.c:937: warning: cast increases required alignment of target type /home/oyvind/workspace/zy1000/build/../openocd/src/target/mips_m4k.c: In function 'mips_m4k_bulk_write_memory': /home/oyvind/workspace/zy1000/build/../openocd/src/target/mips_m4k.c:1077: warning: cast increases required alignment of target type OK, I was looking at mips32_pracc.c, but actually it is this in mips_m4k.c : for(i = 0; i (count*size); i += size) { switch(size) { case 4: t32 = *(uint32_t*)buffer[i]; target_buffer_set_u32(target,buffer[i], t32); break; case 2: t16 = *(uint16_t*)buffer[i]; target_buffer_set_u16(target,buffer[i], t16); break; } } that casts void* buf to uint32_t*. BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 12:52 PM, Øyvind Harboe oyvind.har...@zylin.com wrote: What puzzles me is that there is no warning on x86, even if I the -Wcast-align option is there This kind of explains why I never saw it... BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Wed, Jul 6, 2011 at 2:42 PM, Mahr, Stefan stefan.m...@sphairon.com wrote: mips32_pracc_read_mem and mips32_pracc_write_mem return values (buffer[i]) are already in host endianness, so le_to_h_u32 fails on big endian hosts. I already mentioned this in previous discussions. Hi Stefan, are you sure about this ? It seems to me that buffer[i] is directly filled by target, and I see no reason that it is in the host endianess... BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
that casts void* buf to uint32_t*. Actually buffer is uint8_t *. The definition of target-type-read_memory is bad in that it uses uint8_t * instead of void *. Which is kinda the root of this mess. -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 1:13 PM, Øyvind Harboe oyvind.har...@zylin.com wrote: that casts void* buf to uint32_t*. Actually buffer is uint8_t *. The definition of target-type-read_memory is bad in that it uses uint8_t * instead of void *. Which is kinda the root of this mess. Well, this propagate through all the targets... BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
I am just wandering, would : t32 = *(uint32_t*)((void *)buffer[i]); quite the compiler ;) BR, Drasko On Fri, Jul 8, 2011 at 1:14 PM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: On Fri, Jul 8, 2011 at 1:13 PM, Øyvind Harboe oyvind.har...@zylin.com wrote: that casts void* buf to uint32_t*. Actually buffer is uint8_t *. The definition of target-type-read_memory is bad in that it uses uint8_t * instead of void *. Which is kinda the root of this mess. Well, this propagate through all the targets... BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 12:52 PM, Øyvind Harboe oyvind.har...@zylin.comwrote: What puzzles me is that there is no warning on x86, even if I the -Wcast-align option is there -Wcast-align Warn whenever a pointer is cast such that the required alignment of the target is increased. For example, warn if a char * is cast to an int * on machines where integers can only be accessed at two- or four-byte boundaries. on machines where integers can only be accessed at two- or four-byte boundaries x86 is not such a machine, it supports unaligned access. Which is why it's good to do a cross-compile to another arch regularly to catch these problems. It would be good if there was an option to emit these warnings regardless. Maybe there is. I looked briefly at the memory read functions in mips32_dmaacc.c and mips32_pracc.c and it looks like the type usage is a bit confused. The difference between the *_read_mem{32,16,8} functions should only be what kind of access is made *on the target*. Host data buffer type should be identical, preferrably void*, with no alignment requirement, and count should be in number of bytes. /Andreas ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 1:17 PM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: I am just wandering, would : t32 = *(uint32_t*)((void *)buffer[i]); quite the compiler ;) Yes probably, but it would still crash on an architecture that doesn't support unaligned accesses. /Andreas ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 1:20 PM, Andreas Fritiofson andreas.fritiof...@gmail.com wrote: On Fri, Jul 8, 2011 at 1:17 PM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: I am just wandering, would : t32 = *(uint32_t*)((void *)buffer[i]); quite the compiler ;) Yes probably, but it would still crash on an architecture that doesn't support unaligned accesses. Yes, if there is a reason for crash. I am not sure that it is the case here... I am trying to investigate... BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 1:19 PM, Andreas Fritiofson andreas.fritiof...@gmail.com wrote: I looked briefly at the memory read functions in mips32_dmaacc.c and mips32_pracc.c and it looks like the type usage is a bit confused. The difference between the *_read_mem{32,16,8} functions should only be what kind of access is made *on the target*. How do we determine that ? I thought that it is kept in the size parameter, and mips32_pracc_read_mem is doing exactly this : int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf) { switch (size) { case 1: return mips32_pracc_read_mem8(ejtag_info, addr, count, (uint8_t*)buf); case 2: return mips32_pracc_read_mem16(ejtag_info, addr, count, (uint16_t*)buf); case 4: if (count == 1) return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t*)buf); else return mips32_pracc_read_mem32(ejtag_info, addr, count, (uint32_t*)buf); } return ERROR_OK; } Host data buffer type should be identical, preferrably void*, with no alignment requirement, and count should be in number of bytes. Problem is not in the mips32_pracc.c, thought, but when you come back to mips_m4k_read_memory(), in which buf is uint8_t*. BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
are you sure about this ? It seems to me that buffer[i] is directly filled by target, and I see no reason that it is in the host endianess... Hi Drasko, Yes I'm sure. I tested it on my big endian host platform. I do not understand the code completely, but I think it's caused by the mips ejtag functions. Example: - mips_ejtag_drscan_32 uses uint32 for data - buf_set_u32 and buf_get_u32 make sure that data is in host endianness ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 1:38 PM, Mahr, Stefan stefan.m...@sphairon.comwrote: are you sure about this ? It seems to me that buffer[i] is directly filled by target, and I see no reason that it is in the host endianess... Hi Drasko, Yes I'm sure. I tested it on my big endian host platform. I do not understand the code completely, but I think it's caused by the mips ejtag functions. Example: - mips_ejtag_drscan_32 uses uint32 for data - buf_set_u32 and buf_get_u32 make sure that data is in host endianness Where are those functions defined and how do they know what the target endianness is? It sounds a little strange to do the swapping at this low level. /Andreas ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
Problem is not in the mips32_pracc.c, thought, but when you come back to mips_m4k_read_memory(), in which buf is uint8_t*. That's why the solution could be to add swapping to _mem16, _mem32 etc. and alway return uint8*. ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
Where are those functions defined and how do they know what the target endianness is? They doesn't know the target endianness, but host endianness. It sounds a little strange to do the swapping at this low level. You need swapping when reading and comparing debug registers or send code to MIPS CPU. ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 2:05 PM, Mahr, Stefan stefan.m...@sphairon.comwrote: Where are those functions defined and how do they know what the target endianness is? They doesn't know the target endianness, but host endianness. It sounds a little strange to do the swapping at this low level. You need swapping when reading and comparing debug registers or send code to MIPS CPU. But there are other times when swapping is not the right thing to do, such as reading/writing arbitrary memory blocks, right? So I'd say the swapping belongs to the higher levels that know if the data is to be interpreted or not. Otherwise we'll just be swapping back and forth needlessly. /Andreas ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 2:05 PM, Mahr, Stefan stefan.m...@sphairon.comwrote: Where are those functions defined and how do they know what the target endianness is? They doesn't know the target endianness, but host endianness. You can't convert between target and host endianness if you don't know both. I'm getting confused about all this endianness. Main thing we need to do is to define and be consistent with where we have target and host endianess and look over the data types we use. This is probably not restricted to the MIPS code but probably goes up into the target interface. I have to think it through and right now I have a bunch of kids running around my legs so it'll have to wait. :) /Andreas ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 1:26 PM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: On Fri, Jul 8, 2011 at 1:19 PM, Andreas Fritiofson andreas.fritiof...@gmail.com wrote: I looked briefly at the memory read functions in mips32_dmaacc.c and mips32_pracc.c and it looks like the type usage is a bit confused. The difference between the *_read_mem{32,16,8} functions should only be what kind of access is made *on the target*. How do we determine that ? I thought that it is kept in the size parameter, and mips32_pracc_read_mem is doing exactly this : int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf) { switch (size) { case 1: return mips32_pracc_read_mem8(ejtag_info, addr, count, (uint8_t*)buf); case 2: return mips32_pracc_read_mem16(ejtag_info, addr, count, (uint16_t*)buf); case 4: if (count == 1) return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t*)buf); else return mips32_pracc_read_mem32(ejtag_info, addr, count, (uint32_t*)buf); } return ERROR_OK; } Host data buffer type should be identical, preferrably void*, with no alignment requirement, and count should be in number of bytes. Problem is not in the mips32_pracc.c, thought, but when you come back to mips_m4k_read_memory(), in which buf is uint8_t*. But already here buf is cast to uint{8,16,32}_t* (from void* so no warning but equally risky) which shouldn't be needed because all read_mem* functions could accept a void* buffer and write the data to arbitrary alignment. Main point is that the alignment requirement (buffer data type) on the host should not be coupled to the access size used on the target. And also the data returned in the host buffer should be identical, regardless of which target access size is chosen (this requirement probably gives the answer to whether endian swapping should be done here or not). Does this make sense? Of course you may not be able to do an access with size 2 or 4 to an unaligned *target address* but that has nothing to do with host buffer alignment. If the memory functions only handle byte addressed generic memory blocks, there are no endian issues (here). They pop up first when higher level code tries to interpret the memory contents as multi-byte entities (instructions, addresses, ...) in which case that code must be aware of the target endianness. Again, I may be confused here. /Andreas ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 1:38 PM, Mahr, Stefan stefan.m...@sphairon.com wrote: are you sure about this ? It seems to me that buffer[i] is directly filled by target, and I see no reason that it is in the host endianess... Hi Drasko, Yes I'm sure. I tested it on my big endian host platform. I do not understand the code completely, but I think it's caused by the mips ejtag functions. Example: - mips_ejtag_drscan_32 uses uint32 for data Ok, I see no problem there... - buf_set_u32 and buf_get_u32 make sure that data is in host endianness Why ? Don't we want the data to be in target endianess ? BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 1:54 PM, Mahr, Stefan stefan.m...@sphairon.com wrote: Problem is not in the mips32_pracc.c, thought, but when you come back to mips_m4k_read_memory(), in which buf is uint8_t*. That's why the solution could be to add swapping to _mem16, _mem32 etc. and alway return uint8*. I agree with you, but we should look for the best solution. We can always fall back to this brute force if we do not find anything better. BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 2:05 PM, Mahr, Stefan stefan.m...@sphairon.com wrote: Where are those functions defined and how do they know what the target endianness is? They doesn't know the target endianness, but host endianness. It sounds a little strange to do the swapping at this low level. You need swapping when reading and comparing debug registers or send code to MIPS CPU. Can you give the example of some of these comparisons in the source code ? You are referring to some comparisons in mips32_pracc.c ? BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 3:08 PM, Andreas Fritiofson andreas.fritiof...@gmail.com wrote: On Fri, Jul 8, 2011 at 1:26 PM, Drasko DRASKOVIC drasko.drasko...@gmail.com wrote: On Fri, Jul 8, 2011 at 1:19 PM, Andreas Fritiofson andreas.fritiof...@gmail.com wrote: I looked briefly at the memory read functions in mips32_dmaacc.c and mips32_pracc.c and it looks like the type usage is a bit confused. The difference between the *_read_mem{32,16,8} functions should only be what kind of access is made *on the target*. How do we determine that ? I thought that it is kept in the size parameter, and mips32_pracc_read_mem is doing exactly this : int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf) { switch (size) { case 1: return mips32_pracc_read_mem8(ejtag_info, addr, count, (uint8_t*)buf); case 2: return mips32_pracc_read_mem16(ejtag_info, addr, count, (uint16_t*)buf); case 4: if (count == 1) return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t*)buf); else return mips32_pracc_read_mem32(ejtag_info, addr, count, (uint32_t*)buf); } return ERROR_OK; } Host data buffer type should be identical, preferrably void*, with no alignment requirement, and count should be in number of bytes. Problem is not in the mips32_pracc.c, thought, but when you come back to mips_m4k_read_memory(), in which buf is uint8_t*. But already here buf is cast to uint{8,16,32}_t* (from void* so no warning but equally risky) which shouldn't be needed because all read_mem* functions could accept a void* buffer and write the data to arbitrary alignment. Main point is that the alignment requirement (buffer data type) on the host should not be coupled to the access size used on the target. I do not know all the OpenOCD internals, but I guess that size represent data access size you are mentioning. like, if count is 5 and size is 4 that would mean I want 5 ints. If my presumption is true, then I agree with you, and looking at the PrAcc code that we can safely use void for these buffer pointers. They are just addresses where read data will be put. However, data will be read (accessed) in the size - if it is 4 we will use MIPS32_LW which loads word from memory, and if it is 2, we will use MIPS32_LHU - load halfword unsigned. So, from this point everything seems to be OK, except from this unnecessary casting void* to uintX_t*. Problem is however in mips_m4k_read_memory(), where you have explicit casting t32 = *(uint32_t*)buffer[i]; And also the data returned in the host buffer should be identical, regardless of which target access size is chosen (this requirement probably gives the answer to whether endian swapping should be done here or not). Does this make sense? Yes, and it is (IMHO). Of course you may not be able to do an access with size 2 or 4 to an unaligned *target address* but that has nothing to do with host buffer alignment. If the memory functions only handle byte addressed generic memory blocks, there are no endian issues (here). They pop up first when higher level code tries to interpret the memory contents as multi-byte entities (instructions, addresses, ...) in which case that code must be aware of the target endianness. Again, I may be confused here. I've got lost here... BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
- buf_set_u32 and buf_get_u32 make sure that data is in host endianness Why ? Don't we want the data to be in target endianess ? You need swapping when reading and comparing debug registers or send code to MIPS CPU. Can you give the example of some of these comparisons in the source code ? You are referring to some comparisons in mips32_pracc.c ? example: mips_m4k.c: mips_m4k_poll mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); retval = mips_ejtag_drscan_32(ejtag_info, ejtag_ctrl); ... if (ejtag_ctrl EJTAG_CTRL_ROCC) {... ejtag_ctrl is host endian uint32. If mips_ejtag_drscan_32 would be in target endianness you need to swap here or write and use a new function that does swapping. ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 4:10 PM, Mahr, Stefan stefan.m...@sphairon.com wrote: - buf_set_u32 and buf_get_u32 make sure that data is in host endianness Why ? Don't we want the data to be in target endianess ? You need swapping when reading and comparing debug registers or send code to MIPS CPU. Can you give the example of some of these comparisons in the source code ? You are referring to some comparisons in mips32_pracc.c ? example: mips_m4k.c: mips_m4k_poll mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); retval = mips_ejtag_drscan_32(ejtag_info, ejtag_ctrl); ... if (ejtag_ctrl EJTAG_CTRL_ROCC) {... ejtag_ctrl is host endian uint32. If mips_ejtag_drscan_32 would be in target endianness you need to swap here or write and use a new function that does swapping. I agreee. Code like this is present on even lower level, im mips32_pracc.c, like while (1) { retval = mips_ejtag_drscan_32(ejtag_info, ejtag_ctrl); if (retval != ERROR_OK) return retval; if (ejtag_ctrl EJTAG_CTRL_PRACC) break; if ( (timeout = timeval_ms()-then) 1000 ) { LOG_DEBUG(DEBUGMODULE: No memory access in progress!); return ERROR_JTAG_DEVICE_ERROR; } } It has to be that way - so code must be in the host endianess right after drscan. Is this swap to host endianess done by buf_get_u32() in mips_ejtag_drscan_32() after the queue has been executed ? BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
Is this swap to host endianess done by buf_get_u32() in mips_ejtag_drscan_32() after the queue has been executed ? Yes, buf_get_u32() and buf_set_u32() make sure uint32 is in host endianness. ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 2:05 PM, Mahr, Stefan stefan.m...@sphairon.com wrote: Where are those functions defined and how do they know what the target endianness is? They doesn't know the target endianness, but host endianness. How do they convert then, when they do not know from which endianes to convert from ? /** * Sets @c num bits in @c _buffer, starting at the @c first bit, * using the bits in @c value. This routine fast-paths writes * of little-endian, byte-aligned, 32-bit words. * @param _buffer The buffer whose bits will be set. * @param first The bit offset in @c _buffer to start writing (0-31). * @param num The number of bits from @c value to copy (1-32). * @param value Up to 32 bits that will be copied to _buffer. */ static inline void buf_set_u32(void *_buffer, unsigned first, unsigned num, uint32_t value) BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 4:23 PM, Mahr, Stefan stefan.m...@sphairon.com wrote: Is this swap to host endianess done by buf_get_u32() in mips_ejtag_drscan_32() after the queue has been executed ? Yes, buf_get_u32() and buf_set_u32() make sure uint32 is in host endianness. OK, we are slowely nailing it... Just let me see how the hell these functions do the conversion target/host endianess Do you have any idea ? BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
How do they convert then, when they do not know from which endianes to convert from ? Conversion is done from byte array of jtag chain. The endianness of MIPS EJTAG tap seems to have always the same endianness, no matter of MIPS CPU memory endianness. ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 4:30 PM, Mahr, Stefan stefan.m...@sphairon.com wrote: How do they convert then, when they do not know from which endianes to convert from ? Conversion is done from byte array of jtag chain. How ? The endianness of MIPS EJTAG tap seems to have always the same endianness, no matter of MIPS CPU memory endianness. What makes you think so ? EJTAG specification, Document Number: MD00047 describes bit in Debug Control Register ENM (bit 29 of DCR) Endianess in which the processor is running in kernel and Debug Mode. If your CPU runs in the BE, you'll have to feed it with BE code. BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
How do they convert then, when they do not know from which endianes to convert from ? Conversion is done from byte array of jtag chain. How ? buf_get_u32 does conversion from uint8* array example: mips_ejtag_get_impcode (mips_ejtag.c) field.in_value is filled by jtag_add_dr_scan with 4 times uint8. buf_get_u32 converts byte array to host endian uint32 The endianness of MIPS EJTAG tap seems to have always the same endianness, no matter of MIPS CPU memory endianness. What makes you think so ? Because openocd works in all combinations of BE and LE host and target. (If you revert commit 2482244b0788c007dd789c21a4416379c229ea5c.) So yes, it's just a guess. Could this be the explanation: http://downloads.buffalo.nas-central.org/LS2_MIPSel/DevelopmentTools/JTAG/MD00047-2B-EJTAG-SPC-03.10.pdf Page 97: Byte 0 refers to bits 7:0, byte 1 refers to bits 15:8, byte 2 refers to bits 23:16, and byte 3 refers to bits 31:24, independent of endianess. Please also see Chapter 6.3.3, 6.3.6, 6.4.1, etc. TAPs are alway LSB first, so endianness doesn't matter here. ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Fri, Jul 8, 2011 at 6:30 PM, Mahr, Stefan stefan.m...@sphairon.com wrote: How do they convert then, when they do not know from which endianes to convert from ? Conversion is done from byte array of jtag chain. How ? buf_get_u32 does conversion from uint8* array example: mips_ejtag_get_impcode (mips_ejtag.c) field.in_value is filled by jtag_add_dr_scan with 4 times uint8. buf_get_u32 converts byte array to host endian uint32 How ? It does not convert anything. It just takes the data and puts it into array, in the order that it comes. The endianness of MIPS EJTAG tap seems to have always the same endianness, no matter of MIPS CPU memory endianness. What makes you think so ? Because openocd works in all combinations of BE and LE host and target. (If you revert commit 2482244b0788c007dd789c21a4416379c229ea5c.) So yes, it's just a guess. Which might mean that all commands are sent to EJTAG in appropriate target format in which CPU expects them (be it BE or LE, depends in which mode it runs). Could this be the explanation: http://downloads.buffalo.nas-central.org/LS2_MIPSel/DevelopmentTools/JTAG/MD00047-2B-EJTAG-SPC-03.10.pdf Page 97: Byte 0 refers to bits 7:0, byte 1 refers to bits 15:8, byte 2 refers to bits 23:16, and byte 3 refers to bits 31:24, independent of endianess. This is _always_ the case in _all_ architectures. But, as you see, this Byte0 is put to lower addresses for LE and to higher for BE. This is always the case. Please also see Chapter 6.3.3, 6.3.6, 6.4.1, etc. TAPs are alway LSB first, so endianness doesn't matter here. This is always the case, for all JTAG TAPS. No, there must be something else... BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
Øyvind Harboe wrote: It is not obvious at all from the context that there is an alignment guarantee. If alignment is not guaranteed, casting from uint32 to void would cause problems too, wouldn't it? http://openocd.git.sourceforge.net/git/gitweb.cgi?p=openocd/openocd;a=blob;f=src/target/mips32_pracc.c;h=af60d321638652aad0a52a573add2aceacbfb7d9;hb=HEAD#l310 The version below yields decent code across architectures after Stefan showed that the mileage varies greatly with intrinsic memcpy(). The resulting code is even worse. Andreas Fritiofson wrote: The question is who makes the guarantee that the function is only ever called with uint32-aligned generic pointers. If it just happens to be so that all *current* callers pass a uint32 pointer cast to void pointer, it would be a terribly bad idea to suddenly assume that. If it is guaranteed by design/contract, why is a void pointer used at all? Just use a pointer to uint32 then. Please see mips32_pracc_read_mem (link above). This function returns void pointer because it is used for uint8, uint16 or uint32, depending on size parameter. If reading uint32 or uint16 from target memory, this function returns value in host endianness. While this is useful for normal EJTAG handling, it's bad for dumping target memory. For dumping we need target endianness. BR, Stefan ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
011/7/7 Mahr, Stefan stefan.m...@sphairon.com: Øyvind Harboe wrote: It is not obvious at all from the context that there is an alignment guarantee. If alignment is not guaranteed, casting from uint32 to void would cause problems too, wouldn't it? Why? http://openocd.git.sourceforge.net/git/gitweb.cgi?p=openocd/openocd;a=blob;f=src/target/mips32_pracc.c;h=af60d321638652aad0a52a573add2aceacbfb7d9;hb=HEAD#l310 = this is strange, why cast to uint8_t ? return mips32_pracc_read_mem16(ejtag_info, addr, count, (uint8_t*)buf); -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
Note that this problem has cropped up many places over the OpenOCD code. I'd like to get rid of it once and for all I absolutely intend to fix it for MIPS, but I'd like a good long term solution. With jtag queue callbacks, a user data pointer to the callback is cast to a void pointer, then cast back to e.g. uint32_t *. Casting to/from void * does not yield a warning(should not anyway, right?), but casting from uint8_t * to uint32_t * is dubious because the code does not clearly state it's assumptions. -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
If alignment is not guaranteed, casting from uint32 to void would cause problems too, wouldn't it? Why? Sorry for confusion. I meant the casting within mips32_pracc_read_mem. This is also a cast from void* to uint32_t*. If there will be an alignment error, it will occur here too. ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
If alignment is not guaranteed, casting from uint32 to void would cause problems too, wouldn't it? Why? Sorry for confusion. I meant the casting within mips32_pracc_read_mem. This is also a cast from void* to uint32_t*. If there will be an alignment error, it will occur here too. That's correct. There is no way to know from the code context, is there? No documentation either. Probably the best way would be to remove endianness swapping from mips_m4k_read_memory and put it to mips32_pracc/dma_read_mem32/16. Same for write. pro: mips32_pracc_read_mem32, ... will return a byte array in target endianness, so no cast necessary. con: Add swapping to at least 10 seperate functions BR, Stefan ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Thu, Jul 7, 2011 at 10:41 PM, Mahr, Stefan stefan.m...@sphairon.com wrote: If alignment is not guaranteed, casting from uint32 to void would cause problems too, wouldn't it? Why? Sorry for confusion. I meant the casting within mips32_pracc_read_mem. This is also a cast from void* to uint32_t*. If there will be an alignment error, it will occur here too. That's correct. There is no way to know from the code context, is there? No documentation either. Probably the best way would be to remove endianness swapping from mips_m4k_read_memory and put it to mips32_pracc/dma_read_mem32/16. Same for write. pro: mips32_pracc_read_mem32, ... will return a byte array in target endianness, so no cast necessary. con: Add swapping to at least 10 seperate functions I clearly do not know the code well enough and I have no facilities to test such a thing I trust you here though. -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
Probably the best way would be to remove endianness swapping from mips_m4k_read_memory and put it to mips32_pracc/dma_read_mem32/16. Same for write. pro: mips32_pracc_read_mem32, ... will return a byte array in target endianness, so no cast necessary. con: Add swapping to at least 10 seperate functions I clearly do not know the code well enough and I have no facilities to test such a thing I trust you here though. There is no problem to get it work, but I'm not sure if this is really the best way. I try to prepare a patch within the next days, so you and others can comment. BR, Stefan ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
There is no problem to get it work, but I'm not sure if this is really the best way. I try to prepare a patch within the next days, so you and others can comment. I have particular reason to be especially grateful for your efforts here... ;-) Thanks! -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Wed, Jul 6, 2011 at 6:35 PM, Mahr, Stefan stefan.m...@sphairon.com wrote: Did you see this by testing or by inspection? Both :) Do we even have the right macros here? It would be something like unaligned uint32_t access macros, which will have to exist in host endian versions. mips32_pracc_read_mem casts uint32 to void, so we need to cast it back to uint32 Where exactly ? I can see that void* is casted in uint32*, but not vice versa... I can see also that in mips_m4k_read_memory() uint8_t* is casted to void*. BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Thu, Jul 7, 2011 at 12:59 AM, Andreas Fritiofson andreas.fritiof...@gmail.com wrote: No, casting a pointer-to-any-type to a pointer-to-void and back will never cause alignment issues. The question is who makes the guarantee that the function is only ever called with uint32-aligned generic pointers. If it just happens to be so that all *current* callers pass a uint32 pointer cast to void pointer, it would be a terribly bad idea to suddenly assume that. If it is guaranteed by design/contract, why is a void pointer used at all? Just use a pointer to uint32 then. I have no experience with the MIPS code or arch at all, but if it was up to me I'd prefer if a *_read_mem function didn't interpret the data and thus it should deal with void pointers. I see no other way... Actually, any data you want to write must be transfered to 32-bit value put to the register... Acutually, it is transformed in 32-bit parameter, put onto the miniprogram EJTAG stack, and then copied in the miniprogram (a small Monitor ROM, if you want, written dynamically via dongle) to register. This register is the written to RAM. Now, there must be a way to put 8-bit values to EJTAG stack and then just put this 8 bits into the reg in a miniprogram, but that would demand quite a bit of changes of assembly bytecode miniprograms, IMHO. I don't know at this point, I'll have to study MIPS code more throughly. It would by design be totally free from all endian issues and conversions. Moreover, a function accepting a pointer-to-void should be prepared to handle any kind of alignment thrown at it (unless explicitly stated). That excludes direct casts to uint32_t*. That's why GCC is complaining. Sometimes... It should never complain when casting a generic pointer to another pointer, right? You shouldn't even need an explicit cast IIRC. Where param_in is uint32_t*, and buf is uint8_t* ? Is is maybe because of code like this : for (i = 0; i count; i++) { param_in[i + 2] = buf[i]; } Dunno... I never seen the warnings so far... BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Thu, Jul 7, 2011 at 11:04 PM, Michael Schwingen rincew...@discworld.dascon.de wrote: Am 07/07/2011 10:41 PM, schrieb Mahr, Stefan: Probably the best way would be to remove endianness swapping from mips_m4k_read_memory and put it to mips32_pracc/dma_read_mem32/16. Same for write. pro: mips32_pracc_read_mem32, ... will return a byte array in target endianness, so no cast necessary. con: Add swapping to at least 10 seperate functions Not sure about this. Without having a look at the code, I would expect a function with read_mem32 in the name to return a 32-bit value, not a byte array, and I would expect to get a 32-bit value without a cast. Which cast exacly are you mentioning, and in which function ? static int mips32_pracc_read_mem32(struct mips_ejtag *ejtag_info, uint32_t addr, int count, uint32_t *buf) does not do any casting and returns 32-bit value. Especially if this is used in 10 places, this looks like there *is* a need for a function that returns swapped 32-bit values, only the function uses the wrong data types. I have seen some things that can be avoided in mips32_pracc code. Can you point me exactly to the places, I can not seem to get the particular problem... BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Thu, Jul 7, 2011 at 10:41 PM, Mahr, Stefan stefan.m...@sphairon.com wrote: If alignment is not guaranteed, casting from uint32 to void would cause problems too, wouldn't it? Why? Sorry for confusion. I meant the casting within mips32_pracc_read_mem. This is also a cast from void* to uint32_t*. If there will be an alignment error, it will occur here too. That's correct. There is no way to know from the code context, is there? No documentation either. Probably the best way would be to remove endianness swapping from mips_m4k_read_memory and put it to mips32_pracc/dma_read_mem32/16. Same for write. pro: mips32_pracc_read_mem32, ... will return a byte array in target endianness, so no cast necessary. con: Add swapping to at least 10 seperate functions I am not keen to have code repetition in MIPS32 PrAcc code, which is already bloated and very difficult to maintain... I think we should well understand what is happening here before resolving the problem in the most elegant manner. BR, Drasko ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
[Openocd-development] MIPS target, big endian host
Hi Øyvind, Did you see problems with host endianness or why did you commit this patch: http://openocd.git.sourceforge.net/git/gitweb.cgi?p=openocd/openocd;a=commit;h=2482244b0788c007dd789c21a4416379c229ea5c This patch brokes endianness on big endian host. mips32_pracc_read_mem and mips32_pracc_write_mem return values (buffer[i]) are already in host endianness, so le_to_h_u32 fails on big endian hosts. I already mentioned this in previous discussions. Best regards Stefan ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
mips32_pracc_read_mem and mips32_pracc_write_mem return values (buffer[i]) are already in host endianness, so le_to_h_u32 fails on big endian hosts. I already mentioned this in previous discussions. Ouch. Did you see this by testing or by inspection? The problem is that I mis-interpreted a warning from the compiler. The compiler warned me that I shouldn't cast a uint8_t * to a uint32_t * as this increases alignment. Do we even have the right macros here? It would be something like unaligned uint32_t access macros, which will have to exist in host endian versions. -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
Did you see this by testing or by inspection? Both :) Do we even have the right macros here? It would be something like unaligned uint32_t access macros, which will have to exist in host endian versions. mips32_pracc_read_mem casts uint32 to void, so we need to cast it back to uint32. I found no suitable macro in actual sources. -Ursprüngliche Nachricht- Von: Øyvind Harboe [mailto:oyvind.har...@zylin.com] Gesendet: Mittwoch, 6. Juli 2011 15:02 An: Mahr, Stefan Cc: openocd-development@lists.berlios.de Betreff: Re: MIPS target, big endian host mips32_pracc_read_mem and mips32_pracc_write_mem return values (buffer[i]) are already in host endianness, so le_to_h_u32 fails on big endian hosts. I already mentioned this in previous discussions. Ouch. Did you see this by testing or by inspection? The problem is that I mis-interpreted a warning from the compiler. The compiler warned me that I shouldn't cast a uint8_t * to a uint32_t * as this increases alignment. Do we even have the right macros here? It would be something like unaligned uint32_t access macros, which will have to exist in host endian versions. -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Wed, Jul 6, 2011 at 6:35 PM, Mahr, Stefan stefan.m...@sphairon.com wrote: Did you see this by testing or by inspection? Both :) Do we even have the right macros here? It would be something like unaligned uint32_t access macros, which will have to exist in host endian versions. mips32_pracc_read_mem casts uint32 to void, so we need to cast it back to uint32. I found no suitable macro in actual sources. Hmm then I think we ought to define one to get this put to bed once and for all... -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
mips32_pracc_read_mem casts uint32 to void, so we need to cast it back to uint32. I found no suitable macro in actual sources. Hmm then I think we ought to define one to get this put to bed once and for all... static inline uint32_t uint32_read_unaligned(const void *data) { uint32_t t; // Let's trust the compiler to do something very clever here. memcpy(t, data, sizeof(t)); return t; } ? -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
mips32_pracc_read_mem casts uint32 to void, so we need to cast it back to uint32. I found no suitable macro in actual sources. Hmm then I think we ought to define one to get this put to bed once and for all... static inline uint32_t uint32_read_unaligned(const void *data) { uint32_t t; // Let's trust the compiler to do something very clever here. memcpy(t, data, sizeof(t)); return t; } Do we really need a memcpy? Could we ever run into an alignment issue when simply cast void *back* to uint32 ? If not, I would prefer the simplifed solution. static inline uint32_t h_to_h_u32(const void *data) { return (uint32_t)*data; } ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Wed, Jul 6, 2011 at 11:28 PM, Mahr, Stefan stefan.m...@sphairon.com wrote: mips32_pracc_read_mem casts uint32 to void, so we need to cast it back to uint32. I found no suitable macro in actual sources. Hmm then I think we ought to define one to get this put to bed once and for all... static inline uint32_t uint32_read_unaligned(const void *data) { uint32_t t; // Let's trust the compiler to do something very clever here. memcpy(t, data, sizeof(t)); return t; } Do we really need a memcpy? Trust the compiler: oyvind@fierce:~$ cat test.c #include string.h #include stdint.h uint32_t uint32_read_unaligned(const void *data) { uint32_t t; // Let's trust the compiler to do something very clever here. memcpy(t, data, sizeof(t)); return t; } oyvind@fierce:~$ gcc -O3 -S test.c oyvind@fierce:~$ cat test.s .file test.c .text .p2align 4,,15 .globl uint32_read_unaligned .type uint32_read_unaligned, @function uint32_read_unaligned: .LFB22: .cfi_startproc movl(%rdi), %eax ret .cfi_endproc .LFE22: .size uint32_read_unaligned, .-uint32_read_unaligned .ident GCC: (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2 .section.note.GNU-stack,,@progbits Could we ever run into an alignment issue when simply cast void *back* to uint32 ? If not, I would prefer the simplifed solution. The below does not work in all cases. It will break on architectures that do not support unaligned access. That's why GCC is complaining. Sometimes... -- Øyvind Harboe - Can Zylin Consulting help on your project? US toll free 1-866-980-3434 / International +47 51 87 40 27 http://www.zylin.com/ ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
Trust the compiler NO ! :-) $ gcc -O3 -S test.c $ cat test.s .file test.c .text .p2align 4,,15 .globl uint32_read_unaligned .type uint32_read_unaligned, @function uint32_read_unaligned: pushl %ebp movl%esp, %ebp subl$16, %esp movl8(%ebp), %eax movl(%eax), %eax leave ret .size uint32_read_unaligned, .-uint32_read_unaligned .ident GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5 .section.note.GNU-stack,,@progbits - $ mips-linux-gcc -O3 -S test.c $ cat test.s .file 1 test.c .section .mdebug.abi32 .previous .abicalls .text .align 2 .globl uint32_read_unaligned .entuint32_read_unaligned .type uint32_read_unaligned, @function uint32_read_unaligned: .frame $sp,24,$31 # vars= 8, regs= 1/0, args= 0, extra= 8 .mask 0x1000,-8 .fmask 0x,0 .setnoreorder .cpload $25 .setreorder subu$sp,$sp,24 .cprestore 0 lwl $2,0($4) lwr $2,3($4) swl $2,8($sp) swr $2,11($sp) lw $2,8($sp) sw $28,16($sp) .setnoreorder .setnomacro j $31 addu$sp,$sp,24 .setmacro .setreorder .enduint32_read_unaligned .ident GCC: (GNU) 3.3.6 - $ mips-linux-gnu-gcc -O3 -S test.c $ cat test.s .file 1 test.c .section .mdebug.abi32 .previous .gnu_attribute 4, 1 .abicalls .option pic0 .text .align 2 .globl uint32_read_unaligned .entuint32_read_unaligned .type uint32_read_unaligned, @function uint32_read_unaligned: .setnomips16 .frame $sp,8,$31 # vars= 8, regs= 0/0, args= 0, gp= 0 .mask 0x,0 .fmask 0x,0 .setnoreorder .setnomacro lwl $2,0($4) addiu $sp,$sp,-8 addiu $sp,$sp,8 j $31 lwr $2,3($4) .setmacro .setreorder .enduint32_read_unaligned .ident GCC: (Sourcery G++ Lite 4.3-154) 4.3.3 - $ arm-none-eabi-gcc -O3 -S test.c $ cat test.s .cpu arm7tdmi .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 1 .eabi_attribute 30, 2 .eabi_attribute 18, 4 .file test.c .text .align 2 .global uint32_read_unaligned .type uint32_read_unaligned, %function uint32_read_unaligned: @ Function supports interworking. @ args = 0, pretend = 0, frame = 8 @ frame_needed = 0, uses_anonymous_args = 0 str lr, [sp, #-4]! sub sp, sp, #12 mov r1, r0 mov r2, #4 add r0, sp, #4 bl memcpy ldr r0, [sp, #4] add sp, sp, #12 ldr lr, [sp], #4 bx lr .size uint32_read_unaligned, .-uint32_read_unaligned .ident GCC: (GNU) 4.5.1 ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development
Re: [Openocd-development] MIPS target, big endian host
On Wed, Jul 6, 2011 at 11:35 PM, Øyvind Harboe oyvind.har...@zylin.comwrote: On Wed, Jul 6, 2011 at 11:28 PM, Mahr, Stefan stefan.m...@sphairon.com wrote: mips32_pracc_read_mem casts uint32 to void, so we need to cast it back to uint32. I found no suitable macro in actual sources. Hmm then I think we ought to define one to get this put to bed once and for all... static inline uint32_t uint32_read_unaligned(const void *data) { uint32_t t; // Let's trust the compiler to do something very clever here. memcpy(t, data, sizeof(t)); return t; } Do we really need a memcpy? Trust the compiler: oyvind@fierce:~$ cat test.c #include string.h #include stdint.h uint32_t uint32_read_unaligned(const void *data) { uint32_t t; // Let's trust the compiler to do something very clever here. memcpy(t, data, sizeof(t)); return t; } oyvind@fierce:~$ gcc -O3 -S test.c And with the default optimization level (O2, isn't it)? Could we ever run into an alignment issue when simply cast void *back* to uint32 ? If not, I would prefer the simplifed solution. The below does not work in all cases. It will break on architectures that do not support unaligned access. No, casting a pointer-to-any-type to a pointer-to-void and back will never cause alignment issues. The question is who makes the guarantee that the function is only ever called with uint32-aligned generic pointers. If it just happens to be so that all *current* callers pass a uint32 pointer cast to void pointer, it would be a terribly bad idea to suddenly assume that. If it is guaranteed by design/contract, why is a void pointer used at all? Just use a pointer to uint32 then. I have no experience with the MIPS code or arch at all, but if it was up to me I'd prefer if a *_read_mem function didn't interpret the data and thus it should deal with void pointers. It would by design be totally free from all endian issues and conversions. Moreover, a function accepting a pointer-to-void should be prepared to handle any kind of alignment thrown at it (unless explicitly stated). That excludes direct casts to uint32_t*. That's why GCC is complaining. Sometimes... It should never complain when casting a generic pointer to another pointer, right? You shouldn't even need an explicit cast IIRC. /Andreas ___ Openocd-development mailing list Openocd-development@lists.berlios.de https://lists.berlios.de/mailman/listinfo/openocd-development