EmbeddedRelated.com
Forums

CodeWarrior and Switch statment compiling issue

Started by Tim Raabe September 4, 2003
I have the same code in 2 different projects, in the main loop of
both. This section of code has a switch statement in it, but in one
project, it works, and the other it doesn't(always goes to the first
case). The code is identical except for some port changes due to
outputs being different on the two chips.

The one that works uses the void NEAR _CASE_CHECKED (void) routine,
where the one that doesn't uses the void NEAR _CASE_CHECKED_BYTE
(void) routine. See code below. Both are from the file rtshc12.c.
The difference between the two projects is that one is for the
s12dp256B, and the other is for the s12DJ128B.

Why would this compile into two different types of checks, and what
can I do to fix this issue? Any help you can give would be
appreciated.

Tim

*----------------- CASE_CHECKED -
----------
Parameters:
- unsigned jump-index in the D Register
- table starting at the return address

Result :
- Y remains unchanged

table starts at the return address
2 bytes: N ; number of entries
2 bytes: AddrD ; default label
2 bytes: Addr0 ; jump address for entry 0
2 bytes: Addr1 ; jump address for entry 1
....
2 bytes: AddrN ; jump address for entry N
*/

/*
* Works with this one
*
*/

#ifdef __cplusplus
extern "C"
#endif
#pragma NO_FRAME
#pragma NO_ENTRY
#pragma NO_EXIT

void NEAR _CASE_CHECKED (void) {
asm {
PULX ; load address of search table
CPD 4, X+ ; compare maximal entrie
BLO def ; branch to a defined label
LDD #-1 ; load offset of default label
def: LSLD ; offset*=2
_SRET ; debug info only: This is the last instr
of a function with a special return
JMP [D, X] ; jump to selected label

}
} /*
* Doesnt' work with this one
*
*/ #ifdef __cplusplus
extern "C"
#endif
#pragma NO_FRAME
#pragma NO_ENTRY
#pragma NO_EXIT

void NEAR _CASE_CHECKED_BYTE (void) {
asm {
PULX ; load address
PSHB
#if DO_NOT_USE_TEST_BRANCHES
LEAX 2, X
TSTA
BNE defa ; branch if value > 0xff
CMPB 0, X ; compare low byte
BLO jump ; branch if value < #entries
#else
CMPB 2, X+ ; compare low byte
TBNE A, defa ; branch if value > 0xff
BLO jump ; branch if value < #entries
#endif
defa: LDAB -1, X ; select default entry, address = X-1
BRA sum
jump: LDAB B, X ; load branch offset
sum: LEAX B, X
PULB
_SRET ; debug info only: This is the last instr
of a function with a special return
JMP 0, X ; jump to selected entry
}
}



There are various options in the compiler to control
the code generated for switch tables:
-CswMaxLF
-CsWMinLB
-CswMinLF
-CsMinSLB

My guess is that even with the same source code, the number
and kind of labels for the switch are different in your
code (e.g. controlled by preprocessor macros)?
With different input, the compiler will generate different
code/strategies for it.

Erich

> -----Original Message-----
> From: Tim Raabe [mailto:]
> Sent: Donnerstag, 4. September 2003 18:23
> To:
> Subject: [68HC12] CodeWarrior and Switch statment compiling issue > I have the same code in 2 different projects, in the main loop of
> both. This section of code has a switch statement in it, but in one
> project, it works, and the other it doesn't(always goes to the first
> case). The code is identical except for some port changes due to
> outputs being different on the two chips.
>
> The one that works uses the void NEAR _CASE_CHECKED (void) routine,
> where the one that doesn't uses the void NEAR _CASE_CHECKED_BYTE
> (void) routine. See code below. Both are from the file rtshc12.c.
> The difference between the two projects is that one is for the
> s12dp256B, and the other is for the s12DJ128B.
>
> Why would this compile into two different types of checks, and what
> can I do to fix this issue? Any help you can give would be
> appreciated.
>
> Tim
>
> *----------------- CASE_CHECKED -
> ----------
> Parameters:
> - unsigned jump-index in the D Register
> - table starting at the return address
>
> Result :
> - Y remains unchanged
>
> table starts at the return address
> 2 bytes: N ; number of entries
> 2 bytes: AddrD ; default label
> 2 bytes: Addr0 ; jump address for entry 0
> 2 bytes: Addr1 ; jump address for entry 1
> ....
> 2 bytes: AddrN ; jump address for entry N
> */ >
>
> /*
> * Works with this one
> *
> */
>
> #ifdef __cplusplus
> extern "C"
> #endif
> #pragma NO_FRAME
> #pragma NO_ENTRY
> #pragma NO_EXIT
>
> void NEAR _CASE_CHECKED (void) {
> asm {
> PULX ; load address of search table
> CPD 4, X+ ; compare maximal entrie
> BLO def ; branch to a defined label
> LDD #-1 ; load offset of default label
> def: LSLD ; offset*=2
> _SRET ; debug info only: This is the last instr
> of a function with a special return
> JMP [D, X] ; jump to selected label
>
> }
> } > /*
> * Doesnt' work with this one
> *
> */ > #ifdef __cplusplus
> extern "C"
> #endif
> #pragma NO_FRAME
> #pragma NO_ENTRY
> #pragma NO_EXIT
>
> void NEAR _CASE_CHECKED_BYTE (void) {
> asm {
> PULX ; load address
> PSHB
> #if DO_NOT_USE_TEST_BRANCHES
> LEAX 2, X
> TSTA
> BNE defa ; branch if value > 0xff
> CMPB 0, X ; compare low byte
> BLO jump ; branch if value < #entries
> #else
> CMPB 2, X+ ; compare low byte
> TBNE A, defa ; branch if value > 0xff
> BLO jump ; branch if value < #entries
> #endif
> defa: LDAB -1, X ; select default entry, address = X-1
> BRA sum
> jump: LDAB B, X ; load branch offset
> sum: LEAX B, X
> PULB
> _SRET ; debug info only: This is the last instr
> of a function with a special return
> JMP 0, X ; jump to selected entry
> }
> } >
>
> -------------------- >
> ">http://docs.yahoo.com/info/terms/





