Menu

Can SDCC make garbage-free code for stm8?

Help
Andrew
2018-06-15
2018-08-23
  • Andrew

    Andrew - 2018-06-15

    Hi, I have compiled last SDCC : stm8 3.7.1 #10443 (Linux).
    Here are my a test.c file and makefile.

    test.c :

    #include "stdint.h"
    
    #define PA_ODR *(unsigned char *)(0x5000)
    #define PA_DDR *(unsigned char *)(0x5002)
    #define PA_CR1 *(unsigned char *)(0x5003)
    
    #define pinled 5
    #define pinled_init()   PA_DDR|=pinled;PA_CR1|=pinled
    #define pinled_xor()    PA_ODR^=pinled;
    
    #define TIM4_ISR                25
    
    static void tim4_isr() __interrupt(TIM4_ISR) {
        __asm__("bres 0x5344, #0"); // TIM4_SR &= ~(1 << TIM4_SR_UIF)
    }
    
    static void main() {
        pinled_init();
        pinled_xor();
    }
    

    makefile :

    OBJECTS=test.ihx
    CFLAGS=--nolospre -lstm8 -mstm8 --model-medium
    SDCC=sdcc
    .PHONY: all
    all: $(OBJECTS)
    %.ihx: %.c
        $(SDCC) --out-fmt-ihx $(CFLAGS) $< 
    

    After successful compilation, I was surprised about generated code in test.rst:

    test.rst :

                                          1 ;--------------------------------------------------------
                                          2 ; File Created by SDCC : free open source ANSI-C Compiler
                                          3 ; Version 3.7.1 #10443 (Linux)
                                          4 ;--------------------------------------------------------
                                          5     .module test
                                          6     .optsdcc -mstm8
                                          7     
                                          8 ;--------------------------------------------------------
                                          9 ; Public variables in this module
                                         10 ;--------------------------------------------------------
                                         11 ;--------------------------------------------------------
                                         12 ; ram data
                                         13 ;--------------------------------------------------------
                                         14     .area DATA
                                         15 ;--------------------------------------------------------
                                         16 ; ram data
                                         17 ;--------------------------------------------------------
                                         18     .area INITIALIZED
                                         19 ;--------------------------------------------------------
                                         20 ; Stack segment in internal ram 
                                         21 ;--------------------------------------------------------
                                         22     .area   SSEG
          FFFFFF                         23 __start__stack:
          FFFFFF                         24     .ds 1
                                         25 
                                         26 ;--------------------------------------------------------
                                         27 ; absolute external ram data
                                         28 ;--------------------------------------------------------
                                         29     .area DABS (ABS)
                                         30 ;--------------------------------------------------------
                                         31 ; interrupt vector 
                                         32 ;--------------------------------------------------------
                                         33     .area HOME
          008000                         34 __interrupt_vect:
          008000 82 00 80 73             35     int s_GSINIT ; reset
          008004 82 00 00 00             36     int 0x000000 ; trap
          008008 82 00 00 00             37     int 0x000000 ; int0
          00800C 82 00 00 00             38     int 0x000000 ; int1
          008010 82 00 00 00             39     int 0x000000 ; int2
          008014 82 00 00 00             40     int 0x000000 ; int3
          008018 82 00 00 00             41     int 0x000000 ; int4
          00801C 82 00 00 00             42     int 0x000000 ; int5
          008020 82 00 00 00             43     int 0x000000 ; int6
          008024 82 00 00 00             44     int 0x000000 ; int7
          008028 82 00 00 00             45     int 0x000000 ; int8
          00802C 82 00 00 00             46     int 0x000000 ; int9
          008030 82 00 00 00             47     int 0x000000 ; int10
          008034 82 00 00 00             48     int 0x000000 ; int11
          008038 82 00 00 00             49     int 0x000000 ; int12
          00803C 82 00 00 00             50     int 0x000000 ; int13
          008040 82 00 00 00             51     int 0x000000 ; int14
          008044 82 00 00 00             52     int 0x000000 ; int15
          008048 82 00 00 00             53     int 0x000000 ; int16
          00804C 82 00 00 00             54     int 0x000000 ; int17
          008050 82 00 00 00             55     int 0x000000 ; int18
          008054 82 00 00 00             56     int 0x000000 ; int19
          008058 82 00 00 00             57     int 0x000000 ; int20
          00805C 82 00 00 00             58     int 0x000000 ; int21
          008060 82 00 00 00             59     int 0x000000 ; int22
          008064 82 00 00 00             60     int 0x000000 ; int23
          008068 82 00 00 00             61     int 0x000000 ; int24
          00806C 82 00 80 90             62     int _tim4_isr ; int25
                                         63 ;--------------------------------------------------------
                                         64 ; global & static initialisations
                                         65 ;--------------------------------------------------------
                                         66     .area HOME
                                         67     .area GSINIT
                                         68     .area GSFINAL
                                         69     .area GSINIT
          008073                         70 __sdcc_gs_init_startup:
          008073                         71 __sdcc_init_data:
                                         72 ; stm8_genXINIT() start
          008073 AE 00 00         [ 2]   73     ldw x, #l_DATA
          008076 27 07            [ 1]   74     jreq    00002$
          008078                         75 00001$:
          008078 72 4F 00 00      [ 1]   76     clr (s_DATA - 1, x)
          00807C 5A               [ 2]   77     decw x
          00807D 26 F9            [ 1]   78     jrne    00001$
          00807F                         79 00002$:
          00807F AE 00 00         [ 2]   80     ldw x, #l_INITIALIZER
          008082 27 09            [ 1]   81     jreq    00004$
          008084                         82 00003$:
          008084 D6 80 B1         [ 1]   83     ld  a, (s_INITIALIZER - 1, x)
          008087 D7 00 00         [ 1]   84     ld  (s_INITIALIZED - 1, x), a
          00808A 5A               [ 2]   85     decw    x
          00808B 26 F7            [ 1]   86     jrne    00003$
          00808D                         87 00004$:
                                         88 ; stm8_genXINIT() end
                                         89     .area GSFINAL
          00808D CC 80 70         [ 2]   90     jp  __sdcc_program_startup
                                         91 ;--------------------------------------------------------
                                         92 ; Home
                                         93 ;--------------------------------------------------------
                                         94     .area HOME
                                         95     .area HOME
          008070                         96 __sdcc_program_startup:
          008070 CC 80 97         [ 2]   97     jp  _main
                                         98 ;   return from main will return to caller
                                         99 ;--------------------------------------------------------
                                        100 ; code
                                        101 ;--------------------------------------------------------
                                        102     .area CODE
                                        103 ;   test.c: 14: static void tim4_isr() __interrupt(TIM4_ISR) {
                                        104 ;   -----------------------------------------
                                        105 ;    function tim4_isr
                                        106 ;   -----------------------------------------
          008090                        107 _tim4_isr:
          008090 4F               [ 1]  108     clr a
          008091 62               [ 2]  109     div x, a
                                        110 ;   test.c: 15: __asm__("bres 0x5344, #0"); // TIM4_SR &= ~(1 << TIM4_SR_UIF)
          008092 72 11 53 44      [ 1]  111     bres    0x5344, #0
                                        112 ;   test.c: 16: }
          008096 80               [11]  113     iret
                                        114 ;   test.c: 18: static void main() {
                                        115 ;   -----------------------------------------
                                        116 ;    function main
                                        117 ;   -----------------------------------------
          008097                        118 _main:
                                        119 ;   test.c: 19: pinled_init();
          008097 C6 50 02         [ 1]  120     ld  a, 0x5002
          00809A AA 05            [ 1]  121     or  a, #0x05
          00809C C7 50 02         [ 1]  122     ld  0x5002, a
          00809F C6 50 03         [ 1]  123     ld  a, 0x5003
          0080A2 AA 05            [ 1]  124     or  a, #0x05
          0080A4 C7 50 03         [ 1]  125     ld  0x5003, a
                                        126 ;   test.c: 20: pinled_xor();
          0080A7 C6 50 00         [ 1]  127     ld  a, 0x5000
          0080AA A8 05            [ 1]  128     xor a, #0x05
          0080AC 88               [ 1]  129     push    a
          0080AD 84               [ 1]  130     pop a
          0080AE C7 50 00         [ 1]  131     ld  0x5000, a
                                        132 ;   test.c: 21: }
          0080B1 81               [ 4]  133     ret
                                        134     .area CODE
                                        135     .area CONST
                                        136     .area INITIALIZER
                                        137     .area CABS (ABS)
    

    So, there are two pieces of garbage:

          008090                        107 _tim4_isr:
          008090 4F               [ 1]  108     clr a
          008091 62               [ 2]  109     div x, a
    

    and

          0080AC 88               [ 1]  129     push    a
          0080AD 84               [ 1]  130     pop a
    

    What I have to do to get garbage-free code?
    Thanks.

     

    Last edit: Andrew 2018-06-15
  • Philipp Klaus Krause

    The

    clr a
    div x, a
    

    is generated since SDCC cannot prove that your ISR contains no div/divw (when the ISR contains divisions, certain right shifts, inline asm or calls to functions not defined before the ISR, SDCC cannot prove that the ISR does not contain div/divw. In case the ISR contains divisision, these two instructions are a workaround for a hardware bug ("Unexpected DIV/DIVW instruction result in ISR" in the STM8 errata).

    You could declare ISRs that contain inline assembly, but no division as __naked, so SDCC omits the function prologue and epilogue (the iret then needs to be in the inline asm).

    Philipp

     

    Last edit: Philipp Klaus Krause 2018-06-15
    • Andrew

      Andrew - 2018-06-15

      "Unexpected DIV/DIVW instruction result in ISR" in the STM8 errata

      Thank you very much! Now, will try to search errata before asking.

      And what is about piece with push a and pop a ?

      P.S.

      I have read a method to loose unused code for pic14 from [https://sourceforge.net/p/sdcc/mailman/message/34776699/].
      Then I've tried to modify stm8 .asm files and added .area f_N before each function.
      I've got no errors about such approach.
      But there are no command-line options for sdldstm8 to optimize (loose) unused functions.
      So, I've got another idea.
      Maybe someone can modify aslink and add command-line option and some code from sdar to produce .lib instead of .rel?
      At last, linker sdldstm8 will get just some functions from .lib files , but not all functions from .rel files.
      Do you know about such discussions here?

      Now, I've found a cutting .c file perl script of B.Schwander.
      After some modifications, the script cuts all .c files in a directory and makes one .h file and many .c files each with one function inside. The script also makes .lib.
      Where can I put such temporary decision to loose unused functions?
      Or simply have to make a post here?
      Thanks.

       

      Last edit: Andrew 2018-06-15
      • David Gould

        David Gould - 2018-08-23

        I've found a cutting .c file perl script of B.Schwander.
        After some modifications, the script cuts all .c files in a directory and makes
        one .h file and many .c files each with one function inside. The script also makes .lib.

        I would like to have a copy of your version of B.Schwanders perl script. Please post it somewhere, or you can email it via david-gould@users.sourceforge.net. Thanks!

         
  • Philipp Klaus Krause

    The

    push a
    pop a
    

    was just a minor inefficiency in code generation. As of [r10448], it is no longer generated (code generation for ^ is now more similar to | in handling a).

    Philipp

     

Log in to post a comment.