Read-Only Author Jon Ward Posted 27-May-2002 08:26 GMT Toolset C51 |  RE: Address bits in XDATA Jon Ward ... and another thing: I seem to remember that the Keil implementation is pretty inefficient.
I've used both bit-fields and bit masking and have not noticed a real difference in the code generated for either.
/*--------------------------------------
Struct for bit field test.
--------------------------------------*/
struct bf_st
{
unsigned int bf1: 4;
unsigned int bf2: 3;
unsigned int bf3: 9;
};
struct bf_st bfst; // Structure for 3 bit fields (16 bits)
/*--------------------------------------
Unsigned int for bit mask test.
--------------------------------------*/
unsigned int bfui; // int for 3 bit fields (16 bits)
/*--------------------------------------
Macros used to read and write bits in
the unsigned int.
--------------------------------------*/
#define Get_BF1a (bfui & 0x0F)
#define Get_BF2a ((bfui >> 4) & 0x07)
#define Get_BF3a ((bfui >> 7) & 0x01FF)
#define Set_BF1a(x) (bfui = (bfui & ~0x000F) | (x) & 0x0F)
#define Set_BF2a(x) (bfui = (bfui & ~0x0070) | ((x) & 0x07) << 4)
#define Set_BF3a(x) (bfui = (bfui & ~0xFF80) | ((x) & 0x1FF) << 7)
/*--------------------------------------
Function to test bit field.
--------------------------------------*/
void test_bitfield (void)
{
volatile unsigned int y;
bfst.bf1 = 14;
bfst.bf2 = 7;
bfst.bf3 = 0x1A5;
y = bfst.bf1;
y = bfst.bf2;
y = bfst.bf3;
}
/*--------------------------------------
Function to test bit masking.
--------------------------------------*/
void test_bitmask (void)
{
volatile unsigned int y;
Set_BF1a(14);
Set_BF2a(7);
Set_BF3a(0x1A5);
y = Get_BF1a;
y = Get_BF2a;
y = Get_BF3a;
}
The function test_bitfield tests a struct with 3 bit fields (4, 3, and 9 bits wide). A write and a read is performed to all bit fields.
The function test_bitmask test an unsigned int that is masked into 3 blocks (4, 3, and 9 bits wide). A write and a read is performed to each.
Note that each function writes and reads in the same way. The resulting code is as follows:
test_bitfield
; FUNCTION test_bitfield (BEGIN)
34 void test_bitfield (void)
35 {
36 1 volatile unsigned int y;
37 1
38 1 bfst.bf1 = 14;
0000 E500 R MOV A,bfst+01H
0002 54F0 ANL A,#0F0H
0004 850000 R MOV bfst,bfst
0007 440E ORL A,#0EH
0009 F500 R MOV bfst+01H,A
39 1 bfst.bf2 = 7;
000B 850000 R MOV bfst,bfst
000E 4470 ORL A,#070H
0010 F500 R MOV bfst+01H,A
40 1 bfst.bf3 = 0x1A5;
0012 547F ANL A,#07FH
0014 FF MOV R7,A
0015 74D2 MOV A,#0D2H
0017 F500 R MOV bfst,A
0019 EF MOV A,R7
001A 4480 ORL A,#080H
001C F500 R MOV bfst+01H,A
41 1
42 1 y = bfst.bf1;
001E FF MOV R7,A
001F 750000 R MOV y,#00H
0022 EF MOV A,R7
0023 540F ANL A,#0FH
0025 F500 R MOV y+01H,A
43 1 y = bfst.bf2;
0027 E500 R MOV A,bfst
0029 C4 SWAP A
002A F8 MOV R0,A
002B 54F0 ANL A,#0F0H
002D C8 XCH A,R0
002E E500 R MOV A,bfst+01H
0030 C4 SWAP A
0031 540F ANL A,#0FH
0033 48 ORL A,R0
0034 750000 R MOV y,#00H
0037 5407 ANL A,#07H
0039 F500 R MOV y+01H,A
44 1 y = bfst.bf3;
003B AE00 R MOV R6,bfst
003D E500 R MOV A,bfst+01H
003F 7807 MOV R0,#07H
0041 ?C0006:
0041 CE XCH A,R6
0042 C3 CLR C
0043 13 RRC A
0044 CE XCH A,R6
0045 13 RRC A
0046 D8F9 DJNZ R0,?C0006
0048 FF MOV R7,A
0049 EE MOV A,R6
004A 5401 ANL A,#01H
004C F500 R MOV y,A
004E 8F00 R MOV y+01H,R7
45 1 }
0050 22 RET
; FUNCTION test_bitfield (END)
test_bitmask
; FUNCTION test_bitmask (BEGIN)
50 void test_bitmask (void)
51 {
52 1 volatile unsigned int y;
53 1
54 1 Set_BF1a(14);
0000 E500 R MOV A,bfui+01H
0002 54F0 ANL A,#0F0H
0004 850000 R MOV bfui,bfui
0007 440E ORL A,#0EH
0009 F500 R MOV bfui+01H,A
55 1 Set_BF2a(7);
000B 548F ANL A,#08FH
000D 850000 R MOV bfui,bfui
0010 4470 ORL A,#070H
0012 F500 R MOV bfui+01H,A
56 1 Set_BF3a(0x1A5);
0014 547F ANL A,#07FH
0016 FF MOV R7,A
0017 74D2 MOV A,#0D2H
0019 F500 R MOV bfui,A
001B EF MOV A,R7
001C 4480 ORL A,#080H
001E F500 R MOV bfui+01H,A
57 1
58 1 y = Get_BF1a;
0020 750000 R MOV y,#00H
0023 E500 R MOV A,bfui+01H
0025 540F ANL A,#0FH
0027 F500 R MOV y+01H,A
59 1 y = Get_BF2a;
0029 E500 R MOV A,bfui
002B C4 SWAP A
002C F8 MOV R0,A
002D 54F0 ANL A,#0F0H
002F C8 XCH A,R0
0030 E500 R MOV A,bfui+01H
0032 C4 SWAP A
0033 540F ANL A,#0FH
0035 48 ORL A,R0
0036 750000 R MOV y,#00H
0039 5407 ANL A,#07H
003B F500 R MOV y+01H,A
60 1 y = Get_BF3a;
003D E500 R MOV A,bfui+01H
003F AE00 R MOV R6,bfui
0041 7807 MOV R0,#07H
0043 ?C0007:
0043 CE XCH A,R6
0044 C3 CLR C
0045 13 RRC A
0046 CE XCH A,R6
0047 13 RRC A
0048 D8F9 DJNZ R0,?C0007
004A FF MOV R7,A
004B EE MOV A,R6
004C 5401 ANL A,#01H
004E F500 R MOV y,A
0050 8F00 R MOV y+01H,R7
61 1 }
0052 22 RET
; FUNCTION test_bitmask (END)
As you can see, the bit masking code is actually 2 bytes longer. If you carefully compare these functions, you'll find that the code generated is nearly identical.
Jon |
Read-Only Author Jon Young Posted 27-May-2002 14:46 GMT Toolset C51 |  RE: Address bits in XDATA Jon Young
Opps, sorry, I picked the wrong flag to test. You are correct, bit fields are inefficient.
It would also be great if the compiler also optimized:
<bitfield> <op> <const> or <const> <op> <bitfield>
Where <op> is ==, !=, <, >, <=, >=, &&, ||
xdata struct
{
char AC_FAIL :1;
char LOW_BAT :1;
} SYSTEM_TROUBLE1 _at_ 0x1000;
void main( void )
{
if( SYSTEM_TROUBLE1.LOW_BAT )
SYSTEM_TROUBLE1.AC_FAIL = 1;
}
; FUNCTION main (BEGIN)
0000 901000 MOV DPTR,#SYSTEM_TROUBLE1
0003 E0 MOVX A,@DPTR
0004 FF MOV R7,A
0005 C3 CLR C
0006 13 RRC A
0007 30E004 JNB ACC.0,?C0002
000A EF MOV A,R7
000B 4401 ORL A,#01H
000D F0 MOVX @DPTR,A
000E ?C0002:
000E 22 RET
; FUNCTION main (END)
|