Topic : Bad peephole optimization code

Forum : ST7/STM8

Original Post
Post Information Post
May 15, 2012 - 11:46pm
Guest

I just cranked up the optimizer to level 3 in Ride7 for the STM8L151C8 mcu, and it is generating bad code. In particular, after I call a function, the function pushes 3 bytes of data to the stack, but when the function returns it puts the stack pointer forward 5 bytes - not 3. Therefore, when RETF is executed, an invalid address is loaded and the processor crashes.

Is there something special I have to do to get optimization level 3 to work?

Replies
Post Information Post
+1
0
-1
May 16, 2012 - 6:21pm
Guest

I don't think this is a Ride7 issue, so I'm not sure why the post was moved. :) I assume the problem is with the STM8 compiler - not the IDE.

To illustrate my point, here is the listing of the function that has bad code:

; FUNCTION ?tcbDequeuePriority (BEGIN)
; Register-parameter tcb_queue_ptr (XW) is relocated (auto)
; Register-parameter priority (A) is relocated (auto)
; SOURCE LINE # 997
0000 88 PUSH A
0001 89 PUSHW X
; SOURCE LINE # 1002
0002 1E04 F LDW X,(004H,SP) ; [ tcb_queue_ptr ]
0004 2605 JRNE ?ELSE_0056
; SOURCE LINE # 1005
0006 5F CLRW X
0007 1F01 F LDW (001H,SP),X ; [ ret_ptr ]
0009 2027 JRA ?NXT_0062
000B ?ELSE_0056:
; SOURCE LINE # 1008
000B FE LDW X,(X)
000C 2605 JRNE ?ELSE_0057
000E ?EASY_0002?tcbDequeuePriority:
; SOURCE LINE # 1011
000E 5F CLRW X
000F 1F01 F LDW (001H,SP),X ; [ ret_ptr ]
0011 201F JRA ?NXT_0062
0013 ?ELSE_0057:
; SOURCE LINE # 1014
0013 1E04 F LDW X,(004H,SP) ; [ tcb_queue_ptr ]
0015 FE LDW X,(X)
0016 7B03 F LD A,(003H,SP) ; [ priority ]
0018 E102 CP A,(002H,X)
001A 25F2 JRULT ?EASY_0002?tcbDequeuePriority
; SOURCE LINE # 1017
001C 1F01 F LDW (001H,SP),X ; [ ret_ptr ]
; SOURCE LINE # 1018
001E EE0C LDW X,(00CH,X)
0020 51 EXGW X,Y
0021 1E04 F LDW X,(004H,SP) ; [ tcb_queue_ptr ]
0023 FF LDW (X),Y
; SOURCE LINE # 1019
0024 FE LDW X,(X)
0025 270B JREQ ?NXT_0062
; SOURCE LINE # 1021
0027 1E04 F LDW X,(004H,SP) ; [ tcb_queue_ptr ]
0029 FE LDW X,(X)
002A 905F CLRW Y
002C EF0A LDW (00AH,X),Y
; SOURCE LINE # 1022
002E 1E01 F LDW X,(001H,SP) ; [ ret_ptr ]
0030 EF0C LDW (00CH,X),Y
0032 ?NXT_0062:
; SOURCE LINE # 1031
0032 1E01 F LDW X,(001H,SP) ; [ ret_ptr ]
; SOURCE LINE # 1032
0034 5B05 ADD SP,#005H
0036 87 RETF

As you can see, at the beginning of the function we push A and X (total of 3 bytes), but before we return we pop 5 bytes - thus putting the stack pointer in the wrong position for the return address.

I'm not sure this is the only place with this issue, but it is the first one I hit.

I really need this optimizer to work, because I am out of memory. Help!

+1
0
-1
May 16, 2012 - 6:26pm
Guest

I'm not sure if you want the C code for the function in question or not, so here it is on a separate post.

ATOM_TCB *tcbDequeuePriority (ATOM_TCB **tcb_queue_ptr, uint8_t priority)
{
ATOM_TCB *ret_ptr;

/* Parameter check */
if (tcb_queue_ptr == NULL)
{
/* Return NULL */
ret_ptr = NULL;
}
/* Check for an empty queue */
else if (*tcb_queue_ptr == NULL)
{
/* Return NULL */
ret_ptr = NULL;
}
/* Check if the list head priority is within our range */
else if ((*tcb_queue_ptr)->priority <= priority)
{
/* Remove the list head */
ret_ptr = *tcb_queue_ptr;
*tcb_queue_ptr = (*tcb_queue_ptr)->next_tcb;
if (*tcb_queue_ptr)
{
(*tcb_queue_ptr)->prev_tcb = NULL;
ret_ptr->next_tcb = NULL;
}
}
else
{
/* No higher priority ready threads found */
ret_ptr = NULL;
}

return (ret_ptr);
}

The structure ATOM_TCB is as follows:

typedef struct atom_tcb
{
/* Thread's current stack pointer. When a thread is scheduled
* out the architecture port can save*/
POINTER sp_save_ptr;

/* Thread priority (0-255) */
uint8_t priority;

/* Thread entry point and parameter */
void (*entry_point)(uint32_t);
uint32_t entry_param;

/* Queue pointers */
struct atom_tcb *prev_tcb; /* Previous TCB in doubly-linked TCB list */
struct atom_tcb *next_tcb; /* Next TCB in doubly-linked list */

/* Suspension data */
uint8_t suspended; /* TRUE if task is currently suspended */
uint8_t suspend_wake_status; /* Status returned to woken suspend calls */
ATOM_TIMER *suspend_timo_cb; /* Callback registered for suspension timeouts */

/* Details used if thread stack-checking is required */
#ifdef ATOM_STACK_CHECKING
POINTER stack_top; /* Pointer to top of stack allocation */
uint32_t stack_size; /* Size of stack allocation in bytes */
#endif

} ATOM_TCB;

+1
0
-1
May 22, 2012 - 12:50pm
Guest

I have a very similar problem with peephole optimisation.

In my case it seems to have lost the PUSH X and so tries to use the return address instead of the passed parameter (pointer).

int getline_noblock(char * buff, unsigned char maxlen)
{
    char * ptr;
    int c;
    
    ptr = buff;
...

produces this

              ; FUNCTION ?getline_noblock (BEGIN)
              ; Register-parameter buff (XW) is relocated (auto)
              ; Register-parameter maxlen (A) is relocated (auto)
              ; SOURCE LINE # 112 
0000 88                                PUSH   A
0001 5204                              SUB    SP,#004H
              ; SOURCE LINE # 117 
0003 1E06       F                      LDW    X,(006H,SP)   ; [ buff ]
0005 1F01       F                      LDW    (001H,SP),X   ; [ ptr ]
...

This significant line is at offset 0003 which is expecting buff (passed in X) to be on the stack. It should be reading buff, but actually reads the return address. This cause a crash later in the routine when it uses ptr for writing.

RCSTM8 COMPILER V2.40.11.327

+1
0
-1
August 7, 2012 - 12:14pm
Guest

I had a very similar problem.

In my case the problem was caused by calling a function with a pointer to a structure.
An extra byte was pushed onto the stack and then not popped before the function return.
I solved it by passing a pointer to a void and casting it to a pointer to the required structure.

Not very nice but I only had a few such functions so not a big problem for me at the moment.

+1
0
-1
August 7, 2012 - 1:49pm
Raisonance Support Team

The RKit-STM8 2.44.12.0199 available at the Raisonance Download Center fixes all this issues.

Stéphane