Hi Tim,

_CASE_CHECKED_BYTE is used if all the branch destinations (the cases) are within a 256 byte range.
If the switch content generates more code, _CASE_CHECKED is used instead.
I doubt a bit that the bug is inside of the _CASE_CHECKED_BYTE runtime support.
Instead I would guess that the problem is on the calling side.
Can you check what's in the D register when _CASE_CHECKED_BYTE is entered? Does it contain the right value?
(Note the lowest case entry is 0, if you don't have a case 0, this is not directly the same value).

Also you could send me off list an lst file generated by the compiler which contains the problematic _CASE_CHECKED_BYTE
with a little description which value does not work so I can have a look.

Bye

Daniel > -----Original Message-----
> From: Erich Styger [mailto:]
> Sent: Friday, September 05, 2003 11:59
> To:
> Subject: RE: [68HC12] CodeWarrior and Switch statment compiling issue > There are various options in the compiler to control
> the code generated for switch tables:
> -CswMaxLF
> -CsWMinLB
> -CswMinLF
> -CsMinSLB
>
> My guess is that even with the same source code, the number
> and kind of labels for the switch are different in your
> code (e.g. controlled by preprocessor macros)?
> With different input, the compiler will generate different
> code/strategies for it.
>
> Erich
>
> > -----Original Message-----
> > From: Tim Raabe [mailto:]
> > Sent: Donnerstag, 4. September 2003 18:23
> > To:
> > Subject: [68HC12] CodeWarrior and Switch statment compiling issue
> >
> >
> > I have the same code in 2 different projects, in the main loop of
> > both. This section of code has a switch statement in it, but in one
> > project, it works, and the other it doesn't(always goes to the first
> > case). The code is identical except for some port changes due to
> > outputs being different on the two chips.
> >
> > The one that works uses the void NEAR _CASE_CHECKED (void) routine,
> > where the one that doesn't uses the void NEAR _CASE_CHECKED_BYTE
> > (void) routine. See code below. Both are from the file rtshc12.c.
> > The difference between the two projects is that one is for the
> > s12dp256B, and the other is for the s12DJ128B.
> >
> > Why would this compile into two different types of checks, and what
> > can I do to fix this issue? Any help you can give would be
> > appreciated.
> >
> > Tim
> >
> > *----------------- CASE_CHECKED -
> > ----------
> > Parameters:
> > - unsigned jump-index in the D Register
> > - table starting at the return address
> >
> > Result :
> > - Y remains unchanged
> >
> > table starts at the return address
> > 2 bytes: N ; number of entries
> > 2 bytes: AddrD ; default label
> > 2 bytes: Addr0 ; jump address for entry 0
> > 2 bytes: Addr1 ; jump address for entry 1
> > ....
> > 2 bytes: AddrN ; jump address for entry N
> > */
> >
> >
> >
> >
> > /*
> > * Works with this one
> > *
> > */
> >
> > #ifdef __cplusplus
> > extern "C"
> > #endif
> > #pragma NO_FRAME
> > #pragma NO_ENTRY
> > #pragma NO_EXIT
> >
> > void NEAR _CASE_CHECKED (void) {
> > asm {
> > PULX ; load address of search table
> > CPD 4, X+ ; compare maximal entrie
> > BLO def ; branch to a defined label
> > LDD #-1 ; load offset of default label
> > def: LSLD ; offset*=2
> > _SRET ; debug info only: This is the last instr
> > of a function with a special return
> > JMP [D, X] ; jump to selected label
> >
> > }
> > }
> >
> >
> > /*
> > * Doesnt' work with this one
> > *
> > */
> >
> >
> > #ifdef __cplusplus
> > extern "C"
> > #endif
> > #pragma NO_FRAME
> > #pragma NO_ENTRY
> > #pragma NO_EXIT
> >
> > void NEAR _CASE_CHECKED_BYTE (void) {
> > asm {
> > PULX ; load address
> > PSHB
> > #if DO_NOT_USE_TEST_BRANCHES
> > LEAX 2, X
> > TSTA
> > BNE defa ; branch if value > 0xff
> > CMPB 0, X ; compare low byte
> > BLO jump ; branch if value < #entries
> > #else
> > CMPB 2, X+ ; compare low byte
> > TBNE A, defa ; branch if value > 0xff
> > BLO jump ; branch if value < #entries
> > #endif
> > defa: LDAB -1, X ; select default entry, address = X-1
> > BRA sum
> > jump: LDAB B, X ; load branch offset
> > sum: LEAX B, X
> > PULB
> > _SRET ; debug info only: This is the last instr
> > of a function with a special return
> > JMP 0, X ; jump to selected entry
> > }
> > }
> >
> >
> >
> >
> > --------------------
> >
> >
> >
> > ">http://docs.yahoo.com/info/terms/
> >
> >
> -------------------- >
> ">http://docs.yahoo.com/info/terms/