4.2.4.14 Detection of writing to control registers or insertion of synchronization processing [Professional Edition only] [V1.06.00 or later]

When multiple control registers are updated continuously by a store instruction of the RH850, the order in which the control registers are updated may not match the order in which they were written to the source file. Synchronization processing needs to be inserted in order to control the order in which the control registers are updated.

In CC-RH, continuous writing to control registers can be detected and information of the writing process can be displayed or a fixed synchronization processing can be inserted.

Specify the address range and group information of control registers with #pragma register_group.

Specify #pragma register_group in the following format.

#pragma register_group start-address, end-address[, id="group-ID"]

-

Specify the start address and end address with unsigned integers. An octal, decimal, or hexadecimal integer can be used.

The end address is treated as its address belongs to the group.

Example

Specify a 16-byte area starting from address 0x100 as follows:

#pragma register_group 0x100, 0x10f

-

The group-ID is an identifier for specifying the group to which the control register belongs.

The usable characters for the group-ID are only alphabetic characters (a-z or A-Z; case-sensitive), numbers (0-9), and underscore (_).

The length of the group-ID is not limited.

-

To specify the same group which is not continuous in the address space, the same group-ID can be specified in more than one #pragma register_group directive.

-

The group-ID can be omitted. If omitted, writing to that area is treated as an operation that is not continuous with any other write operations.

-

An error will be output in any of the following cases.

-

When the start address is larger than the end address

-

When an unusable character for the group-ID is used

-

When the address ranges specified in multiple #pragma register_group directives overlap with each other

 

Example

#pragma register_group 0xfedf0000, 0xfedfffff, id="CPU"
#pragma register_group 0xfee00000, 0xfee0ffff, id="0"
 
#define REG1 (*(volatile unsigned char*)0xfedf0000)    /* Control register of group "CPU" */
#define REG2 (*(volatile unsigned char*)0xfedf0001)    /* Control register of group "CPU" */
#define REG_Z (*(volatile unsigned short*)0xfee00000)  /* Control register of group "0" */
 
void func(void) {
   REG1 = 0;
   REG2 = 1;
   REG_Z = 2;
}

(a)

If the above example is compiled with the -store_reg=list option specified, write operations are determined as shown below and a message indicating that writing was performed is output to the standard error output.

-

Since REG1 and REG2 belong to the same group, synchronization processing does not need to be applied to writing to REG1.

-

Since REG2 and REG_Z belong to different groups, synchronization processing needs to be applied to writing to REG2.

-

Since whether there is writing to the same group after writing to REG_Z is not clear, synchronization processing needs to be applied to writing to REG_Z.

src.c(10):M0536001:control register is written.(id=CPU, 0xfedf0001)
src.c(11):M0536001:control register is written.(id=0, 0xfee00000)

(b)

If the same example is compiled with the -store_reg=list_all option specified, a message is output for writing to all of the control registers specified by #pragma register_group without determining whether continuous writing to the same group is performed.

src.c(9):M0536001:control register is written.(id=CPU, 0xfedf0000)
src.c(10):M0536001:control register is written.(id=CPU, 0xfedf0001)
src.c(11):M0536001:control register is written.(id=0, 0xfee00000)

(c)

If the same example is compiled with the -store_reg=sync option specified, write operations are determined in the same manner as (a) and synchronization processing is inserted in the output code instead of a message being output. In synchronization processing, a combination of loading from the same control register and syncp instruction is output.

Output example

_func:
        .stack _func = 0
        movhi 0x0000FEDF, r0, r2
        st.b r0, 0x00000000[r2]
         ; Synchronization processing is not inserted because writing to the 
         ; same group occurs later.
        movhi 0x0000FEDF, r0, r2
        mov 0x00000001, r5
        st.b r5, 0x00000001[r2]
        ld.bu 0x00000001[r2], r10  ; Synchronization processing is inserted.
        syncp                      ;
 
        movhi 0x0000FEE0, r0, r2
        mov 0x00000002, r5
        st.h r5, 0x00000000[r2]
        ld.hu 0x00000002[r2], r10  ; Synchronization processing is inserted.
        syncp                      ;
        jmp [r31]

[Caution]

-

When #pragma register_group is used with the -Xmerge_file option at the same time, even though a #pragma register_group directive that is incompatible between source files is specified, an error will not occur and the result may be unintended. It is recommended to include #pragma register_group in the include file and share it between source files.

-

If there is a possibility that an exception will occur between writing to a control register and the synchronization processing, manually write the synchronization processing in the exception handler as necessary.