English Amiga Board

English Amiga Board (https://eab.abime.net/index.php)
-   Coders. C/C++ (https://eab.abime.net/forumdisplay.php?f=118)
-   -   VBCC code generation (https://eab.abime.net/showthread.php?t=73895)

Asman 30 May 2014 09:22

VBCC code generation
 
Hi

For following code
Code:

define CIAADDR (UBYTE*)(0xbfe001)
UBYTE fire(void)
{
    return (!(*CIAADDR & 128));
}

vbcc generate following asm
Code:

        near        code
        near        a4,-2
        opt        0
        opt        NQLPSMRBT
        public        _fire
        cnop        0,4
_fire
        movem.l        l485,-(a7)
        moveq        #0,d0
        move.b        12574721,d0
        and.l        #128,d0
        bne        l38
        moveq        #1,d1
        bra        l39
l38
        moveq        #0,d1
l39
        move.b        d1,d0
l485        reg
l487        equ        0
        rts

Main question is: Is there possibility to generate better code for the above routine ? I mean about some magic switch or something in vbcc. I used following options: -S -O3 -c99 -sd -sc to generate above asm code.

I don't understand why and.l is used, I think that better will be and.b in this case. Is there a way to change this and.l --> and.b and then remove first moveq #0,d0 ?

Funny things happen when I'm trying to use __reg for same routine
Code:

    __reg("d1") UBYTE r = (!(*CIAADDR & (128)));

    return r;

then vbcc generated

Code:

        near        code
        near        a4,-2
        opt        0
        opt        NQLPSMRBT
        public        _fire
        cnop        0,4
_fire
        movem.l        l485,-(a7)
        moveq        #0,d0
        move.b        12574721,d0
        and.l        #128,d0
        bne        l38
        moveq        #1,d2
        bra        l39
l38
        moveq        #0,d2
l39
        move.b        d2,d0
l485        reg        d2
        movem.l        (a7)+,d2
l487        equ        4
        rts

And who eat my d1 register ? :)

Any comments and explanation are welcome.

Samurai_Crow 30 May 2014 16:06

Why did it do AND.L? Because you specifically (though implicitly) asked it to. The default type of an integer is int, which in turn is 32-bits. If you want 128 to represent an unsigned char value, try changing the notation of 128 to 128UC or '\0x80' using single quotes (just typing this from memory, I hope that's right). I know that on SAS/C when you wanted a long constant value instead of a 16-bit int, you had two options: Hit a switch on the compiler that defined all ints as 32 bits instead of 16, or put a capital L after your constant to indicate its type. Another way would be to cast the 128 to UBYTE, which should inline the conversion using constant folding.

*edit*
As another suggestion, try #include <stdbool.h> at the beginning of your code so you can return a bool value and cast that to a UBYTE. It might be able to optimize the branches to a SNE D0 and an AND.B #1, D0 eliminating the need for D1 altogether though it might not do this if you're not optimizing for an '060. Like this:
Code:

#include <stdbool.h>

/* definition of CIAADDR */

UBYTE fire() {
  return (*CIAADDR&(UBYTE)128==(UBYTE)128)&(UBYTE)1;
}


Asman 31 May 2014 09:36

Thanks for answer Samurai Crow. But ... vbcc do not like your suggestion :)
I even tried with (to check if add.b will be generated)
Code:

        UBYTE c = 128;
        UBYTE r = *CIAADDR;

        return c & r;

and vbcc generate

Code:

        near        code
        near        a4,-2
        opt        0
        opt        NQLPSMRBT
        public        _fire
        cnop        0,4
_fire
        movem.l        l478,-(a7)
        move.b        12574721,d0
        and.l        #255,d0
        and.l        #128,d0
l478        reg
l480        equ        0
        rts

About stdbool.h, as I checked then I don't have such file in includes.

So it not big deal this and.l but I thought that is possible to optimize a bit generated output.

Edit:
There is always another way: back to pure asm :)

alkis 15 August 2014 12:04

Hmm, old thread, but look at the gcc output

-m68000
Code:

_fire:
        moveb 12574721,d0
        extw d0
        extl d0
        notl d0
        addl d0,d0
        subxl d0,d0
        negl d0
        rts

and for >=68020
Code:

_fire:
        moveb 12574721,d0
        eorw #128,d0
        bfextu d0{#24:#1},d0
        rts

Now, I can't say I can follow the logic on the 68000 output, but the >=020 part is sort of cool ;-)

matthey 15 August 2014 13:12

Quote:

Originally Posted by alkis (Post 969839)
Code:

_fire:
        moveb 12574721,d0
        eorw #128,d0
        bfextu d0{#24:#1},d0
        rts

Now, I can't say I can follow the logic on the 68000 output, but the >=020 part is sort of cool ;-)

It may be cool but it's not that great. It did really good combining the !& into xor but then it failed when it used the BFEXTU instruction. The best savings would come from inlining the function though.

Don_Adan 15 August 2014 13:34

Code:


_fire:
        moveb 12574721,d0
        add.b d0,d0
        subx.l d0,d0
        addq.l #1,d0
        rts


phx 15 August 2014 13:56

Quote:

Originally Posted by Asman (Post 957207)
[/code]About stdbool.h, as I checked then I don't have such file in includes.

That's a C99 feature still missing in V0.9b. Will be part of V0.9d.

Quote:

So it not big deal this and.l but I thought that is possible to optimize a bit generated output.
The code generator likes to work with 32 bits on a 32-bit CPU. I guess this is because the propability that all 32 bits of an operation are needed later is quite big.

Quote:

There is always another way: back to pure asm :)
Or do it like this:
Code:

UBYTE asmfire(void)="\tbtst\t#7,$bfe001\n\tsne\td0";

UBYTE fire() {
  return asmfire();
}


Thorham 15 August 2014 16:57

Quote:

Originally Posted by Asman (Post 957207)
There is always another way: back to pure asm :)

Indeed. On 68k machines it may not be such a bad idea to use assembly language, and besides, it's fun :D

Side note: Those C compilers sure write good code :rolleyes

alkis 16 August 2014 11:48

...And from gcc 4.6.4 (atari-mint target)

Code:

_fire:
        move.b 12574721,%d0
        not.b %d0
        lsr.b #7,%d0
        rts


matthey 17 August 2014 09:33

Quote:

Originally Posted by alkis (Post 970037)
...And from gcc 4.6.4 (atari-mint target)

Code:

_fire:
        move.b 12574721,%d0
        not.b %d0
        lsr.b #7,%d0
        rts


Looks good. Maybe the rumors of GCC improving again are true. Makes me want to adapt the compiler to use vasm or add some kind of a system to convert elf 68k to Amiga hunk.


All times are GMT +2. The time now is 10:55.

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.

Page generated in 0.04551 seconds with 11 queries