log in | register | forums
Show:
Go:
Forums
Username:

Password:

User accounts
Register new account
Forgot password
Forum stats
List of members
Search the forums

Advanced search
Recent discussions
- !OBrowse reviewed (News:1)
- Aemulor (Gen:13)
- DDE reaches release 28 and above (News:)
- Elesar quicks dispels stormy clouds (News:2)
- RISC OS London Show 2017 - Notes from the talks (News:2)
- RISC OS London Show 2017 (News:)
- RISC OS London Show 2017 - Pictures (News:)
- October News (News:2)
- Retrospective thoughts on 12 months of Titanium ownership (News:4)
- RISC OS London Show 2017 (News:1)
Latest postings RSS Feeds
RSS 2.0 | 1.0 | 0.9
Atom 0.3
Misc RDF | CDF
Site Search
 
Article archives
Acorn Arcade forums: Programming: Compilerism of the day
 
  Compilerism of the day
  Phlamethrower (14:10 8/5/2010)
  Phlamethrower (14:23 8/5/2010)
    pnaulls (14:33 8/5/2010)
    Stoppers (16:10 8/5/2010)
      Phlamethrower (21:23 9/5/2010)
        swirlythingy (18:13 29/3/2013)
          thesnark (19:17 29/3/2013)
          Loris (17:31 3/4/2013)
  sirbod (13:24 13/1/2014)
    swirlythingy (13:46 13/1/2014)
      sirbod (14:10 13/1/2014)
        Phlamethrower (16:01 13/1/2014)
        swirlythingy (16:18 13/1/2014)
          sirbod (17:38 13/1/2014)
            arawnsley (23:12 13/1/2014)
              swirlythingy (23:40 13/1/2014)
                Zarchos (09:03 15/1/2014)
                  sirbod (12:47 12/2/2014)
                    Zarchos (09:57 13/2/2014)
                    sirbod (17:51 17/2/2014)
                      nunfetishist (09:33 18/2/2014)
              sirbod (00:15 14/1/2014)
  sirbod (10:11 14/1/2014)
    Phlamethrower (12:16 14/1/2014)
      sirbod (13:36 14/1/2014)
 
Jeffrey Lee Message #114358, posted by Phlamethrower at 14:10, 8/5/2010
PhlamethrowerHot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff

Posts: 15055
Since when did the << operator mean "rotate left"?

#include <stdio.h>
#include <stdlib.h>

int main(int argc,char **argv)
{
int size = atoi(argv[1]);
unsigned long pow2 = ((unsigned long)1)<<size;
unsigned long bits1 = pow2-1;
unsigned long bits2 = (((unsigned long)1)<<size)-1;
printf("%d %d %08lx %08lx %08lx\n",
(int)sizeof(unsigned long),size,pow2,bits1,bits2);
return 0;
}


GCC 4.1.1 on RISC OS:


*test 32 (or seemingly any other value >=32)
4 32 00000000 ffffffff ffffffff
*test -1 (or seemingly any other value <=-1)
4 -1 00000000 ffffffff ffffffff
GCC 4.4.1 on Linux (i486-linux-gnu):


$ ./test 32
4 32 00000001 00000000 00000000
$ ./test 33
4 33 00000002 00000001 00000001
(etc.)
$ ./test -1
4 -1 80000000 7fffffff 7fffffff
$ ./test -2
4 -2 40000000 3fffffff 3fffffff
(etc.)
GCC 3.4.4 on Cygwin (i.e. i686-pc-cygwin) seems to produce the same results as the Linux test unhappy

[Edited by Phlamethrower at 15:13, 8/5/2010]
  ^[ Log in to reply ]
 
Jeffrey Lee Message #114359, posted by Phlamethrower at 14:23, 8/5/2010, in reply to message #114358
PhlamethrowerHot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff

Posts: 15055
And after searching around a bit, it looks like it's the fault of the C standard, whereby out-of-range shifts have undefined behaviour. Grr!
  ^[ Log in to reply ]
 
Peter Naulls Message #114360, posted by pnaulls at 14:33, 8/5/2010, in reply to message #114359
Member
Posts: 317
And after searching around a bit, it looks like it's the fault of the C standard, whereby out-of-range shifts have undefined behaviour. Grr!
Yeah. And don't get started on the default sign of chars. Certainly I would expect consistency on cygwin vs x86 Linux, as well as between RISC OS and ARM Linux (EABI notwithstanding). But as you note, there are a number of things in the C standard where it's not defined, but in practice tends to be processor dependent including the above two, and things like sign of bit fields, structure packing.

The compiler will generate a warning if it can, although whether it should (or should go to the effort to) in your example is another matter.
  ^[ Log in to reply ]
 
Simon Willcocks Message #114367, posted by Stoppers at 16:10, 8/5/2010, in reply to message #114359
Member
Posts: 278
And after searching around a bit, it looks like it's the fault of the C standard, whereby out-of-range shifts have undefined behaviour. Grr!
It's the way the x86 instruction works; it just ignores bits 5 and up. I got caught by it when I was doing my ARM emulator.

It's not something a compiler can warn about, either, unless you fancy a warning on every << instruction. Does it warn you if you shift by a too large constant?

Simon
  ^[ Log in to reply ]
 
Jeffrey Lee Message #114389, posted by Phlamethrower at 21:23, 9/5/2010, in reply to message #114367
PhlamethrowerHot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff

