View unanswered posts | View active topics It is currently Wed Jul 30, 2014 6:10 am






Reply to topic  [ 13 posts ] 
3.05: issue in switch statement with ubyte and array 
Author Message
Moderator
Moderator
User avatar

Joined: Wed Mar 05, 2008 8:14 am
Posts: 3165
Location: Rotterdam, The Netherlands
Post Re: 3.05: issue in switch statement with ubyte and array
Can you report this issue to the usual email address? :)

- Xander

_________________
| Professional Conduit of Reasonableness
| (Title bestowed upon on the 8th day of November, 2013)
| My Blog: I'd Rather Be Building Robots
| ROBOTC 3rd Party Driver Suite: [Project Page]


Thu Jan 19, 2012 2:33 pm
Profile WWW
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: 3.05: issue in switch statement with ubyte and array
RobotC seems to confuse easily between signed and unsigned values. I'd bet the ubyte somehow got converted to a signed 16-bit value in the switch statement. Just for fun if you have time, try this and see if it works.
Code:
switch(home.cell[x][y].info)
  {
    case -1:  nxtDisplayStringAt(0,40,"[x][y] 0x80 ok");   break;
    default:    nxtDisplayStringAt(0,40,"[x][y] 0x80 miss"); break;
  }


Thu Jan 19, 2012 6:21 pm
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: 3.05: issue in switch statement with ubyte and array
I encountered this bug before. It was a 16-bit value not an ubyte. But whenever I defined something that's the most significant bit, the code doesn't work. So it has something to do with signed and unsigned. At that time, I thought it was my fault because there is no "unsigned" 16-bit value in RobotC. But since you reproduced this issue with 8-bit, I think it is a similar issue.


Fri Jan 20, 2012 4:03 am
Profile
Creator
Creator

Joined: Fri Feb 09, 2007 9:21 am
Posts: 614
Post Re: 3.05: issue in switch statement with ubyte and array
MHTS wrote:
RobotC seems to confuse easily between signed and unsigned values. I'd bet the ubyte somehow got converted to a signed 16-bit value in the switch statement.

Yes. This was a bug in the compiler code generation. The fix is made and will hopefully be in the next update release.


Fri Jan 20, 2012 10:50 am
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: 3.05: issue in switch statement with ubyte and array
miki wrote:
@MHTS:
I got the same behavior with a case -1 and case 0x80.

Sorry, 0x80 sign extended to 16-bit is not -1, it should have been -128 (0xff80). So it might work with either case 0xff80 or case -128 if you are still curious to try it.


Fri Jan 20, 2012 2:50 pm
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: 3.05: issue in switch statement with ubyte and array
I think this bug has been around for a while and not specific to 3.05. I have noticed it a long time ago, but I didn't have time to narrow it down to the conclusion we have now. I believe the compiler might have generated a 16-bit compare instruction that automatically sign extended the 8-bit value that caused this issue.


Sun Jan 22, 2012 12:12 am
Profile
Moderator
Moderator
User avatar

Joined: Wed Mar 05, 2008 8:14 am
Posts: 3165
Location: Rotterdam, The Netherlands
Post Re: 3.05: issue in switch statement with ubyte and array
Would doing something like this help at all?
Code:
switch((ubyte)home.cell[0][0].info)
  {
    case 0x80:  nxtDisplayStringAt(0,50,"[0][0] 0x80 ok");   break;
    default:    nxtDisplayStringAt(0,50,"[0][0] 0x80 miss"); break;
  }   


- Xander

_________________
| Professional Conduit of Reasonableness
| (Title bestowed upon on the 8th day of November, 2013)
| My Blog: I'd Rather Be Building Robots
| ROBOTC 3rd Party Driver Suite: [Project Page]


Sun Jan 22, 2012 2:50 am
Profile WWW
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: 3.05: issue in switch statement with ubyte and array
mightor wrote:
Would doing something like this help at all?
Code:
switch((ubyte)home.cell[0][0].info)
  {
    case 0x80:  nxtDisplayStringAt(0,50,"[0][0] 0x80 ok");   break;
    default:    nxtDisplayStringAt(0,50,"[0][0] 0x80 miss"); break;
  }   


- Xander

