When the PIC, PIROD, or PID facility is used, the following processes in the startup routine need to be changed.
| 
- | Initialization of base registers | 
| 
- | Initialization of RAM sections | 
 
When the entire program is to be configured as position-independent, it is necessary to jump from the reset vector to a desired position. Therefore, the branch destination address should be written to a specific RAM area or data flash area as an example. To restart the program without shutting off the power supply of the microcontroller, the branch destination address should be stored in a specific register.
 
In the reset vector, the address to be jumped to is acquired and a register indirect branch is executed.
|     cstart_address .set 0xXXXXXXXX    ; Address storing the branch destination                                        ; address to be executed       .section "RESET", text     .align   512     mov cstart_address, r10     ld.w 0[r10], r10     jmp [r10] | 
 
| 
(2) | Initialization of base registers | 
When the PID facility is used, first the means of passing the offset information (hereafter referred to as the RAM offset value), such as how much to shift the allocation position at execution from the start address of the RAM section that was specified at linkage, has to be decided in advance. For example, the RAM offset value should be written to a specific RAM area or data flash area.Note
| 
Note | Since the specific area has to be referenced with an absolute address in this case, the PID or PIROD facility is not supported. | 
 
To restart the program without shutting off the power supply of the microcontroller, the RAM offset value should be stored in a specific register.
The RAM offset value that was received is added to the base register, and this address will be used as the base address at execution.
|     mov      0xfedf0000, r28       ; Memory address for passing RAM offset value     ld.w     0[r28], r28           ; Offset (RAM offset) between data arrangement                                    ; at linkage and data arrangement at execution       mov      #_stacktop, sp        ; set sp register     mov      #__gp_data, gp        ; set gp register     mov      #__ep_data, ep        ; set ep register     add      r28, sp     add      r28, gp     add      r28, ep | 
 
| 
(3) | Initialization of RAM sections | 
The _INITSCT_RH() function cannot be used for initializing sections when the PID facility is used because the section information table is only for input. Due to this, the initial values are to be directly copied in the startup routine.
The offset between the allocation address of the code area or constant data area at linkage and execution is obtained as an advance preparation. Hereafter, this offset is referred to as the ROM offset value.
|     jarl     .pic_base, r29   ; Address of .pic_base label at execution is stored                               ; in r29 .pic_base:     mov      #.pic_base, r10  ; Address of .pic_base label at linkage is stored                                ; in r10     sub      r10, r29         ; Value obtained by subtracting r10 from r29 is the                               ; ROM offset value | 
 
Next, initialization of sections with initial value is performed.
For a section to be initialized, the start and end addresses of the copy source of the initial value and the copy destination address are stored in the r6, r7, and r8 registers, respectively.
|     mov      #__s.sdata32, r6     mov      #__e.sdata32, r7     mov      #__s.sdata32.R, r8 | 
 
When the PIROD facility is used, the ROM offset value is added to the start address (r6 register) and end address (r7 register) of the copy source of the initial value.
 
When the PID facility is used, the RAM offset value is added to the address to which data is copied (r8 register).
 
The copy routine is called here because the preparation for copy is completed.
|     jarl     _copy4, lp ....     ; r6: source begin  (4-byte aligned)     ; r7: source end  (r6 <= r7)     ; r8: destination begin  (4-byte aligned)     .align    2 _copy4:     sub      r6, r7 .copy4.1:     cmp      4, r7     bl       .copy4.2     ld.w     0[r6], r10     st.w     r10, 0[r8]     add      4, r6     add      4, r8     add      -4, r7     br       .copy4.1 .copy4.2:     cmp      2, r7     bl       .copy4.3     ld.h     0[r6], r10     st.h     r10, 0[r8]     add      2, r6     add      2, r8     add      -2, r7 .copy4.3:     cmp      0, r7     bz       .copy4.4     ld.b     0[r6], r10     st.b     r10, 0[r8] .copy4.4:     jmp      [lp] | 
 
Processing up to this point is repeated for the number of sections that require an initial value.
 
Next, sections with no initial value are initialized with 0. The start address and end address of a target section are stored in the r6 and r7 registers, respectively.
|     mov      #__s.sbss32, r6     mov      #__e.sbss32, r7 | 
 
When the PID facility is used, the RAM offset value is added to the start address (r6 register) and end address (r7 register).
 
The initialization routine is called and the target sections are initialized with 0.
|     jarl     _clear4, lp ....     ; r6: destination begin (4-byte aligned)     ; r7: destination end  (r6 <= r7)     .align   2 _clear4:     sub      r6, r7 .clear4.1:     cmp      4, r7     bl       .clear4.2     st.w     r0, 0[r6]     add      4, r6     add      -4, r7     br       .clear4.1 .clear4.2:     cmp      2, r7     bl       .clear4.3     st.h     r0, 0[r6]     add      2, r6     add      -2, r7 .clear4.3:     cmp      0, r7     bz       .clear4.4     st.b     r0, 0[r6] .clear4.4:     jmp      [lp] | 
 
Processing up to this point is repeated for the number of sections that need to be initialized.
 
| 
(4) | Branch to main function | 
When the PIC facility is used and a jump is to be made to the main function with the FERET instruction, the ROM offset value is added to the value that is stored in FEPC.
|     mov      #_exit, lp       ; lp <- #_exit     mov      #_main, r10       add      r29, lp          ; ROM offset value is added     add      r29, r10         ; ROM offset value is added       ldsr     r10, 2, 0        ; FEPC <- #_main                ; apply PSW and PC to start user mode     feret | 
 
