Menu

#2615 compiler wipes out register holding temp in if-else with reserve-regs-iy

closed-fixed
None
Z80
5
2017-05-15
2017-05-14
alvin
No

sdcc -v
9913 MINGW64

The test code:

#define PORT_A_KEY_LEFT    0x0004
#define PORT_A_KEY_RIGHT   0x0008
#define PORT_A_KEY_1       0x0010

unsigned int keystatus;
unsigned char basestage;

void InitPlayerConstants();

void InitSelectorStage()
{
    unsigned char selected_stage=0;
    unsigned char keyfree=1;

    // Bucle
    while(1)
    {
        // Selector left
        if(keystatus&PORT_A_KEY_LEFT)
        {
            if(keyfree==1)
                if(selected_stage>0)
                    selected_stage--;
            keyfree=0;
        }

        // Selector right
        else if(keystatus&PORT_A_KEY_RIGHT)
        {
            if(keyfree==1)
                if(selected_stage<4)
                    selected_stage++;
            keyfree=0;
        }
        // No key
        else keyfree=1;

        // Play?
        if(keystatus&PORT_A_KEY_1)
        {
            basestage=selected_stage;
            InitPlayerConstants();
            return;
        }
    }
}

First correctly generated code with
sdcc -mz80 -S test.c --no-c-code-in-asm --no-peep

The peepholer will improve this code greatly but the no-peep is used so the nature of the code generation problem is clear.

_InitSelectorStage::
    ld  c, #0x00
    ld  b, #0x01
00118$:
    dec b
    jp  NZ,00154$
    ld  a,#0x01
    jp  00155$
00154$:
    xor a,a
00155$:
    ld  iy, #_keystatus
    bit 2, 0 (iy)
    jp  NZ,00156$
    jp  00113$
00156$:
    or  a, a
    jp  Z, 00104$
    ld  a, c
    or  a, a
    jp  Z, 00104$
    dec c
00104$:
    ld  b, #0x00
    jp  00114$
00113$:
    ld  iy, #_keystatus
    bit 3, 0 (iy)
    jp  NZ,00157$
    jp  00110$
00157$:
    or  a, a
    jp  Z, 00108$
    ld  a, c
    sub a, #0x04
    jp  NC, 00108$
    inc c
00108$:
    ld  b, #0x00
    jp  00114$
00110$:
    ld  b, #0x01
00114$:
    ld  iy, #_keystatus
    bit 4, 0 (iy)
    jp  NZ,00158$
    jp  00118$
00158$:
    ld  iy, #_basestage
    ld  0 (iy), c
    call    _InitPlayerConstants
00120$:
    ret

Register A is being set to the boolean value (keyfree == 1) and the test for (keyfree==1) is being pulled ahead of the if..else. IY is being used to test keystatus.

Incorrect code is generated when sdcc is told not to use IY
sdcc -mz80 -S test.c --no-c-code-in-asm --no-peep --reserve-regs-iy

_InitSelectorStage::
    ld  c, #0x00
    ld  b, #0x01
00118$:
    dec b
    jp  NZ,00154$
    ld  a,#0x01
    jp  00155$
00154$:
    xor a,a
00155$:
    ld  hl, #_keystatus
    ld  a, (hl)
    and a, #0x04
    jp  NZ,00156$
    jp  00113$
00156$:
    or  a, a
    jp  Z, 00104$
    ld  a, c
    or  a, a
    jp  Z, 00104$
    dec c
00104$:
    ld  b, #0x00
    jp  00114$
00113$:
    ld  hl, #_keystatus
    ld  a, (hl)
    and a, #0x08
    jp  NZ,00157$
    jp  00110$
00157$:
    or  a, a
    jp  Z, 00108$
    ld  a, c
    sub a, #0x04
    jp  NC, 00108$
    inc c
00108$:
    ld  b, #0x00
    jp  00114$
00110$:
    ld  b, #0x01
00114$:
    ld  hl, #_keystatus
    ld  a, (hl)
    and a, #0x10
    jp  NZ,00158$
    jp  00118$
00158$:
    ld  hl, #_basestage
    ld  (hl), c
    call    _InitPlayerConstants
00120$:
    ret

The peepholer will also improved this code but it is starting with incorrect code. As in the correct case, register A is being set to boolean value (keyfree==1) ahead of the if..else. Because sdcc is not allowed to use IY it goes to using HL directly to access keyfree. However in order to read the byte there it, reads it with regster A, thus wiping out the stored boolean value:

    ld  hl, #_keystatus
    ld  a, (hl)
    and a, #0x04

The peepholer for the correct case without reserve-regs-iy will result in very similar code but register A is not modified:

    ld  hl,#_keystatus+0
    bit 2, (hl)
    jr  Z,00113$

Discussion

  • Philipp Klaus Krause

    • assigned_to: Philipp Klaus Krause
     
  • Philipp Klaus Krause

    • status: open --> closed-fixed
     
  • Philipp Klaus Krause

    Fixed in revision [r9916].

    Philipp

     

Log in to post a comment.