It's hard to tell. Without knowing how the compiler generated the code, can't tell if that would fix the problem. But of course, you just need to put the code in and try :-)
In any case, Dick said it's already fixed. It's just an exercise for the curious minds.


Sun Jan 22, 2012 5:03 am
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: 3.05: issue in switch statement with ubyte and array
Did test case #8 work?


Sun Jan 22, 2012 1:58 pm
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: 3.05: issue in switch statement with ubyte and array
Hmm, so it is not 16-bit?! Try 32-bit (i.e. case 0xffffff80).


Sun Jan 22, 2012 2:58 pm
Profile
Moderator
Moderator
User avatar

Joined: Wed Mar 05, 2008 8:14 am
Posts: 3165
Location: Rotterdam, The Netherlands
Post Re: 3.05: issue in switch statement with ubyte and array
Code:
////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DEFINITIONS
////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define HOME_MAP_NBR_X  33
#define HOME_MAP_NBR_Y  20

typedef struct
{
  ubyte info;
  ubyte reel;
  ubyte path;
  ubyte dist;
} S_CELL;

typedef struct
{
  ubyte  nbr_x;
  ubyte  nbr_y;
  S_CELL cell[HOME_MAP_NBR_X][HOME_MAP_NBR_Y];
} S_HOME;

////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DECLARATIONS
////////////////////////////////////////////////////////////////////////////////////////////////////////////
S_HOME  home;

////////////////////////////////////////////////////////////////////////////////////////////////////////////
// CODES
////////////////////////////////////////////////////////////////////////////////////////////////////////////
task main()
//
//
// Constants Pool:
//
//0000: 80FF0000                                                   long    "65408"
//0004: 255800                                                     string  "%X"
//0007: 23312078 3830206F 6B00                                     string  "#1 x80 ok"
//0011: 23312078 38302065 727200                                   string  "#1 x80 err"
//001C: 23322078 3830206F 6B2000                                   string  "#2 x80 ok "
//0027: 23322078 38302065 727200                                   string  "#2 x80 err"
//0032: 23332078 3830206F 6B00                                     string  "#3 x80 ok"
//003C: 23332078 38302065 727200                                   string  "#3 x80 err"
//0047: 23342078 3830206F 6B00                                     string  "#4 x80 ok"
//0051: 23342078 38302065 727200                                   string  "#4 x80 err"
//005C: 23352078 3830206F 6B00                                     string  "#5 x80 ok"
//0066: 23352078 38302065 727200                                   string  "#5 x80 err"
//0071: 2336202D 31323820 6F6B00                                   string  "#6 -128 ok"
//007C: 2336202D 31323820 65727200                                 string  "#6 -128 err"
//0088: 2337202D 31206F6B 00                                       string  "#7 -1 ok"
//0091: 2337202D 31206572 7200                                     string  "#7 -1 err"
//009B: 23382078 46463830 206F6B00                                 string  "#8 xFF80 ok"
//00A7: 23382078 46463830 20657272 00                              string  "#8 xFF80 err"
//00B4:
//
//Constants Summary    Items: 18, Size: 180 bytes
//
//Code segment: main(); Task: 0
//
0000: 11117300                 bFloatDuringInactiveMotorPWM = 0   
0004: 67180000000000000000     defineMUXes(none, none, none, none, none, none, none, none, none, none, none, none, none, none, none, none)
    : 0000000000000000                                           
