switch 文使用時の挙動 (最適化なし時)

お世話になります。

以下プログラムで、

ビルドツールの設定を最適化なし

E2Liteを使いRL78/G13の実チップにてデバッグ(自動生成ツールの設定=デバッグあり)

ブレーク設定を①、②に設定

 にて試しているのですが、

①で、停止後、F5で実行をすると、②で停止する予定が停止せず、

また①に戻ってしまいます(リセットしてしまう)

  ※シミュレータでは、ちゃんと②で停止します。

 

void main1(void)  //自動生成コードmain からの飛び先

{
unsigned char v,x;
    v=1;     //①
    switch(v){
        case 0:x=x+1;break;
        case 1:x=x+1;break;
        case 2:x=x+1;break;
        case 3:x=x+1;break;
        case 4:x=x+1;break;
    }
    while(1){
        x=x+1;     //②
    }
 }

調べると、switch 文は、最適化なしでは、テーブルジャンプコードに

生成されるようで、以下 逆アセンブルの③のところで、BR AX  (AXレジスタで示すアドレスにジャンプ)

するはずが、AXの値が0のままになってしまっています。よって、0番地にジャンプするので、リセット時

同様の挙動になってしまう。この理由がわからず困っています。宜しくお願い致します。

void main1(void)

{

_main1:
c7 PUSH HL
c1 PUSH AX
fbf8ff MOVW HL,SP

unsigned char v,x;

v=1;

cc0101 MOV [HL+1H],#1H
switch(v){

e1 ONEB A
318e SHRW AX,8H
440500 CMPW AX,#5H
de24 BNC $_main1+0x34
12 MOVW BC,AX
490a20 MOV A,200AH[BC]
311c SHLW BC,1H
9efc MOV CS,A
790020 MOVW AX,2000H[BC]
61cb BR AX    ;<<<<<<<<<<<<<<<<<③

 

case 0:x=x+1;break;

8b MOV A,[HL]
81 INC A
9b MOV [HL],A
ef12 BR $_main1+0x34
case 1:x=x+1;break;

8b MOV A,[HL]
81 INC A
9b MOV [HL],A
ef0d BR $_main1+0x34
case 2:x=x+1;break;

8b MOV A,[HL]
81 INC A
9b MOV [HL],A
ef08 BR $_main1+0x34
case 3:x=x+1;break;

8b MOV A,[HL]
81 INC A
9b MOV [HL],A
ef03 BR $_main1+0x34
case 4:x=x+1;break;

8b MOV A,[HL]
81 INC A
9b MOV [HL],A
}

 

while(1){

 

x=x+1;

8b MOV A,[HL]
81 INC A
9b MOV [HL],A
}

effb BR $_main1+0x34

 

}