Coding example
A coding example for using the PIC, PIROD, or PID facility is shown below.
| $ifdef __PIC   .TEXT .macro     .section .pctext, pctext   .endm $else   .TEXT .macro     .section .text, text   .endm $endif | 
| $ifdef __PID   .STACK_BSS .macro     .section .stack.bss, sbss32   .endm $else   .STACK_BSS .macro     .section .stack.bss, bss   .endm $endif   ;----------------------------------------------------------------------------- ;   system stack ;----------------------------------------------------------------------------- STACKSIZE    .set    0x200     .STACK_BSS     .align   4     .ds      (STACKSIZE)     .align   4 _stacktop:   ;----------------------------------------------------------------------------- ;   startup ;-----------------------------------------------------------------------------     .TEXT     .public  __cstart     .align   2 __cstart:   $ifdef __PIC     jarl     .pic_base, r29 .pic_base:     mov      #.pic_base, r10     sub      r10, r29 $endif   $ifdef __PID     mov      0xfedf0000, r28       ; Memory address for passing RAM offset value     ld.w     0[r28], r28           ; Offset (RAM offset) between data arrangement                                    ; at linkage and data arrangement at execution $endif       mov      #_stacktop, sp        ; set sp register     mov      #__gp_data, gp        ; set gp register     mov      #__ep_data, ep        ; set ep register $ifdef __PID     add      r28, sp     add      r28, gp     add      r28, ep $endif       ; initialize 1 data section $ifdef __PID   $ifdef __PIROD     mov      #__s.sdata32, r6     add      r29, r6     mov      #__e.sdata32, r7     add      r29, r7     mov      #__s.sdata32.R, r8     add      r28, r8 | 
|   $else     mov      #__s.sdata32, r6     mov      #__e.sdata32, r7     mov      #__s.sdata32.R, r8     add      r28, r8   $endif $else   $ifdef __PIROD     mov      #__s.data, r6     add      r29, r6     mov      #__e.data, r7     add      r29, r7     mov      #__s.data.R, r8   $else     mov      #__s.data, r6     mov      #__e.data, r7     mov      #__s.data.R, r8   $endif $endif     jarl     _copy4, lp       ; initialize 1 bss section $ifdef __PID     mov      #__s.sbss32, r6     mov      #__e.sbss32, r7     add      r28, r6     add      r28, r7 $else     mov      #__s.bss, r6     mov      #__e.bss, r7 $endif     jarl     _clear4, lp       ; enable FPU $if 1 ; disable this block when not using FPU     stsr     6, r10, 1         ; r10 <- PID     shl      21, r10     shr      30, r10     bz       .L1               ; detecting FPU     stsr     5, r10, 0         ; r10 <- PSW     movhi    0x0001, r0, r11     or       r11, r10     ldsr     r10, 5, 0         ; enable FPU       movhi   0x0002, r0, r11     ldsr    r11, 6, 0          ; initialize FPSR     ldsr    r0, 7, 0           ; initialize FPEPC .L1: $endif       ; set various flags to PSW via FEPSW       stsr    5, r10, 0          ; r10 <- PSW     ;xori   0x0020, r10, r10   ; enable interrupt     ;movhi  0x4000, r0, r11     ;or     r11, r10           ; supervisor mode -> user mode     ldsr    r10, 3, 0          ; FEPSW <- r10     mov     #_exit, lp         ; lp <- #_exit     mov     #_main, r10 | 
| $ifdef __PIC     add     r29, lp     add     r29, r10 $endif     ldsr    r10, 2, 0          ; FEPC <- #_main       ; apply PSW and PC to start user mode     feret   _exit:     br      _exit              ;  end of program   ;----------------------------------------------------------------------------- ;   copy routine ;-----------------------------------------------------------------------------     ; r6: source begin  (4-byte aligned)     ; r7: source end  (r6 <= r7)     ; r8: destination begin  (4-byte aligned)     .align  2 _copy4:     sub     r6, r7 .copy4.1:     cmp     4, r7     bl      .copy4.2     ld.w    0[r6], r10     st.w    r10, 0[r8]     add     4, r6     add     4, r8     add     -4, r7     br      .copy4.1 .copy4.2:     cmp     2, r7     bl      .copy4.3     ld.h    0[r6], r10     st.h    r10, 0[r8]     add     2, r6     add     2, r8     add     -2, r7 .copy4.3:     cmp     0, r7     bz      .copy4.4     ld.b    0[r6], r10     st.b    r10, 0[r8] .copy4.4:     jmp     [lp]   ;----------------------------------------------------------------------------- ;   clear routine ;-----------------------------------------------------------------------------     ; r6: destination begin (4-byte aligned)     ; r7: destination end  (r6 <= r7)     .align  2 _clear4:     sub     r6, r7 .clear4.1:     cmp     4, r7     bl      .clear4.2     st.w    r0, 0[r6]     add     4, r6     add     -4, r7     br      .clear4.1 | 
| .clear4.2:     cmp     2, r7     bl      .clear4.3     st.h    r0, 0[r6]     add     2, r6     add     -2, r7 .clear4.3:     cmp     0, r7     bz      .clear4.4     st.b    r0, 0[r6] .clear4.4:     jmp     [lp]   ;----------------------------------------------------------------------------- ;   dummy section ;----------------------------------------------------------------------------- $ifdef __PID     .section .sdata32, sdata32 .L.dummy.sdata32:     .section .sbss32, sbss32 .L.dummy.sbss32: $else     .section .data, data .L.dummy.data:     .section .bss, bss .L.dummy.bss: $endif   $ifdef __PIROD     .section .pcconst32, pcconst32 .L.dummy.pcconst32: $else     .section .const, const .L.dummy.const: $endif ;-------------------- end of start up module -------------------; |