Peephole issues (deadmove)

Help
afgncaap
2009-01-09
2013-03-12
  • afgncaap
    afgncaap
    2009-01-09

    So, sorry if this has already been answered somewhere, I can't seem to see anything:

    I have been working on a context swap, and it seems that sdcc, even with model large used, uses the local stack for the address of the return function.  Because I am swapping, this is trashed, so I have been using the peephole to replace LCALL/RET with LJMP.  I think that code should now work as intended, but now, when I try to compile, I get the error:

    sdcc  --peep-file ../../src/kernel/hal/cc243X/peep.c --stack-auto --xstack --mod
    el-large -L "C:\Program Files\SDCC\lib\large-stack-auto-xstack" -I. -mmcs51 --xr
    am-loc 0xE000 -D NANORK -D __SDCC__ -D NODE_ADDR=0 -I . -I../../src/platform/inc
    lude -I../../src/platform/cc243X/include -I../../src/radio/cc243X/include -I../.
    ./src/radio/cc243X/hal/cc243X -I../../src/radio/cc243X/platform/cc243X -I../../s
    rc/drivers/include -I../../src/drivers/platform/cc243X/include -I../../src/kerne
    l/include -I../../src/kernel/hal/include --std-sdcc89  --debug  -c  ../../src/ke
    rnel/source/nrk.c -o ../../src/kernel/source/nrk.rel

    ...

    ../../src/kernel/source/nrk.c:212: error 9: FATAL Compiler Internal Error in fil
    e '/home/sdcc-builder/build/sdcc-build/orig/sdcc/src/mcs51/peep.c' line number '
    180' : error in deadmove
    Contact Author with source code

    where peep.c is my peephole file.  If I compile with the peep.c empty, there is no error.  If I compile with the function in nrk.c removed, I just get an error 9 somewhere else.
    What is "deadmove," and why is the my peephole file and the .c file interacting in the first place?  Am I going about this whole thing wrong?

    Compiled with version SDCC : mcs51/gbz80/z80/avr/ds390/pic16/pic14/TININative/xa51/ds400/hc08 2.8.4 #5242 (Sep 22 2008) (MINGW32)

    files peep.c and nrk.c below:

    peep.c_____________________________________________________________
    replace {
        lcall %1
    } by {
        push acc
        mov r0, _spx
        mov a,pcl
        add a,#0x15
        movx @r0,a
        inc r0
        mov a,pch
        movx @r0,a
        inc r0
        mov _spx, r0
        pop acc
        ljmp %1
    }

    replace {
        reti
    }by{
        ri
    }
    replace {
        ret
    } by {
        xch a,r1
        mov r0, _spx
       
        dec r0
        movx a,@r0
        push acc
        dec r0
        movx a,@r0
        push acc
        xch a,r1
        rrt
    }

    replace {
        rrt
    } by {
        ret
    }

    replace {
        ri
    } by {
        reti
    }

    replace {
        sjmp %1
    } by {
        ljmp %1
    }

    replace {
        jz %1
    } by {
        jnnz (pc+3)
        ljmp %1
    }

    replace {
        jnnz (pc+3)
        ljmp %5
    } by {
        jz %5
    } if labelInRange

    replace {
        jnz %1
    } by {
        jz (pc+3)
        ljmp %1
    }

    replace {
        jz (pc+3)
        ljmp %5
    } by {
        jnz %5
    } if labelInRange

    replace {
        jnnz (pc+3)
    } by {
        jnz (pc+3)
    }

    replace {
        jc %1
    } by {
        jnnc (pc+3)
        ljmp %1
    }

    replace {
        jnnc (pc+3)
        ljmp %5
    } by {
        jc %5
    } if labelInRange

    replace {
        jnc %1
    } by {
        jc (pc+3)
        ljmp %1
    }

    replace {
        jc (pc+3)
        ljmp %5
    } by {
        jnc %5
    } if labelInRange

    replace {
        jnnc (pc+3)
    } by {
        jnc (pc+3)
    }

    replace {
        jb %1,%2
    } by {
        jnnb %1,(pc+3)
        ljmp %2
    }

    replace {
        jnnb %1,(pc+3)
        ljmp %5
    } by {
        jb %1,%5
    } if labelInRange   

    replace {
        jnb %1,%2
    } by {
        jb %1,(pc+3)
        ljmp %2
    }

    replace {
        jb %1,(pc+3)
        ljmp %5
    } by {
        jnb %1,%5
    } if labelInRange

    replace {
        jnnb %1,(pc+3)
    } by {
        jnb %1,(pc+3)
    }

    replace {
        cjne a,%2,%3
    } by {
        subb a,%2
        jz (pc+3)
        ljmp %3
    }

    replace {
        cjne %1,%2,%3
    } by {
        mov a,%1
        subb a,%2
        jz (pc+3)
        ljmp %3
    }

    replace {
        ljmp %5
    } by {
        sjmp %5
    } if labelInRange

    ____________________________________________

    nrk.c________________________________________
    /******************************************************************************
    *  Nano-RK, a real-time operating system for sensor networks.
    *  Copyright (C) 2007, Real-Time and Multimedia Lab, Carnegie Mellon University
    *  All rights reserved.
    *
    *  This is the Open Source Version of Nano-RK included as part of a Dual
    *  Licensing Model. If you are unsure which license to use please refer to:
    http://www.nanork.org/nano-RK/wiki/Licensing
    *
    *  This program is free software: you can redistribute it and/or modify
    *  it under the terms of the GNU General Public License as published by
    *  the Free Software Foundation, version 2.0 of the License.
    *
    *  This program is distributed in the hope that it will be useful,
    *  but WITHOUT ANY WARRANTY; without even the implied warranty of
    *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    *  GNU General Public License for more details.
    *
    *  You should have received a copy of the GNU General Public License
    *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
    *
    *  Contributing Authors (specific to this file):
    *  Anthony Rowe
    *  Zane Starr
    *  Anand Eswaren
    *******************************************************************************/

    #include <stdio.h>
    #include <nrk_includes.h>
    #include <ulib.h>
    #include <nrk.h>
    #include <nrk_task.h>
    #include <nrk_idle_task.h>
    #include <nrk_defs.h>
    #include <nrk_cpu.h>
    #include <nrk_scheduler.h>
    #include <nrk_error.h>
    #include <nrk_events.h>
    #include <nrk_stack_check.h>
    #include <nrk_status.h>
    #include <nrk_watchdog.h>
    #include <nrk_reserve.h>
    #include <nrk_cfg.h>
    #include <nrk_stats.h>

    #ifdef __SDCC__
    void nrk_int_disable(void) {
      DISABLE_GLOBAL_INT();
    }

    void nrk_int_enable(void) {
      ENABLE_GLOBAL_INT();
    }
    #else

    inline void nrk_int_disable(void) {
      DISABLE_GLOBAL_INT();
    };

    inline void nrk_int_enable(void) {
      ENABLE_GLOBAL_INT();
    };
    #endif

    uint8_t nrk_task_init_cnt;

    NRK_STK *nrk_kernel_stk_ptr;

    NRK_TCB    nrk_task_TCB[NRK_MAX_TASKS];

    NRK_STK    nrk_idle_task_stk[NRK_TASK_IDLE_STK_SIZE];  /* Idle task stack   */
    #ifdef KERNEL_STK_ARRAY
        NRK_STK nrk_kernel_stk[NRK_KERNEL_STACKSIZE];
    #endif

    void nrk_halt()
    {
    nrk_int_disable();
    while(1);
    }

    /**
    *  nrk_init();
    * *  - Init TCBlist - linked list of empty TCBs
    *  - Init global variables
    *  - Init event list
    *  - Create idle task
    */
    void nrk_init()
    {
       
        uint8_t i;   
    //    unsigned char *stkc;
       nrk_task_type IdleTask;
       printf("Start init: %u\r\n",nrk_task_init_cnt);
       nrk_wakeup_signal = nrk_signal_create();
       if(nrk_wakeup_signal==NRK_ERROR) nrk_kernel_error_add(NRK_SIGNAL_CREATE_ERROR,0);
       
       //if((volatile)TCCR1B!=0) nrk_kernel_error_add(NRK_STACK_OVERFLOW,0);
       if(_nrk_startup_ok()==0) nrk_kernel_error_add(NRK_BAD_STARTUP,0);
       #ifdef NRK_STARTUP_VOLTAGE_CHECK
           if(nrk_voltage_status()==0) nrk_kernel_error_add(NRK_LOW_VOLTAGE,0);
       #endif

       #ifdef NRK_REBOOT_ON_ERROR
       #ifndef NRK_WATCHDOG
       while(1)
           {
            nrk_kprintf( PSTR("KERNEL CONFIG CONFLICT:  NRK_REBOOT_ON_ERROR needs watchdog!\r\n") );
                for (i = 0; i < 100; i++)
                      nrk_spin_wait_us (1000);
           }
       #endif
       #endif

        #ifdef NRK_WATCHDOG
        if(nrk_watchdog_check()==NRK_ERROR)
        {
            nrk_watchdog_disable();
        nrk_kernel_error_add(NRK_WATCHDOG_ERROR,0);
        }
        nrk_watchdog_enable();
        #endif
     
        nrk_stack_pointer_init();
    /*
        #ifdef KERNEL_STK_ARRAY
        stkc = (uint16_t*)&nrk_kernel_stk[NRK_KERNEL_STACKSIZE-1];
        nrk_kernel_stk[0]=STK_CANARY_VAL;
            nrk_kernel_stk_ptr = &nrk_kernel_stk[NRK_KERNEL_STACKSIZE-1];
        #else
            stkc = NRK_KERNEL_STK_TOP-NRK_KERNEL_STACKSIZE;
            *stkc = STK_CANARY_VAL;
            stkc = NRK_KERNEL_STK_TOP;
        nrk_kernel_stk_ptr = NRK_KERNEL_STK_TOP;
        #endif
        *stkc++ = (uint16_t)((uint16_t)_nrk_timer_tick>>8);
        *stkc = (uint16_t)((uint16_t)_nrk_timer_tick&0xFF);
    */   

       // printf( "Init kernel_entry= %d %d\n",kernel_entry[1], kernel_entry[0] );

        printf("mid init: %u\r\n",nrk_task_init_cnt);
        nrk_cur_task_prio = 0;
        nrk_cur_task_TCB = NULL;
       
        nrk_high_ready_TCB = NULL;
        nrk_high_ready_prio = 0;

       #ifdef NRK_STATS_TRACKER
        nrk_stats_reset();
       #endif

        #ifdef NRK_MAX_RESERVES
        // Setup the reserve structures
        _nrk_reserve_init();
        #endif

        _nrk_resource_cnt = NRK_MAX_RESOURCE_CNT;

    for(i=0;i<NRK_MAX_RESOURCE_CNT;i++)
    {
        nrk_sem_list[i].count=-1;
        nrk_sem_list[i].value=-1;
        nrk_sem_list[i].resource_ceiling=-1;
        //nrk_resource_count[i]=-1;
        //nrk_resource_value[i]=-1;
        //nrk_resource_ceiling[i]=-1;
       
    }       
        for (i= 0; i<NRK_MAX_TASKS; i++)
        {
            nrk_task_TCB[i].task_prio = TCB_EMPTY_PRIO;
            nrk_task_TCB[i].task_ID = -1;
            }
     
          
        // Setup a double linked list of Ready Tasks
        for (i=0;i<NRK_MAX_TASKS;i++)
        {
            _nrk_readyQ[i].Next    =    &_nrk_readyQ[i+1];
            _nrk_readyQ[i+1].Prev    =    &_nrk_readyQ[i];
        }
       
        _nrk_readyQ[0].Prev    =    NULL;
        _nrk_readyQ[NRK_MAX_TASKS].Next    =    NULL;
        _head_node = NULL;
        _free_node = &_nrk_readyQ[0];
       
       
       
            // SDCC can not do cast
        nrk_task_set_entry_function( &IdleTask,(void *) nrk_idle_task);
        nrk_task_set_stk( &IdleTask, nrk_idle_task_stk, NRK_TASK_IDLE_STK_SIZE);
        nrk_idle_task_stk[0]=STK_CANARY_VAL;   
        //IdleTask.task_ID = NRK_IDLE_TASK_ID;
        IdleTask.prio = 0;
        IdleTask.offset.secs = 0;
        IdleTask.offset.nano_secs = 0;
        IdleTask.FirstActivation = TRUE;
        IdleTask.Type = IDLE_TASK;
        IdleTask.SchType = PREEMPTIVE;
        nrk_activate_task(&IdleTask);
       
    }

    uint8_t*  stkptr;

    void nrk_start (void)
    {
        int8_t task_ID;
        uint8_t i,j;
    //    NRK_STK *x;
    //    unsigned char *stkc;
        NRK_TCB    *new_nrk_TCB;

        /*
            - Get highest priority task from rdy list
            - set cur prio and start the task
        */
        // Check to make sure all tasks unique

    //    dump_stack_info();
        task_ID = nrk_get_high_ready_task_ID();   
        nrk_high_ready_prio = nrk_task_TCB[task_ID].task_prio;
        nrk_high_ready_TCB = nrk_cur_task_TCB = &nrk_task_TCB[task_ID]; 
        //new_nrk_high_ready_TCB =  nrk_task_TCB[task_ID];
        //printf("new_nrk_high_ready_TCB %x",new_nrk_high_ready_TCB);
        printf("Task %u, Ready= %u, Cur= %u,TCB= %x\r\n",task_ID,nrk_high_ready_prio,nrk_cur_task_prio,(uint16_t)nrk_high_ready_TCB);   
        nrk_cur_task_prio = nrk_high_ready_prio;

        nrk_print_readyQ();
    //    nrk_stack_pointer_restore();

        /*
        #ifdef KERNEL_STK_ARRAY
             stkc = (uint16_t*)&nrk_kernel_stk[NRK_KERNEL_STACKSIZE-1];
        #else
            stkc = NRK_KERNEL_STK_TOP;
        #endif
        *stkc++ = (uint16_t)((uint16_t)_nrk_timer_tick>>8);
        *stkc = (uint16_t)((uint16_t)_nrk_timer_tick&0xFF);
       
        //TODO: this way on msp
        // *stkc++ = (uint16_t)((uint16_t)_nrk_timer_tick&0xFF);
        // *stkc = (uint16_t)((uint16_t)_nrk_timer_tick>>8);
    */
    //    nrk_target_start();

    _asm
        mov _stkptr,sp
    _endasm;

        nrk_stack_pointer_init();
    printf("1st %X %X\r\n",(uint16_t) nrk_high_ready_TCB,(*((xdata uint16_t*) nrk_high_ready_TCB)));
    nrk_kprintf("XStack\r\n");
    printf("%X\r\n",(*((xdata uint8_t*)(*((xdata uint16_t*) nrk_high_ready_TCB)+2))));
    printf("%X\r\n",(*((xdata uint8_t*)(*((xdata uint16_t*) nrk_high_ready_TCB)+1))));
    printf("%X\r\n",(*((xdata uint8_t*)(*((xdata uint16_t*) nrk_high_ready_TCB)))));
    printf("%X\r\n",(*((xdata uint8_t*)(*((xdata uint16_t*) nrk_high_ready_TCB)-1))));
    printf("%X\r\n",(*((xdata uint8_t*)(*((xdata uint16_t*) nrk_high_ready_TCB)-2))));
    printf("%X\r\n",(*((xdata uint8_t*)(*((xdata uint16_t*) nrk_high_ready_TCB)-3))));
    printf("%X\r\n",(*((xdata uint8_t*)(*((xdata uint16_t*) nrk_high_ready_TCB)-4))));
    printf("%X\r\n",(*((xdata uint8_t*)(*((xdata uint16_t*) nrk_high_ready_TCB)-5))));
    printf("%X\r\n",(*((xdata uint8_t*)(*((xdata uint16_t*) nrk_high_ready_TCB)-6))));
    printf("%X\r\n",(*((xdata uint8_t*)(*((xdata uint16_t*) nrk_high_ready_TCB)-7))));
    printf("%X\r\n",(*((xdata uint8_t*)(*((xdata uint16_t*) nrk_high_ready_TCB)-8))));
    nrk_kprintf("Stack\r\n");
    printf("%X\r\n",(*(stkptr+2)));
    printf("%X\r\n",(*(stkptr+1)));
    printf("%X\r\n",(*(stkptr)));
    printf("%X\r\n",(*(stkptr-1)));
    printf("%X\r\n",(*(stkptr-2)));
    printf("%X\r\n",(*(stkptr-3)));
    printf("%X\r\n",(*(stkptr-4)));
    printf("%X\r\n",(*(stkptr-5)));
    printf("%X\r\n",(*(stkptr-6)));
    printf("%X\r\n",(*(stkptr-7)));
    printf("%X\r\n",(*(stkptr-8)));
        nrk_target_start();
        nrk_start_high_ready_task();

        // you should never get here   
        while(1);
    }

    void nrk_start_high_ready_task() __naked
    {
        _asm
            mov dptr,#_nrk_high_ready_TCB
           
            movx a,@dptr
            mov b,a
            inc dptr
            movx a,@dptr
            mov dph,a
            mov a,b
            mov dpl,a
           
            movx a, @dptr
            mov _spx,a
            inc dptr
            movx a, @dptr
            mov __XPAGE,a
        
            mov a, _spx
            mov r0,a
            subb a,#0xD
            mov _spx,a
           
            ;Get the tasks PC and put it on the local stack
            dec r0
            movx a,@r0
            push acc
            dec r0
            movx a,@r0
            push acc
           
            dec r0
            movx a,@r0
            mov psw,a
            dec r0
            movx a,@r0
            mov r1,a
            dec r0
            movx a,@r0
            ;get r0 and put it on the local stack
            push acc
            dec r0
            movx a,@r0
            mov r7,a
            dec r0
            movx a,@r0
            mov r6,a
            dec r0
            movx a,@r0
            mov r5,a
            dec r0
            movx a,@r0
            mov r4,a
            dec r0
            movx a,@r0
            mov r3,a
            dec r0
            movx a,@r0
            mov r2,a
            dec r0
            movx a,@r0
            mov dph,a
            dec r0
            movx a,@r0
            mov dpl,a
            dec r0
            movx a,@r0
            mov b,a
            dec r0
            movx a,@r0
           
            pop ar0   
           
            reti
        _endasm;
    }

    int8_t nrk_TCB_init (nrk_task_type *Task, NRK_STK *ptos, NRK_STK *pbos, uint16_t stk_size, void *pext, uint16_t opt)
    {
        //  Already in critical section so no needenter critical section
        if(Task->Type!=IDLE_TASK)
            Task->task_ID=nrk_task_init_cnt;
        else Task->task_ID=NRK_IDLE_TASK_ID;

        if(nrk_task_init_cnt>=NRK_MAX_TASKS) nrk_kernel_error_add(NRK_EXTRA_TASK,0);
        if(Task->Type!=IDLE_TASK) nrk_task_init_cnt++;
        if(nrk_task_init_cnt==NRK_IDLE_TASK_ID) nrk_task_init_cnt++;
        //initialize member of TCB structure
        nrk_task_TCB[Task->task_ID].OSTaskStkPtr = ptos;
        nrk_task_TCB[Task->task_ID].task_prio = Task->prio;
        nrk_task_TCB[Task->task_ID].task_state = SUSPENDED;
       
        nrk_task_TCB[Task->task_ID].task_ID = Task->task_ID;
        nrk_task_TCB[Task->task_ID].suspend_flag = 0;
        nrk_task_TCB[Task->task_ID].period= _nrk_time_to_ticks( (void *)Task->period );  // sdcc can not do cast
        nrk_task_TCB[Task->task_ID].next_wakeup= _nrk_time_to_ticks( (void*)Task->offset); // sdcc can not do cast
        nrk_task_TCB[Task->task_ID].next_period= nrk_task_TCB[Task->task_ID].period+nrk_task_TCB[Task->task_ID].next_wakeup;
        nrk_task_TCB[Task->task_ID].cpu_reserve= _nrk_time_to_ticks((void *)Task->cpu_reserve); // sdcc can not do cast
        nrk_task_TCB[Task->task_ID].cpu_remaining = nrk_task_TCB[Task->task_ID].cpu_reserve;
        nrk_task_TCB[Task->task_ID].num_periods = 1;
        nrk_task_TCB[Task->task_ID].OSTCBStkBottom = pbos;
        nrk_task_TCB[Task->task_ID].errno= NRK_OK;
       
        return NRK_OK;
    }

    /*
    * _nrk_timer_tick()
    *
    * This function is called by the interrupt timer0.
    * It calls the scheduler.
    */
    void _nrk_timer_tick(void)
    {
        // want to do something before the scheduler gets called?
        // Go ahead and put it here...
        _nrk_scheduler();
          return;
    }

    uint16_t nrk_version (void)
    {
        return (NRK_VERSION);
    }

    ___________________________________________________________