Everything
4.2.6.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.

CC-RH is capable of detecting writing to control registers and displaying information on the writing process, as well as inserting synchronization processing of a fixed form.

 

Code indicating access to control registers will be detected when all of the following conditions are satisfied.

-

An expression shall cast a single integer constant to a pointer to a volatile qualifier and indirectly reference it with the unary * operator or -> operator.

*(volatile int*)0xffff0000 = x;
((volatile struct ST*)0xffff0004)->member = y;

In this case, the integer constant indicates the address of the control register.

An expression including a variable instead of a constant integer or an expression including multiple casts may not be detected.

-

The above integer constant shall be within the range specified by #pragma register_group.

 

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

 

How to detect writing to control registers and insert synchronization processing is described below, based on the following example of input source code.

Example of input source code

#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)

How to detect writing to a control register

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)

Note that synchronization processing is determined to be necessary even in cases where writing to a control register is followed by a function call or access to an unknown address in memory that cannot be detected as writing to a control register.

(b)

How to detect all writings to control registers

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)

How to insert synchronization processing after writing to a control register

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.

-

Successive writing to control registers belonging to the same group may not be detected in certain circumstances. In such a case, CC-RH may output incorrect detection messages or insert unnecessary synchronization processing.