Forum unknown
· Software
#C's
15 messages in this thread
I was having a problem porting a piece of C code to the Amiga because Lattice C
insists on changing the value of a pointer when cast. I had pointer to char
and cast it and if the pointer did not happen to be an even address, the cast
changed it! so it ended up pointing to a different address (garbage). I just
tried something, I have two variables declared separated by 104 bytes of
storage, printf("%d\n",&x-&y) prints 104, but printf("%d\n",&y-&x) prints
65432. looks like only 16 bits, the object code is doing a sub.w instruction,
not sub.l seems strange, none of my other 68000 computers do this.
This was fixed in version 3.03a of Lattice … they were trying to "protect"
the user from creating code that whould do a MOVE.L or MOVE.W from an odd
address …. any pointer that was declared as pointing to anything other than
char was & with 0xFFFFFFFE , since Amiga Include files use alot of APTR's this
caused real problems with buffers etc… I don't think 'C' was ment to be a
protective language (that's what LINT is for).
This was fixed in version 3.03a of Lattice … they were trying to "protect"
the user from creating code that whould do a MOVE.L or MOVE.W from an odd
address …. any pointer that was declared as pointing to anything other than
char was & with 0xFFFFFFFE , since Amiga Include files use alot of APTR's this
caused real problems with buffers etc… I don't think 'C' was ment to be a
protective language (that's what LINT is for).
Not sure I understand what you're claiming that Lattice C is doing wrong. You
_can't_ have a valid pointer to a char situated on an odd address (address regs
can't contain odd values). You didn't mention to what you were casting the
pointer to char, by the way.
What's wrong with the printf() results? The &x and &y values would be the same
whether word or long, since they're sign extended as words. If it's doing a
sub.w instead of a sub.l that does sound like a bug, since the printf() 'd'
conversion specification specifically relates to ints (unless the 'l' modifier
is used) and Lattice is _supposed_ to treat ints as 32 bit animals.
— Bob Perez
Address regs can't contain odd values? Can't you say
lea 13,a0
move.b (a0),d0
13 is odd.
I thought the low bit goes out the 68000 and controls the upper/lower data
strobe line to the memory signifying that it wants only the least or most
significant byte of a certain word, so for practical purposes, even though
you only _really_ have address lines a1-a23 you get an effective a0 address
line, the data strobe.
I was casting it as pointer to int. Now I know that ints must be aligned on
word boundaries, but I had to get to an int that may or may not have been,
and I had a choice, leave it as pointer to char and have the compiler
complain about different types of objects being assigned, or change it to
pointer to int, and have my own C code that would avoid a bus error by
checking for an odd address myself and if odd moving the int one byte at a
time.
I couldn't win in this situation, and what I did does work on other systems,
like I told them. As for the printf, &x is a machine address, how can it
only be one word (16 bits)? I looked at assembler code produced on my Wicat
for that and it does a: pea _x pea pushes 32 bits onto the stack. I just
thought it was strange whatever it is that Lattice is doing. Sorry to hear
about the pre-demise of another 68000 magazine idea. Maybe its a conspiracy
by IBM? Gary
Lattice 3.03 does not do any even alignment of addresses. They do listen! I
understand why they did it — but I think it goes against the philosophy of the
language to have the compiler make those kind of decisions. I might suggest
that if you ever need to store two types of pointers at some location, you use
a union rather than a cast. That is a more portable way of handling it.
-Steve
The reason I was actually trying to do what I did was because it was an
interpreter that was storing generated code in an array in memory. sometimes
opcodes are one byte and can be followed by a 32 bit address therefore the
address (treated as int) may or may not be on a word boundary depending upon
previous opcodes alignment.
In this case a union would just complicate matters, and anyway the way
Lattice passes unions to functions seems strange to me. I had a problem with
that too. I had functions declared where one of the args was a union of a
double, an int, and a pointer to char, and the other arg was a type flag. In
the calling routine the code would just pass a double, int or pointer to
char, and the appropriate flag.
It seems that Lattice wants me to actually pass a union, then startup code in
the routine will take the address of the union I passed, make a copy on the
stack and use that. Seems more efficient to me to just allow me to pass
whatever in, and then if there is a statement that access the arg as a double
or whatever generate code to access it that way.
The starting address of that argument will be the same no matter what type it
is. That is what happens on my Sun anyway. Imagine if the routine was
recursive with multiple unions as arguments, all that extra stack space and
the time taken to make copies of all the arguments when they are already
being passed by value anyway.
The reason I was actually trying to do what I did was because it was an
interpreter that was storing generated code in an array in memory. sometimes
opcodes are one byte and can be followed by a 32 bit address therefore the
address (treated as int) may or may not be on a word boundary depending upon
previous opcodes alignment.
In this case a union would just complicate matters, and anyway the way
Lattice passes unions to functions seems strange to me. I had a problem with
that too. I had functions declared where one of the args was a union of a
double, an int, and a pointer to char, and the other arg was a type flag. In
the calling routine the code would just pass a double, int or pointer to
char, and the appropriate flag.
It seems that Lattice wants me to actually pass a union, then startup code in
the routine will take the address of the union I passed, make a copy on the
stack and use that. Seems more efficient to me to just allow me to pass
whatever in, and then if there is a statement that access the arg as a double
or whatever generate code to access it that way.
The starting address of that argument will be the same no matter what type it
is. That is what happens on my Sun anyway. Imagine if the routine was
recursive with multiple unions as arguments, all that extra stack space and
the time taken to make copies of all the arguments when they are already
being passed by value anyway.
Lattice 3.03 does not do any even alignment of addresses. They do listen! I
understand why they did it — but I think it goes against the philosophy of the
language to have the compiler make those kind of decisions. I might suggest
that if you ever need to store two types of pointers at some location, you use
a union rather than a cast. That is a more portable way of handling it.
-Steve
Yeah, I think I misunderstood your question..now it's scrolled off and I can't
access it. I thought you were trying to force a longword access with a pointer
that contained an odd value. Sure, you can lea 13,a0 if your next action on a0
is a byte access only since, as you point out, the UDS and LDS process the odd
bit so that the access winds up on an even address after all.
Of course, &n is always a 32 bit value on the Amiga, I thought you were talking
about the value (&x – &y) which should also produce a 32 bit value but not
necessarily, especially when you haven't used the 'l' modifier in your
conversion specification. New compilers often have bugs like that.
I'm still looking up potential publishers and have some hope for the idea. I'll
let you know. Thanks
The problem was CthaThe problem was that I was trying to access code
generated by the Icon interpreter and 32 bit addresses may not have been
aligned on word boundaries since Icon uses a lot of 1 byte opcodes. So there
was C code to take care of that problem and if it checked and found the
address was odd it would move the 4 bytes to an integer variable 1 byte at a
time.
Either the compiler would complain about different types of pointers if I
left them both pointer to char, or if (as I did) I heeded its warning and
changed one to pointer to int (cast it rather) then it chopped the address
for me. Seems I couldn't win and I just choose the wrong alternative is all.
As for the &x – &y, yes it should be 32 bits and I can't see how the answer
could be 65432 for &y-&x and 104 for &x-&y unless it was doing 16 bit
arithmetic, it looks to me very much like the "wrap-around" in 16 bits from
-1, even if one of the address was large enough to cause this, and they
weren't I printed them too, with the %d specification and they were both 200
thousand something I would think it would have said something like 2 billion
if it was wrapping in 32 bits. Anyway.
I didn't know Lattice was a new compiler on the Amiga, I just assumed it was
a port of some other version of the compiler, say their 68000 version for the
Mac or something. I just read in Unix World that Lattice has signed an
agreement with SAS institute to put the Lattice C compiler onto the IBM 370
series computers. Supposedly compatible with IBM-pc code too. Its a small
world.
The problem was CthaThe problem was that I was trying to access code
generated by the Icon interpreter and 32 bit addresses may not have been
aligned on word boundaries since Icon uses a lot of 1 byte opcodes. So there
was C code to take care of that problem and if it checked and found the
address was odd it would move the 4 bytes to an integer variable 1 byte at a
time.
Either the compiler would complain about different types of pointers if I
left them both pointer to char, or if (as I did) I heeded its warning and
changed one to pointer to int (cast it rather) then it chopped the address
for me. Seems I couldn't win and I just choose the wrong alternative is all.
As for the &x – &y, yes it should be 32 bits and I can't see how the answer
could be 65432 for &y-&x and 104 for &x-&y unless it was doing 16 bit
arithmetic, it looks to me very much like the "wrap-around" in 16 bits from
-1, even if one of the address was large enough to cause this, and they
weren't I printed them too, with the %d specification and they were both 200
thousand something I would think it would have said something like 2 billion
if it was wrapping in 32 bits. Anyway.
I didn't know Lattice was a new compiler on the Amiga, I just assumed it was
a port of some other version of the compiler, say their 68000 version for the
Mac or something. I just read in Unix World that Lattice has signed an
agreement with SAS institute to put the Lattice C compiler onto the IBM 370
series computers. Supposedly compatible with IBM-pc code too. Its a small
world.
Yeah, I think I misunderstood your question..now it's scrolled off and I can't
access it. I thought you were trying to force a longword access with a pointer
that contained an odd value. Sure, you can lea 13,a0 if your next action on a0
is a byte access only since, as you point out, the UDS and LDS process the odd
bit so that the access winds up on an even address after all.
Of course, &n is always a 32 bit value on the Amiga, I thought you were talking
about the value (&x – &y) which should also produce a 32 bit value but not
necessarily, especially when you haven't used the 'l' modifier in your
conversion specification. New compilers often have bugs like that.
I'm still looking up potential publishers and have some hope for the idea. I'll
let you know. Thanks
Address regs can't contain odd values? Can't you say
lea 13,a0
move.b (a0),d0
13 is odd.
I thought the low bit goes out the 68000 and controls the upper/lower data
strobe line to the memory signifying that it wants only the least or most
significant byte of a certain word, so for practical purposes, even though
you only _really_ have address lines a1-a23 you get an effective a0 address
line, the data strobe.
I was casting it as pointer to int. Now I know that ints must be aligned on
word boundaries, but I had to get to an int that may or may not have been,
and I had a choice, leave it as pointer to char and have the compiler
complain about different types of objects being assigned, or change it to
pointer to int, and have my own C code that would avoid a bus error by
checking for an odd address myself and if odd moving the int one byte at a
time.
I couldn't win in this situation, and what I did does work on other systems,
like I told them. As for the printf, &x is a machine address, how can it
only be one word (16 bits)? I looked at assembler code produced on my Wicat
for that and it does a: pea _x pea pushes 32 bits onto the stack. I just
thought it was strange whatever it is that Lattice is doing. Sorry to hear
about the pre-demise of another 68000 magazine idea. Maybe its a conspiracy
by IBM? Gary
Not sure I understand what you're claiming that Lattice C is doing wrong. You
_can't_ have a valid pointer to a char situated on an odd address (address regs
can't contain odd values). You didn't mention to what you were casting the
pointer to char, by the way.
What's wrong with the printf() results? The &x and &y values would be the same
whether word or long, since they're sign extended as words. If it's doing a
sub.w instead of a sub.l that does sound like a bug, since the printf() 'd'
conversion specification specifically relates to ints (unless the 'l' modifier
is used) and Lattice is _supposed_ to treat ints as 32 bit animals.
— Bob Perez