pointers getting nutz !

Discuss the development of software, tools, libraries and anything else that helps make ps2dev happen.

Moderators: cheriff, Herben

Post Reply
User avatar
evilo
Posts: 230
Joined: Thu Apr 22, 2004 8:40 pm
Contact:

pointers getting nutz !

Post by evilo »

I currently have some strange behaviour with pointers to different data types ..

So le'ts try to explain myself as simple as possible ! let's say that I have one function with the following prototype :
void* get_something(_u32 parameter);
And that can return a pointer to either a u8, u16, u32 (depeding of the case, and this is not the case in which the returned value type is not the exptected one), Then this fct is called by an other one like :
_u16 myFct(_u32 parameter)
{

_u16* ptr = get_something(parameter);

if (ptr == NULL)
return 0;
else
return *ptr;
}
In the above case the expected return value is a u16, so it should work, but calling it result in garbages in *ptr, and only a bad hack like the following one allow to get the correct return value....
Casting have no effect, and compiler keep complains on "casting pointers from different sizes" if I cast it.
_u16 myFct(_u32 parameter)
{

_u8* ptr = get_something(parameter);

if (ptr == NULL)
return 0;
else
return ptr[1]<<8|ptr[0];
}
So just declaring it as a u8...

I have similar fct that are waiting for a u8 and u32...
only _u8 is working fine, as it "seems" to be the only possible things returned, but for _u32 value, the only way to make it working is to apply the same kind of stuff that above...

What is the problem ?? This code is working just fine when compiled and ran on a PC..

Is it me, or is there any issue with pointer in the GCC, SDK ??

thanks..
pixel
Posts: 791
Joined: Fri Jan 30, 2004 11:43 pm

Post by pixel »

It all depends on what your "void *" is pointing at. You have to know something: on MIPS processors, memory access (load and store) has to be aligned. That is:

Code: Select all

u8 tab&#91;6&#93; = &#123;1, 2, 3, 4, 5, 6&#125;;
u32 * p = &tab&#91;2&#93;;
u32 a = *p;
This piece of code will perfectly work on any x86, but won't on PS2. Most probably will generate an exception though, instead of having a random behavior like you're experiencing.
pixel: A mischievous magical spirit associated with screen displays. The computer industry has frequently borrowed from mythology. Witness the sprites in computer graphics, the demons in artificial intelligence and the trolls in the marketing department.
Guest

Post by Guest »

Try return (_u16)*ptr;

Pixel, are you sure alignment is the issue here ? I thought the compiler should automatically generate instructions to handle unaligned load/stores ?
I am wondering that it simply isn't casting the return value properly.

If alignment was the issue, then a bus-error should be generated.

But the problem is certainly due to each architectures native word size and unaligned load/store handling. :) But should be able to code a program around that.
User avatar
evilo
Posts: 230
Joined: Thu Apr 22, 2004 8:40 pm
Contact:

Post by evilo »

That's exactly the kind of stuff done inside the function...

hmm... I didn't know that memory aligment was also applying in this case..

is there any workaround, except the one I used (shtg more clean) ??

thanks for your answer.
Guest

Post by Guest »

evilo wrote:That's exactly the kind of stuff done inside the function...

hmm... I didn't know that memory aligment was also applying in this case..

is there any workaround, except the one I used (shtg more clean) ??

thanks for your answer.
Did you try what I suggested ?

The alignment issue here is how the compiler by default does casting (or lack thereof) when moving the return value from your function (32 bits) to the u16 variable (16 bits).
User avatar
evilo
Posts: 230
Joined: Thu Apr 22, 2004 8:40 pm
Contact:

Post by evilo »

yes sorry gorim...
_u16* ptr =(_u16* ) get_something(parameter);
if (ptr == NULL)
return 0;
else
return (_u16)*ptr;
the effect is the same... I get it back as a u8 but casted to u16 ...
Guest

Post by Guest »

I bet the problem is inside get_something()....


code code! show me!
User avatar
evilo
Posts: 230
Joined: Thu Apr 22, 2004 8:40 pm
Contact:

Post by evilo »

lol... :)
id* translate_address_read(_u32 address)
{
address &= 0xFFFFFF;


if (address == 0x8008)
ram[0x8008] = (_u8)((abs(TIMER_HINT_RATE - (int)timer_hint)) >> 2);

if (address <= RAM_END)
return ram + address;

// ===================================

//Get EEPROM status?
if (eepromStatusEnable)
{
eepromStatusEnable = FALSE;
if (address == 0x220000 || address == 0x230000)
{
eepromStatus = 0xFFFFFFFF;
return &eepromStatus;
}
}

//ROM (LOW)
if (rom.data && address >= ROM_START && address <= ROM_END)
{
if (address <= ROM_START + rom.length)
return rom.data + (address - ROM_START);
else
return NULL;
}

//ROM (HIGH)
if (rom.data && address >= HIROM_START && address <= HIROM_END)
{
if (address <= HIROM_START + (rom.length - 0x200000))
return rom.data + 0x200000 + (address - HIROM_START);
else
return NULL;
}

// ===================================

//BIOS Access?
if ((address & 0xFF0000) == 0xFF0000)
return bios + (address & 0xFFFF); // BIOS ROM

// ===================================

//Signal a flash memory error
if (memory_unlock_flash_write)
memory_flash_error = TRUE;

return NULL;
}
ram is declared as _u8 ram[]
eepromStatus is delacred as _u32;

code is working like a charm on pc, and this is typically the case that pixel showed before.. I don't think there is any clue apart rewriting the code in a completely different way..
Guest

Post by Guest »

Where exactly in the code is eepromStatus declared ?

I see you returning &eepromStatus. If it is declared inside the function, you are returning a pointer to the stack and that will be corrupted surely. The only way to prevent that is to declared eepromStatus statically or outside of any function. Since stack corruption manifests in weird and random ways, its quite likely it can work fine on a PC but fail elsewhere.

Other than that, not sure what the rom structure looks like, but nothing else looks obviously wrong. :)
User avatar
evilo
Posts: 230
Joined: Thu Apr 22, 2004 8:40 pm
Contact:

Post by evilo »

eepromStatus is a global static variable,

rom.data is a u8 array

hmm ;)
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

Two things:

1 - What is the address when it goes bonkers? Maybe it is an alignment issue.
2 - Why don't you just look at the generated code?

For 1, look at it this way. The value is a pointer. How is the code supposed to know what it will be? If the address is a constant like a variable address, code to handle unaligned access can be generated. However, there's no way to do that with a pointer. YOU have to do that.

u16 access_word(u16* address) {
if ((u32)address & 1) {
u8 *ptr = (u8*)address;
return (u16)(ptr[1]<<8 | ptr[0]);
} else
return *address;
}

See? YOU handle the alignment yourself because YOU can determine the alignment where the compiler can't.
mrbrown
Site Admin
Posts: 1537
Joined: Sat Jan 17, 2004 11:24 am

Post by mrbrown »

Yes, just post the assembly of the function, so folks will stop trying to guess at what's going on.

And here someone told me not too long ago that knowing asm for the CPU you're dealing with isn't important :P.
"He was warned..."
dreamtime
Posts: 14
Joined: Mon Feb 02, 2004 10:12 pm
Location: Melbourne, Australia
Contact:

Post by dreamtime »

Did you guys work out what the problem with this was?
I think I remember having similar problems around 2 years ago and came up with a solution :)
I'd need to see exactly how all your globals are declared.
Post Reply