Details on compiler behaviour for 8051 bit manipulation



I was investigating my 8051 compiler's (its Hitech 7.6) behaviour
regarding bit manipulation, and came up with some strange/interesting
results. Lets say we want to manipulate PX0, which is the lowest bit in
the IP register. Now, PX0 is defined with

static bit PX0 @ 0xB8;

which is the BIT address 0xB8. And IP_BITS is defined with

static SFR_BITS IP_BITS @ 0xB8;

which is the BYTE address 0xB8. SFR_BITS is a special struct that is
defined with

typedef struct {
unsigned B7:1; /* this is the most significant bit */
unsigned B6:1;
unsigned B5:1;
unsigned B4:1;
unsigned B3:1;
unsigned B2:1;
unsigned B1:1;
unsigned B0:1;
} SFR_BITS;

Now, IP_BITS.B0 also accesses the BIT address 0xB8, that is, exactly
the same as PX0.
Then, I expected that manipulation of IP_BITS.B0 and PX0 would be
totally interchangeble, but it seems they are not. The following test
program illustrates this:

// 8051test.c
#include "8051.h"
void Test()
{
// Self copying in 4 flavours
IP_BITS.B0 = IP_BITS.B0;
IP_BITS.B0 ^= 0;
PX0 = PX0;
PX0 ^= 0;

// Inverting in 4 flavours
IP_BITS.B0 = !IP_BITS.B0;
IP_BITS.B0 ^= 1;
PX0 = !PX0;
PX0 ^= 1;
}

compiles to this:

global stack_internal
psect text,class=CODE
psect text
global _Test
signat _Test,88
_Test:
jmp f861
f860:
;8051test.c: 5: IP_BITS.B0 = IP_BITS.B0;
mov c,ip.0
mov ip.0,c
;8051test.c: 6: IP_BITS.B0 ^= 0;
;8051test.c: 7: PX0 = PX0;
mov c,ip.0
mov ip.0,c
;8051test.c: 8: PX0 ^= 0;
;8051test.c: 11: IP_BITS.B0 = !IP_BITS.B0;
bnb ip.0, u11
jmp u10
u11:
mov r1,#1
sjmp u20
u10:
mov r1,#0
u20:
mov r0,#0
mov a,r1
mov c,acc.0
mov ip.0,c
;8051test.c: 12: IP_BITS.B0 ^= 1;
cpl ip.0
;8051test.c: 13: PX0 = !PX0;
cpl ip.0
;8051test.c: 14: PX0 ^= 1;
cpl ip.0
;8051test.c: 15: }
l2:
ret
f861:
jmp f860
f862 equ 0
end

Note that doint ^=0; will not read/write anything, but doing just =
assignment to itself means reading and then writing back. Question:
Does this corresponds to anything at all in the C standard or the 8051
hardware?

Note also that IP_BITS.B0 = !IP_BITS.B0; compiles to something far more
complicated than all the other 3 inverting statements. Question: Does
this corresponds to anything at all in the C standard or the 8051
hardware?

Feel free to comment on this. However, comments like "its all the same"
is not useful. The BNB and CPL instructions does NOT read the same
thing, if it had been a port pin (compiler behaves the same).

.



Relevant Pages

  • Re: Details on compiler behaviour for 8051 bit manipulation
    ... I expected that manipulation of IP_BITS.B0 and PX0 would be ... totally interchangeble, but it seems they are not. ... Note that IP_BITS.B0 and PX0 both in fact compiles to accessing the BIT ... standard, have to access the whole byte ...
    (comp.arch.embedded)
  • Re: Details on compiler behaviour for 8051 bit manipulation
    ... I expected that manipulation of IP_BITS.B0 and PX0 would be ... totally interchangeble, but it seems they are not. ... That expectation is based on invalid assumptions. ... Does this corresponds to anything at all in the C standard or the 8051 ...
    (comp.arch.embedded)