Specifying the Register Bank for a Function

The lowest 32 bytes of all members of the 8051 family are grouped into 4 banks of 8 registers each. Programs can access these registers as R0 through R7. The register bank is selected by two bits of the program status word (PSW).  Register banks are useful when processing interrupts or when using a real-time operating system. Rather than saving the 8 registers, the CPU can switch to a different register bank for the duration of the interrupt service routine.

The using function attribute is used to specify which register bank a function uses. For example:
void rb_function (void) using 3
{
.
.
.
}

The using attribute takes as an argument an integer constant in the value range 0 to 3. Expressions with operators are not allowed, and the using attribute is not allowed in function prototypes. The using attribute affects the object code of the function as follows:

    The currently selected register bank is saved on the stack at function entry.

    The specified register bank is set.

    The former register bank is restored before the function is exited.

The following program example shows you how to specify the using function attribute and what the generated assembly code for the function entry and exit looks like.

.
.
.
stmt level source
1
2 extern bit alarm;
3 int alarm_count;
4 extern void alfunc (bit b0);
5
6 void falarm (void) using 3 {
7 1 alarm_count++;
8 1 alfunc (alarm = 1);
9 1 }
.
.
.
ASSEMBLY LISTING OF GENERATED OBJECT CODE
; FUNCTION falarm (BEGIN)
0000 C0D0 PUSH PSW
0002 75D018 MOV PSW,#018H
; SOURCE LINE # 6
; SOURCE LINE # 7
0005 0500 R INC alarm_count+01H
0007 E500 R MOV A,alarm_count+01H
0009 7002 JNZ ?C0002
000B 0500 R INC alarm_count
000D ?C0002:
; SOURCE LINE # 8
000D D3 SETB C
000E 9200 E MOV alarm,C
0010 9200 E MOV ?alfunc?BIT,C
0012 120000 E LCALL alfunc
; SOURCE LINE # 9
0015 D0D0 POP PSW
0017 22 RET
; FUNCTION falarm (END)
.
.
.

In the previous example, the code starting at offset 0000h  saves the initial PSW  on the stack and sets the new register bank. The code starting at offset 0015h  restores the original register bank by popping the original PSW  from the stack.

The using attribute should not be used in functions that return a value in registers. You must exercise extreme care to ensure that register bank switches are performed only in carefully controlled areas. Failure to do so will yield incorrect function results. Even when you use the same register bank, functions declared with the using attribute cannot return a bit value.

Typically, the using attribute is most useful in functions that also specify the interrupt attribute. It is most common to specify a different register bank for each interrupt priority level. Therefore, you could use one register bank for all non-interrupt code, one for the high level interrupt, and one for the low level interrupt.