Posts: 15055
Does it warn you if you shift by a too large constant?
Yes - GCC 4.1.1 seems to warn if you give give it a too-large const variable and turn on optimisation (e.g. const int i=33; unsigned long j=1<<i), or if you simply specify specify the shift directly (e.g. unsigned long j=1<<33). A non-const shift amount, with or without optimisation, doesn't seem to generate any warning, even if it's obvious (to the programmer!) that the shift amount is constant (And a const shift without optimisation doesn't generate any warning either, presumably because the const variable optimisation is disabled)

Of course none of that really helps me with my problem, where I was interested in shifting using a user-specified value wink

[Edited by Phlamethrower at 22:25, 9/5/2010]
  ^[ Log in to reply ]
 
Martin Bazley Message #122177, posted by swirlythingy at 18:13, 29/3/2013, in reply to message #114389

Posts: 460
I found out not too long ago - while attempting to untangle some code which it emerged was relying on this behaviour - that ARM does indeed have a similar problem with out-of-range shifts to x86. The difference is that the cut-off point is bit 8, not bit 5. So shifting left by any value between 32 and 255 will produce zero, just as you'd expect, but when you reach 256 it suddenly wraps around.

One of the most obscure bits of ARM minutiae I've ever encountered. I have no idea why they designed it like that.
  ^[ Log in to reply ]
 
Christopher Bazley Message #122180, posted by thesnark at 19:17, 29/3/2013, in reply to message #122177
AA refugee
Posts: 11
One of the most obscure bits of ARM minutiae I've ever encountered. I have no idea why they designed it like that.
Undefined behaviour is undefined. Nothing to see here. Move along please.
  ^[ Log in to reply ]
 
Tony Haines Message #122249, posted by Loris at 17:31, 3/4/2013, in reply to message #122177
madbanHa ha, me mine, mwahahahaha
Posts: 1025
I found out not too long ago - while attempting to untangle some code which it emerged was relying on this behaviour - that ARM does indeed have a similar problem with out-of-range shifts to x86. The difference is that the cut-off point is bit 8, not bit 5. So shifting left by any value between 32 and 255 will produce zero, just as you'd expect, but when you reach 256 it suddenly wraps around.

One of the most obscure bits of ARM minutiae I've ever encountered. I have no idea why they designed it like that.
I (vaguely) remember a Usenet discussion on this topic, involving Sophie Wilson and someone else... possibly Wilco?
IIRC Sophie regretted the decision which was made on grounds of expediency. Wilco, however, liked it - since it meant one could store something else at the top of the shift register.
  ^[ Log in to reply ]
 
Jon Abbott Message #122919, posted by sirbod at 13:24, 13/1/2014, in reply to message #114358
Member
Posts: 563
Just spotted these unpredictable instructions in Fire & Ice, I'm not sure which C compiler version it was created under though:

LDMIA a2!, {a1, a2}

I presume the intended instruction is:

LDMIA a2, {a1, a2}


LDR doesn't fair much better, the code is littered with inappropriate write-backs:

LDR a1, [a1], #0

Instead of:

LDR a1, [a1, #0]
  ^[ Log in to reply ]
 
Martin Bazley Message #122920, posted by swirlythingy at 13:46, 13/1/2014, in reply to message #122919

Posts: 460
Just spotted these unpredictable instructions in Fire & Ice, I'm not sure which C compiler version it was created under though:
Pretty sure Fire & Ice is handcrafted assembler. At least I hope no computer would be that stupid.

Do keep an eye out for the unrolled loop in the music player which thinks it's copying sample data:

LDRB R0,[R10],#1
STRB R10,[R9],#1
LDRB R0,[R10],#1
STRB R10,[R9],#1
LDRB R0,[R10],#1
STRB R10,[R9],#1
LDRB R0,[R10],#1
STRB R10,[R9],#1
LDRB R0,[R10],#1
STRB R10,[R9],#1
(...)


Ten points if you can guess what that would sound like, and identify the resulting glitch in the background music during gameplay!
  ^[ Log in to reply ]
 
Jon Abbott Message #122921, posted by sirbod at 14:10, 13/1/2014, in reply to message #122920
Member
Posts: 563
Definitely C (at least I've always assumed the following is associated with C), perhaps with bits of handcrafted assembler. Which C compiler starts code off with the following sequence:

BLNV &00000008
BLNV &0000000C
BLNV &00000010
BL &00000080
SWI OS_Exit


I've yet to get it into the game, so haven't come across that lovely sequence yet...however I was considering adding fixup code when the JIT hits a certain address - you've highlighted that that's actually a good idea.

[Edited by sirbod at 14:12, 13/1/2014]
  ^[ Log in to reply ]
 
Jeffrey Lee Message #122922, posted by Phlamethrower at 16:01, 13/1/2014, in reply to message #122921
PhlamethrowerHot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff

Posts: 15055
That's the sequence old versions of Norcroft (i.e. Acorn C/C++) used to generate as part of the AIF header, before NV condition codes were deprecated.

[Edited by Phlamethrower at 16:03, 13/1/2014]
  ^[ Log in to reply ]
 
Martin Bazley Message #122923, posted by swirlythingy at 16:18, 13/1/2014, in reply to message #122921

Posts: 460
I've yet to get it into the game, so haven't come across that lovely sequence yet...however I was considering adding fixup code when the JIT hits a certain address - you've highlighted that that's actually a good idea.
Fixing that up will quite dramatically alter the background music of the first world, so not quite consistent with ADFFS's 'warts and all' emulation. (I mean, you could just use fixup code to bypass all the copy protection...)
  ^[ Log in to reply ]
 
Jon Abbott Message #122924, posted by sirbod at 17:38, 13/1/2014, in reply to message #122923
Member
Posts: 563
The preservation is "warts and all". There's nothing to stop the Boot script from fixing bugs, several of them already do this. As you've not used ADFFS, I should probably explain that the Boot script is not part of the original floppy image, its in !ADFFS.Obey

If you want "warts and all" games, you simply run the game icon instead of using "Boot floppy" - obviously you're then restricted to it running on the original machines it was intended to support though.
  ^[ Log in to reply ]
 
Andrew Rawnsley Message #122925, posted by arawnsley at 23:12, 13/1/2014, in reply to message #122924
R-Comp chap
Posts: 462
Since you have rights to distribute the game, why not issue a new patch, fixing a few bugs? Then users can choose to run the original or the patched version.
  ^[ Log in to reply ]
 
Martin Bazley Message #122926, posted by swirlythingy at 23:40, 13/1/2014, in reply to message #122925

Posts: 460
What I'd really like is an updated port, designed to run in true colour screen modes so it could do the Amiga's raster bars and draw the map without it flickering all the time.

Although one without broken music would be nice to have as well.
  ^[ Log in to reply ]
 
Jon Abbott Message #122927, posted by sirbod at 00:15, 14/1/2014, in reply to message #122925
Member
Posts: 563
We've gone slightly off topic, however...

Producing a patch would be quite long winded due to the protection used in the game. Once it's running under the ARM3 JIT it's fairly trivial to get the JIT to alter instructions when it touches them.

You can already choose to run original untouched versions of the games by running the game icon. Using "Boot floppy" however kicks off all the layers to get them working on newer systems.

All floppy images released by the project are untouched originals, on an original Acorn you could run most via the icon and not use "Boot floppy" - just be prepared for your BIOS to get trashed and modules unplugged LOL
  ^[ Log in to reply ]
 
Jon Abbott Message #122928, posted by sirbod at 10:11, 14/1/2014, in reply to message #114358
Member
Posts: 563
Getting back on thread...

The following code sequence in RISC OS (all versions above 3.5) frequently causes an abort:

TEQP PC, #&0C000003
STR R14, [R0, -R0]


There should be a NOP between those instructions, as the CPU isn't guaranteed to be in SVC at the time (I think it's in UND). More to the point, it should probably be using MSR.

The offending code would appear to be in the UNDEF macro in middle,v line 843
  ^[ Log in to reply ]
 
Jeffrey Lee Message #122929, posted by Phlamethrower at 12:16, 14/1/2014, in reply to message #122928
PhlamethrowerHot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot Hot stuff

Posts: 15055
There should be a NOP between those instructions, as the CPU isn't guaranteed to be in SVC at the time (I think it's in UND).
Look at s.ARM600; for 26bit versions of the OS the undefined instruction vector (i.e. the actual hardware vector) branches to a pre-veneer which switches the CPU from UND32 to SVC26. Then it calls whatever the installed environment handler is (e.g. the default handler 'UNDEF'). So if you're running into problems with 26bit OS's failing when they fall through to the default handler then that implies that something has directly replaced the hardware vector and the code which switches the OS into SVC26 is being skipped.
  ^[ Log in to reply ]
 
Jon Abbott Message #122930, posted by sirbod at 13:36, 14/1/2014, in reply to message #122929
Member
Posts: 563
Good point, the next time I see it I'll follow the vector and see how the pre-veneer is being bypassed.

EDIT: Now I think about it, I'm seeing the Undefined Vector being called in User CPU mode, so something must be branching to the vectors.

[Edited by sirbod at 14:22, 14/1/2014]
  ^[ Log in to reply ]
 
Xavier Louis Tardy Message #122931, posted by Zarchos at 09:03, 15/1/2014, in reply to message #122926
Member
Posts: 47
Martin : some (partial) good news for you, I hope ... soon.


[Edited by Zarchos at 09:06, 15/1/2014]
  ^[ Log in to reply ]
 
Jon Abbott Message #123021, posted by sirbod at 12:47, 12/2/2014, in reply to message #122931
Member
Posts: 563
Martin : some (partial) good news for you, I hope ... soon.
So...what was the good news?

Found some more compilerisms, this time in Cannon Fodder where every CMP instruction has Rn set to R2:

E1502005 - CMP R0, R5 (Cannon Fodder)
E1500005 - CMP R0, R5 (correct encoding)

I don't know what compiler was used although its not early Norcroft. It's a later version of whatever C compiler Krisalis used at the time going by the prevalent use of STMFD R13!, {PC}/B instead of BL.

Edit: Lotus Turbo Challenge 2 suffers from the same issue

[Edited by sirbod at 21:33, 18/2/2014]
  ^[ Log in to reply ]
 
Xavier Louis Tardy Message #123024, posted by Zarchos at 09:57, 13/2/2014, in reply to message #123021
Member
Posts: 47
Mmmmhhh Jon, the good news will come from Steve, very soon, and please Martin : steady raster bars with line precision ... it'll offer far more than that in fact ;-)
  ^[ Log in to reply ]
 
Jon Abbott Message #123036, posted by sirbod at 17:51, 17/2/2014, in reply to message #123021
Member
Posts: 563
And here's another, in BlowPipe:

E1060240 - TST R6, R0, ASR #4 (BlowPipe)
E1160240 - TST R6, R0, ASR #4 (correct encoding)

It's missing the S bit in BlowPipe.

The C compiler has appended "rcc 3.00" to the end of the file.
  ^[ Log in to reply ]
 
Rob Kendrick Message #123037, posted by nunfetishist at 09:33, 18/2/2014, in reply to message #123036
nunfetishist
Exposing morons since 1981

Posts: 484
The C compiler has appended "rcc 3.00" to the end of the file.
Surely squeeze has appended that. squeeze will happily compress any valid AIF.
  ^[ Log in to reply ]
 

Acorn Arcade forums: Programming: Compilerism of the day