0016: 6767010004               ClearSensors(S1..S4)               
001B: 11390000                 bMotorReflected[motorA] = 0       
001F: 11380001                 nMotorPIDSpeedCtrl[motorA] = 1     
0023: 11390100                 bMotorReflected[motorB] = 0       
0027: 11380101                 nMotorPIDSpeedCtrl[motorB] = 1     
002B: 11390200                 bMotorReflected[motorC] = 0       
002F: 11380201                 nMotorPIDSpeedCtrl[motorC] = 1     
{
  // Display
  eraseDisplay();
0033: 9800                     eraseDisplay()                     

  int x=0;
0035: 122B2A05020000           G1322 = 0                         
  int y=0;
003C: 122B2B05020000           G1323 = 0                         
  home.cell[0][0].info = 0x80;
0043: 11340280                 G01H(byte) = 128                   
  writeDebugStreamLine("%X",home.cell[0][0].info);
0047: 8D2B2E05340200           G1326(long) = G01H(byte)            // Convert 'short' to 'long'
004E: EF11320400012B2E05       writeDebugStreamLine("%X", home.cell[0][0].info)
  writeDebugStreamLine("%X",home.cell[x][y].info);
0057: 2F2B2A052000             BoundsCheck(G1322, 33)             
005D: 2F2B2B051300             BoundsCheck(G1323, 20)             
0063: AA2B2D052B2A05021400     G1325 = G1322 * 20                 
006D: 082B2D052B2B05           G1325 += G1323                     
0074: 0A2B2D05020400           G1325 *= 4                         
007B: 7D2B2E052D0200           G1326 = addrOf G01H(byte)           // Convert to RAM address [3]
0082: 082B2D052B2E05           G1325 += G1326                     
0089: 8F2B2D053A2D05           G1325 = *G1325                      // Convert 'ubyte'  to 'short'
0090: 8D2B2E052B2D05           G1326(long) = G1325                 // Convert 'short' to 'long'
0097: EF11320400012B2E05       writeDebugStreamLine("%X", home.cell[x][y].info)
  // test case #1
  switch(home.cell[0][0].info)
00A0: 23020280003402000A00     TestAndBranchUnsignedByteVarFar(128 != G01H(byte), L00B2) // case label 128
  {
    case 0x80:  writeDebugStreamLine("#1 x80 ok");  break;
00AA: EF1132070000             writeDebugStreamLine("#1 x80 ok") 
00B0: 7907                     BranchNear(L00B8)                   // Goto break location (67)
    default:    writeDebugStreamLine("#1 x80 err"); break;
00B2: EF1132110000      L00B2: writeDebugStreamLine("#1 x80 err")
  }
  // test case #2
  switch(home.cell[x][y].info)
00B8: 2F2B2A052000      L00B8: BoundsCheck(G1322, 33)             
00BE: 2F2B2B051300             BoundsCheck(G1323, 20)             
00C4: AA2B2D052B2A05021400     G1325 = G1322 * 20                 
00CE: 082B2D052B2B05           G1325 += G1323                     
00D5: 0A2B2D05020400           G1325 *= 4                         
00DC: 7D2B2E052D0200           G1326 = addrOf G01H(byte)           // Convert to RAM address [3]
00E3: 082B2D052B2E05           G1325 += G1326                     
00EA: 992D5C0A3A2D05           G1326H(byte) = *G1325             
00F1: 8F2B2E052D5C0A           G1326 = G1326H(byte)                // Convert 'ubyte'  to 'short'
00F8: 25020280002B2E050A00     TestAndBranchIntFar(128 != G1326, L010A) // case label 128
  {
    case 0x80:  writeDebugStreamLine("#2 x80 ok "); break;
0102: EF11321C0000             writeDebugStreamLine("#2 x80 ok ")
0108: 7907                     BranchNear(L0110)                   // Goto break location (69)
    default:    writeDebugStreamLine("#2 x80 err"); break;
010A: EF1132270000      L010A: writeDebugStreamLine("#2 x80 err")
  }
  // test case #3
  switch((ubyte)home.cell[x][y].info)
0110: 2F2B2A052000      L0110: BoundsCheck(G1322, 33)             
0116: 2F2B2B051300             BoundsCheck(G1323, 20)             
011C: AA2B2D052B2A05021400     G1325 = G1322 * 20                 
0126: 082B2D052B2B05           G1325 += G1323                     
012D: 0A2B2D05020400           G1325 *= 4                         
0134: 7D2B2E052D0200           G1326 = addrOf G01H(byte)           // Convert to RAM address [3]
013B: 082B2D052B2E05           G1325 += G1326                     
0142: 992D5C0A3A2D05           G1326H(byte) = *G1325             
0149: 8F2B2E052D5C0A           G1326 = G1326H(byte)                // Convert 'ubyte'  to 'short'
0150: 25020280002B2E050A00     TestAndBranchIntFar(128 != G1326, L0162) // case label 128
  {
    case 0x80:  writeDebugStreamLine("#3 x80 ok");  break;
015A: EF1132320000             writeDebugStreamLine("#3 x80 ok") 
0160: 7907                     BranchNear(L0168)                   // Goto break location (71)
    default:    writeDebugStreamLine("#3 x80 err"); break;
0162: EF11323C0000      L0162: writeDebugStreamLine("#3 x80 err")
  }
  // test case #4
  switch(((ubyte)home.cell[x][y].info))
0168: 2F2B2A052000      L0168: BoundsCheck(G1322, 33)             
016E: 2F2B2B051300             BoundsCheck(G1323, 20)             
0174: AA2B2D052B2A05021400     G1325 = G1322 * 20                 
017E: 082B2D052B2B05           G1325 += G1323                     
0185: 0A2B2D05020400           G1325 *= 4                         
018C: 7D2B2E052D0200           G1326 = addrOf G01H(byte)           // Convert to RAM address [3]
0193: 082B2D052B2E05           G1325 += G1326                     
019A: 992D5C0A3A2D05           G1326H(byte) = *G1325             
01A1: 8F2B2E052D5C0A           G1326 = G1326H(byte)                // Convert 'ubyte'  to 'short'
01A8: 25020280002B2E050A00     TestAndBranchIntFar(128 != G1326, L01BA) // case label 128
  {
    case 0x80:  writeDebugStreamLine("#4 x80 ok");  break;
01B2: EF1132470000             writeDebugStreamLine("#4 x80 ok") 
01B8: 7907                     BranchNear(L01C0)                   // Goto break location (73)
    default:    writeDebugStreamLine("#4 x80 err"); break;
01BA: EF1132510000      L01BA: writeDebugStreamLine("#4 x80 err")
  }
  // test case #5
  ubyte ub = home.cell[x][y].info;
01C0: 2F2B2A052000      L01C0: BoundsCheck(G1322, 33)             
01C6: 2F2B2B051300             BoundsCheck(G1323, 20)             
01CC: AA2B2D052B2A05021400     G1325 = G1322 * 20                 
01D6: 082B2D052B2B05           G1325 += G1323                     
01DD: 0A2B2D05020400           G1325 *= 4                         
01E4: 7D2B2E052D0200           G1326 = addrOf G01H(byte)           // Convert to RAM address [3]
01EB: 082B2D052B2E05           G1325 += G1326                     
01F2: 9934580A3A2D05           G1324H(byte) = *G1325             
  switch(ub)
01F9: 230202800034580A0A00     TestAndBranchUnsignedByteVarFar(128 != G1324H(byte), L020B) // case label 128
  {
    case 0x80:  writeDebugStreamLine("#5 x80 ok");  break;
0203: EF11325C0000             writeDebugStreamLine("#5 x80 ok") 
0209: 7907                     BranchNear(L0211)                   // Goto break location (75)
    default:    writeDebugStreamLine("#5 x80 err"); break;
020B: EF1132660000      L020B: writeDebugStreamLine("#5 x80 err")
  }
  // test case #6
  switch(home.cell[x][y].info)
0211: 2F2B2A052000      L0211: BoundsCheck(G1322, 33)             
0217: 2F2B2B051300             BoundsCheck(G1323, 20)             
021D: AA2B2D052B2A05021400     G1325 = G1322 * 20                 
0227: 082B2D052B2B05           G1325 += G1323                     
022E: 0A2B2D05020400           G1325 *= 4                         
0235: 7D2B2E052D0200           G1326 = addrOf G01H(byte)           // Convert to RAM address [3]
023C: 082B2D052B2E05           G1325 += G1326                     
0243: 992D5C0A3A2D05           G1326H(byte) = *G1325             
024A: 8F2B2E052D5C0A           G1326 = G1326H(byte)                // Convert 'ubyte'  to 'short'
0251: 25020280FF2B2E050A00     TestAndBranchIntFar(-128 != G1326, L0263) // case label -128
  {
    case -128:  writeDebugStreamLine("#6 -128 ok");  break;
025B: EF1132710000             writeDebugStreamLine("#6 -128 ok")
0261: 7907                     BranchNear(L0269)                   // Goto break location (77)
    default:    writeDebugStreamLine("#6 -128 err"); break;
0263: EF11327C0000      L0263: writeDebugStreamLine("#6 -128 err")
  }
  // test case #7
  switch(home.cell[x][y].info)
0269: 2F2B2A052000      L0269: BoundsCheck(G1322, 33)             
026F: 2F2B2B051300             BoundsCheck(G1323, 20)             
0275: AA2B2D052B2A05021400     G1325 = G1322 * 20                 
027F: 082B2D052B2B05           G1325 += G1323                     
0286: 0A2B2D05020400           G1325 *= 4                         
028D: 7D2B2E052D0200           G1326 = addrOf G01H(byte)           // Convert to RAM address [3]
0294: 082B2D052B2E05           G1325 += G1326                     
029B: 992D5C0A3A2D05           G1326H(byte) = *G1325             
02A2: 8F2B2E052D5C0A           G1326 = G1326H(byte)                // Convert 'ubyte'  to 'short'
02A9: 250202FFFF2B2E050A00     TestAndBranchIntFar(-1 != G1326, L02BB) // case label -1
  {
    case -1:    writeDebugStreamLine("#7 -1 ok");  break;
02B3: EF1132880000             writeDebugStreamLine("#7 -1 ok")   
02B9: 7907                     BranchNear(L02C1)                   // Goto break location (79)
    default:    writeDebugStreamLine("#7 -1 err"); break;
02BB: EF1132910000      L02BB: writeDebugStreamLine("#7 -1 err") 
  }
  // test case  #8
  switch(home.cell[x][y].info)
02C1: 2F2B2A052000      L02C1: BoundsCheck(G1322, 33)             
02C7: 2F2B2B051300             BoundsCheck(G1323, 20)             
02CD: AA2B2D052B2A05021400     G1325 = G1322 * 20                 
02D7: 082B2D052B2B05           G1325 += G1323                     
02DE: 0A2B2D05020400           G1325 *= 4                         
02E5: 7D2B2E052D0200           G1326 = addrOf G01H(byte)           // Convert to RAM address [3]
02EC: 082B2D052B2E05           G1325 += G1326                     
02F3: 992D5C0A3A2D05           G1326H(byte) = *G1325             
02FA: 8F2B2E052D5C0A           G1326 = G1326H(byte)                // Convert 'ubyte'  to 'short'
0301: 8D2B2E052B2E05           G1326(long) = G1326                 // Convert 'short' to 'long'
0308: 24023200002B2E050900     TestAndBranchLongFar(65408 != G1326(long), L0319) // case label 65408
  {
    case 0xFF80:writeDebugStreamLine("#8 xFF80 ok");  break;
0312: EF11329B0000             writeDebugStreamLine("#8 xFF80 ok")
0318: FE                       Return()                            // Replace 'bra'
    default:    writeDebugStreamLine("#8 xFF80 err"); break;
0319: EF1132A70000      L0319: writeDebugStreamLine("#8 xFF80 err")
031F: FE                       Return()                            // main()
0000: FE                       Return()                            // _main__()

_________________
| Professional Conduit of Reasonableness
| (Title bestowed upon on the 8th day of November, 2013)
| My Blog: I'd Rather Be Building Robots
| ROBOTC 3rd Party Driver Suite: [Project Page]


Sun Jan 22, 2012 3:19 pm
Profile WWW
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: 3.05: issue in switch statement with ubyte and array
Ah, just as I expected the following compare instruction is treating the ubyte as "int" which really means "signed short".
Code:
TestAndBranchIntFar(128 != G1326, L0162)

The case 0xff80 doesn't work because the compiler is generating a different instruction.

Xander, can you tell us how you generated the assembly listing? :-) That's useful to debug compiler issues.
[EDIT]: Ah never mind, found it. "View->Assembly (F9)".


Sun Jan 22, 2012 3:32 pm
Profile
Moderator
Moderator
User avatar

Joined: Wed Mar 05, 2008 8:14 am
Posts: 3165
Location: Rotterdam, The Netherlands
Post Re: 3.05: issue in switch statement with ubyte and array
Yeah, I hit that by accident once and it's proven quite useful since :)

- Xander

_________________
| Professional Conduit of Reasonableness
| (Title bestowed upon on the 8th day of November, 2013)
| My Blog: I'd Rather Be Building Robots
| ROBOTC 3rd Party Driver Suite: [Project Page]


Sun Jan 22, 2012 3:39 pm
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 13 posts ] 

Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  



Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.