c0 POP AX
c6 POP HL
d7 RET

  • > 逆アセンブルの③のところで、BR AX (AXレジスタで示すアドレスにジャンプ)
    > するはずが、AXの値が0のままになってしまっています。よって、0番地にジャンプ

    見た感じ、

    > 790020 MOVW AX,2000H[BC]

    AXにミラー領域を通してジャンプ先の下位16ビットを取得して

    > 61cb BR AX    ;<<<<<<<<<<<<<<<<<③

    ジャンプしてるようなので、AXが0になるのだとしたらミラー領域が間違ってる可能性が高いと思います。マイコンの種類の設定を間違えてミラー領域が正しくない番地になってるのでは。

    あと直接関係ないとは思いますが

    > unsigned char v,x;
    > v=1;     //①
    > switch(v){
    > case 0:x=x+1;break;

    変数 x の値が未初期化操作してしまっており、未定義動作を踏んでいます。
  • コメントありがとうございます。
    >AXが0になるのだとしたらミラー領域が間違ってる可能性が高いと思います。
    確かにそうなのかと思うのですが、
    以下の④のところにアセンブラ命令レベルでブレーク設定して、ステップ実行
    すると、AXには、ジャンプ先アドレスが転送され、③のジャンプが成功するの
    で混乱しています。④のブレーク設定せず実行する場合NG、E2Liteなしの、
    HEX書き込みでもNGでした。

    x未定義ご指摘の通りです。


    790020 MOVW AX,2000H[BC] <④
    61cb BR AX    ;<<<<<<<<<<<<<<<<<③
  • マイコンの種類の設定は確認されましたか?
  • > AXの値が0のままになってしまっています。よって、0番地にジャンプするので、リセット時同様の挙動になってしまう。

    RL78 の 0番地はリセットベクタでありプログラムの開始番地ではないので、仮にそこへ分岐したとしてもリセット時同様の挙動になるとは限りません。不正命令やパリティエラーかなんかでソフトウェアリセットが掛かっているのを 0番地に分岐したと誤解されてはいませんか?
  • nyanさん、こんにちは。NoMaYと申します。

    以下の③でAXがゼロになるのであれば、その前の命令の実行の時、BCレジスタ値と(BC+0x2000)番地のメモリ値がどうなっているか知りたいです。CS+(だと思われますが)の画面コピーを見せて頂けませんか?

    > 790020 MOVW AX,2000H[BC]
    > 61cb BR AX    ;<<<<<<<<<<<<<<<<<③

  • ご指摘のマイコン型番ですが、改めて確認したところ、現物は、ROM96K品、CS+の設定は64Kでした。
    これが、原因かもしれません。64Kの現物入手して確認してみます。
    >RL78 の 0番地はリセットベクタであり・・・・・・
    アセンブラレベルで0番地にジャンプする前の以下の④でブレークして確認していますので、
    多分その線は無いかと思います。
    また、CS+デバッガでCPUリセット直後に、PC値を main1のアドレスに設定しても同じ挙動を
    示しますので、割り込み関連のベクタ設定ミスでは無いと判断しました。

    790020 MOVW AX,2000H[BC] <④
  • > ご指摘のマイコン型番ですが、改めて確認したところ、現物は、ROM96K品、CS+の設定は64Kでした。

    > これが、原因かもしれません。

    RL78/G13 の ROM96kB の製品はミラー領域の開始がF3000H、64kB の製品はF2000Hなのでそれが原因でしょう。

    > 64Kの現物入手して確認してみます。

    フツーは CS+ の設定を修正変更するところだと思います。

  • > >RL78 の 0番地はリセットベクタであり・・・・・・
    > アセンブラレベルで0番地にジャンプする前の以下の④でブレークして確認していますので、
    > 多分その線は無いかと思います。

    ハードウェアマニュアル見れ
  • nyanさん、こんにちは。NoMaYです。

    追加ですが、同じ時のシミュレータでの画面コピーも見たいです。

    > 以下の③でAXがゼロになるのであれば、その前の命令の実行の時、BCレジスタ値と(BC+0x2000)番地のメモリ値がどうなっているか知りたいです。CS+(だと思われますが)の画面コピーを見せて頂けませんか?
    > > 790020 MOVW AX,2000H[BC]
    > > 61cb BR AX    ;<<<<<<<<<<<<<<<<<③

  • お騒がせしました。96K品のミラー領域3000H~というのを軽視していました。
    CS+側設定96K設定にしたところ、AX,3000H [BC]にコード生成され、問題なく
    実行できるようになりました。

    cefc00 MOV CS,#0H
    790030 MOVW AX,3000H[BC]  <<<<<<
    61cb BR AX

    fujita nozomu 様ありがとうございました。
  • NoMaY さん
    すみません、CS+のROM設定を直したところ解決しました。
    BCの値ですが、0002 となっていました。
    BCレジスタ値は、実機、シミュレータとも同一でした。
    判ったことは、実ROM96Kなのに、CS+ 64K設定の場合、
    CS+デバッガでステップ実行だと何故か、F2000H-F3000Hの
    エリアも参照できるため、正常に実行できる。
    しかし、RUNで一気に動かすと参照できず0番地の飛んで
    しまう(本来こちらが正しい動作)の為、嵌ってしまいま
    した。ステップ実行でもF2000H-F3000Hの参照が出来なけれ
    ばもっとはやく解決したと思いますが。まーその前に設定
    の間違いが無ければ問題にならなかったのですが。
    お騒がせしました。
  • nyanさん、こんにちは。NoMaYです。

    あっ、違うかも、、、 もう少し考えてから、後でリプライします、、、

    たぶんですが、補足すれば、以下でしょうかね、、、

    CS+デバッガ ⇒ CS+デバッガのシミュレータ
    本来こちらが正しい動作 ⇒ シミュレータの動作の期待値(実デバイスと同じであるべきだと思うから)

    > CS+デバッガでステップ実行だと何故か、F2000H-F3000Hの
    > エリアも参照できるため、正常に実行できる。
    > しかし、RUNで一気に動かすと参照できず0番地の飛んで
    > しまう(本来こちらが正しい動作)の為、

  • nyanさん、こんにちは。NoMaYです。

    こういうことだったのかな、と思いました、、、

    (A) コンパイラ設定:ROM=64K(MIRROR=F2000H~) & シミュレータ設定:ROM=64K(MIRROR=F2000H~)
    動作して当然である筈であり、実際、nyanさんの手元で動作した

    (B) コンパイラ設定:ROM=64K(MIRROR=F2000H~) & ハードウェアデバッガ設定:ROM=64K(MIRROR=F2000H~)

    (B-1) もしもデバッグに使用した実デバイス:ROM=64K(MIRROR=F2000H~)だったなら
    動作して当然である筈であり、きっと、nyanさんが該当実デバイスを入手して試したら動作すると思われる

    (B-2) しかしデバッグに使用した実デバイス:ROM=96K(MIRROR=F3000H~)だった
    動作しなくて当然といえば当然であり、実際、nyanさんの手元で動作しなかった

    nyanさんの投稿から推測すると

    此の実デバイスでF2000H~F2FFFHをリードするとゼロがリードされる
    (というか此の実デバイスではF2000H~F2FFFHはデータフラッシュメモリ(リセット解除後は停止状態)の領域ですね)

    よって

    790020 MOVW AX,2000H[BC] → BC+2000H=2002HならF2002H番地が読み出されてAX=0となる
    61cb   BR AX → AX=0となったのだから0番地へジャンプする

    以後推測です(fujita nozomu氏が言いたかったことなのかもと思います)

    0番地はリセットベクタが書かれているのだが、0番地からを命令コードとして実行

    どんどんと実行していくうちに安全機能設定によりリセットを発生させるような命令を実行
    (というか安全機能設定が全OFFでも命令コード0xFFを実行すると実デバイスでは(デバッグ時以外は)リセットが発生します)

    リセットが発生

    リセットルーチンの先頭から実行

    main1()の先頭の①に戻る

     

  • NoMaY さん
    解説ありがとうございます。
    その通りだと思います。