8.6.6 スタートアップ・ルーチン

PIC,PIROD機能やPID機能を使用する場合,スタートアップ・ルーチン内の次の処理を変更する必要があります。

-

リセット・ベクタ

-

ベース・レジスタ初期化

-

RAMセクションの初期化

-

main関数への分岐

 

(1)

リセット・ベクタ

プログラム全体を位置独立として構成する場合は,リセット・ベクタから任意の位置に分岐させる必要があります。このため,例えば,特定のRAM領域や,データ・フラッシュ領域に,分岐先アドレスを書き込んでおきます。または,マイコンの電源を遮断しないでプログラムを再起動する場合は,特定のレジスタに分岐先アドレスを格納しておきます。

 

リセット・ベクタでは,分岐したいアドレスを取得して,レジスタ間接分岐を実行します。

    cstart_address .set 0xXXXXXXXX    ; 実行したい分岐先アドレスを格納しているアドレス
 
    .section "RESET", text
    .align   512
    mov cstart_address, r10
    ld.w 0[r10], r10
    jmp [r10]

 

(2)

ベース・レジスタ初期化

PID機能を使用する場合は,まず事前に,リンク時に指定したRAMセクションの開始アドレスから,実行時にどれだけずらして配置するか,のオフセット情報(以降RAMオフセット値と呼びます)を,受け渡す手段を決めておきます。例えば,特定のRAM領域や,データ・フラッシュ領域にRAMオフセット値を書き込んでおきます。

この場合,その特定の領域は絶対アドレスで参照する必要があるため,PID,PIROD機能の対象外になります。

 

または,マイコンの電源を遮断しないでプログラムを再起動する場合は,特定のレジスタにRAMオフセット値を格納しておきます。

受け取ったRAMオフセット値を,ベース・レジスタに加算して,実行時のベース・アドレスとして使用します。

    mov     0xfedf0000, r28          ; 受け渡し用のメモリのアドレス
    ld.w    0[r28], r28              ; リンク時のデータ配置と,実行時のデータ配置の間の
                                     ; オフセット(RAMオフセット)
 
    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)

RAMセクションの初期化

_INITSCT_RH()関数はセクション情報のテーブルが入力であるため,PID機能使用時のセクション初期化には使用できません。そこで,スタートアップ・ルーチン内で直接初期値をコピーします。

事前準備として,コード領域,定数データ領域の,リンク時と実行時の配置オフセットを求めます。以降ROMオフセット値と呼びます。

    jarl    .pic_base, r29   ; r29に実行時の.pic_baseラベルのアドレスを格納する
.pic_base:
    mov     #.pic_base, r10  ; r10にリンク時の.pic_baseラベルのアドレスを格納する
    sub     r10, r29         ; r29 - r10 の値が,ROMオフセット値になる

 

次に,初期値ありセクションの初期化を行います。

初期化の対象となるセクションの,初期値のコピー元の先頭アドレス,終端アドレス,コピー先アドレスをr6,r7,r8レジスタに格納します。

    mov     #__s.sdata32, r6
    mov     #__e.sdata32, r7
    mov     #__s.sdata32.R, r8

 

PIROD機能を使用している場合,初期値のコピー元の先頭アドレス,終端アドレス(r6,r7レジスタ)に,ROMオフセット値を加算します。

    add     r29, r6
    add     r29, r7

 

PID機能を使用している場合,データのコピー先アドレス(r8レジスタ)にRAMオフセット値を加算します。

    add     r28, r8

 

ここまででコピーの準備ができたので,コピールーチンを呼び出します。

    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]

 

ここまでの処理を,初期値が必要なセクションの数だけ繰り返します。

 

次に,初期値無しセクションを0で初期化します。対象セクションの先頭アドレス,終端アドレスを,r6,r7レジスタに格納します。

    mov     #__s.sbss32, r6
    mov     #__e.sbss32, r7

 

PID機能を使用している場合,先頭アドレス,終端アドレス(r6,r7レジスタ)にRAMオフセット値を加算します。

    add     r28, r6
    add     r28, r7

 

初期化ルーチンを呼び出して,対象セクションを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]

 

ここまでの処理を,初期化が必要なセクションの数だけ繰り返します。

 

(4)

main関数への分岐

PIC機能を使用していて,FERET命令でmain関数へ分岐する場合,FEPCに格納する値にROMオフセット値を加算します。

    mov     #_exit, lp        ; lp <- #_exit
    mov     #_main, r10
 
    add     r29, lp           ; ROMオフセット値を加算
    add     r29, r10          ; ROMオフセット値を加算
 
    ldsr    r10, 2, 0         ; FEPC <- #_main
 
            ; apply PSW and PC to start user mode
    feret

 

コーディング例

PIC,PIROD,PID機能使用向けのコーディング例を次に示します。

$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          ; 受け渡し用のメモリのアドレス
    ld.w    0[r28], r28              ; リンク時のデータ配置と、実行時のデータ配置の間の
                                     ; オフセット(RAMオフセット)
$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 -------------------;