简体   繁体   中英

How to push variable in sdcc inline assembly?

I have this code in ThreadCreate() :

int tmpPSW = newThID << 3;
__asm
    PUSH A
    PUSH _tmpPSW
__endasm;

This results in:

?ASlink-Warning-Undefined Global '_tmpPSW' referenced by module 'cooperative'

I don't get why. tmpPSW is clearly defined, but sdcc complains. What am I doing wrong here? Is there other way to push C variable in sdcc inline assembly?

Also this is probably relevant. The .asm file generated contains allocation info:

;------------------------------------------------------------
;Allocation info for local variables in function 'ThreadCreate'
;------------------------------------------------------------
;fp                        Allocated to registers 
;newThMask                 Allocated to registers r6 r7 
;newThID                   Allocated to registers r5 
;startSP                   Allocated to registers r3 r4 
;tmp                       Allocated to registers 
;tmpPSW                    Allocated to registers 
;------------------------------------------------------------

Does this mean I run out of registers? If so how should I mitigate this?


EDIT:

Source of ThreadCreate() :

// ThreadID is typedef&#039;ed as char
ThreadID ThreadCreate(FunctionPtr fp) {
    if (activeTh == 0b1111)
        return -1;

    // i.e. get rightmost bit 0 in bitmask
    // https://stackoverflow.com/a/42747608/6306190
    int newThMask = ~activeTh & (activeTh + 1);

    activeTh |= newThMask;

    ThreadID newThID = 0;
    while (newThMask >>= 1) { newThID++; }
    int startSP = (newThID ^ (1UL << 2)) << 4;

    int tmp = SP;
    SP = startSP;

    int tmpPSW = newThID << 3;
    __asm
        PUSH DPL          ;; push _fp (argument passed in as DPTR in SDCC)
        PUSH DPH          ;; push _fp
        MOV A, #0
        PUSH A            ;; ACC
        PUSH A            ;; B
        PUSH A            ;; DPL
        PUSH A            ;; DPH
        PUSH _tmpPSW      ;; PSW
    __endasm;

    savedSP[newThID] = SP;
    SP = tmp;
    return newThID;
}

Generated assembly of ThreadCreate() :

;------------------------------------------------------------
;Allocation info for local variables in function &#039;ThreadCreate&#039;
;------------------------------------------------------------
;fp                        Allocated to registers 
;newThMask                 Allocated to registers r6 r7 
;newThID                   Allocated to registers r5 
;startSP                   Allocated to registers r3 r4 
;tmp                       Allocated to registers 
;tmpPSW                    Allocated to registers 
;------------------------------------------------------------
;   cooperative.c:104: ThreadID ThreadCreate(FunctionPtr fp) {
;   -----------------------------------------
;    function ThreadCreate
;   -----------------------------------------
_ThreadCreate:
;   cooperative.c:110: if (activeTh == 0b1111)
    mov a,#0x0f
    cjne    a,_activeTh,00121$
    clr a
    cjne    a,(_activeTh + 1),00121$
    sjmp    00122$
00121$:
    sjmp    00102$
00122$:
;   cooperative.c:111: return -1;
    mov dpl,#0xff
    ret
00102$:
;   cooperative.c:119: int newThMask = ~activeTh & (activeTh + 1);
    mov a,_activeTh
    cpl a
    mov r6,a
    mov a,(_activeTh + 1)
    cpl a
    mov r7,a
    mov a,#0x01
    add a,_activeTh
    mov r4,a
    clr a
    addc    a,(_activeTh + 1)
    mov r5,a
    mov a,r4
    anl ar6,a
    mov a,r5
    anl ar7,a
;   cooperative.c:157: activeTh |= newThMask;
    mov a,r6
    orl _activeTh,a
    mov a,r7
    orl (_activeTh + 1),a
;   cooperative.c:160: while (newThMask >>= 1) { newThID++; }
    mov r5,#0x00
00103$:
    mov ar3,r6
    mov a,r7
    mov c,acc.7
    rrc a
    xch a,r3
    rrc a
    xch a,r3
    mov r4,a
    mov ar6,r3
    mov ar7,r4
    mov a,r3
    orl a,r4
    jz  00105$
    inc r5
    sjmp    00103$
00105$:
;   cooperative.c:161: int startSP = (newThID ^ (1UL << 2)) << 4;
    mov ar3,r5
    mov r4,#0x00
    mov r6,#0x00
    xrl ar3,#0x04
    mov a,r4
    swap    a
    anl a,#0xf0
    xch a,r3
    swap    a
    xch a,r3
    xrl a,r3
    xch a,r3
    anl a,#0xf0
    xch a,r3
    xrl a,r3
    mov r4,a
;   cooperative.c:163: int tmp = SP;
    mov r7,_SP
;   cooperative.c:164: SP = startSP;
    mov _SP,r3
;   cooperative.c:176: __endasm;
    PUSH    DPL ;; push _fp (argument passed in as DPTR in 390)
    PUSH    DPH ;; push _fp
    MOV A, #0
    PUSH    A ;; ACC
    PUSH    A ;; B
    PUSH    A ;; DPL
    PUSH    A ;; DPH
    PUSH    _tmpPSW ;; PSW
;   cooperative.c:178: savedSP[newThID] = SP;
    mov a,r5
    add a,r5
    add a,#_savedSP
    mov r1,a
    mov r4,_SP
    mov r6,#0x00
    mov @r1,ar4
    inc r1
    mov @r1,ar6
;   cooperative.c:179: SP = tmp;
    mov _SP,r7
;   cooperative.c:180: return newThID;
    mov dpl,r5
;   cooperative.c:181: }
    ret

The compiler optimized your variable away, because it was never used from the view of the compiler. Compare the generated assembly with the source to see this.

You might try other options. Because I don't have SDCC installed, I can just suggest:

  • Make the variable volatile .
  • Make the variable static , since one flavor of PUSH works with an address in the internal RAM.
  • Because inline assembly is heavily depending on the surrounding code and the compiler, you could also use newThID in the assembly part, and do the shift there.

Note 1: The generated assembly demonstrates how slow machine code gets if you use int without thinking. Limit your variables to the smallest appropriate data type.

Note 2: Don't make the variable global. static does what you want without exposing the variable globally: Place it in RAM so it can be accessed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM