SSブログ
English Version

独自言語 picle のコンパイラ化(その4) [PIC]

  picle言語 のPIC24FJ用セルフコンパイラの製作を進めています。問題点や状況などを少し書いておきます。
  1. 環境等の問題
    • アプリからのフラッシュ書込未反映
       MPLABX + Pickit3 環境ではテーブルアクセス(TBLWR)を使ってアプリケーションでフラッシュメモリに書き込んだ結果がMPLABX の「Program Memory」に反映されません orz
       念のため MPLABX を最新版(Ver3.26)にして見ましたが状況は同じでした。
       初めは書込み方法が悪いのかと思い、アプリ側を何度も確認しましたがアプリ側の処理は問題無いようにしか見えません^^;
       MPLABX の「Program Memory」で見えないだけで実際にはフラッシュへの書込みができていることに気づきました orz
       従ってディバッグモードを継続したままで生成したマシン語部分をステップ動作させることができません orz
       一旦、ディバッグモードから抜けた後、PIC からフラッシュメモリを吸上げて、開始アドレス指定してステップ動作させることは可能です(めんどいですが・・)

    • CP命令の byte サイズ指定ビット
      「16-bit MCU and DSC Programmer’s Reference Manual((C) 2005-2011 Microchip Technology Inc.)」では下記のように書かれていますが、 MPLABX の「Program Memory」でのニーモニック表示では マシン語コード:0xE1801D のニーモニックが CPB W0,[W13] と表示されます。
       確認のためにCP命令をアセンブラにかけてみると

      000000 1D 80 E1 cpb W0,[W13]
      000002 1D 00 E1 cp W0,[W13]

      となり、MPLABX の方が正解でしたw。今後、リファレンスマニュアルの完成度も考慮して作業を進めていく必要がありそうです。
      (マイクロチップ社のエラータに記載済みか否かは未確認です)

      CP part of the Reference Manual

    • 配列要素のアドレス
       除算の余りがうまく設定されなかったので調査した結果、Cコンパイラの挙動に不思議な点がありました。
      使用しているCコンパイラは XC16 1.26 (A) です。

      #define MODULO_IDX 1
      #define Modulo_ VarVal[MODULO_IDX]

      こんな感じで define し、

      MOV_Ws_f16( W(1), (WORD)(&Modulo_) );

      でW1が保存される先が、0x08d4 でした。 VarVal のアドレスは 0x882 なので変なアドレスに保存されています。

      MOV_Ws_f16( W(1), (WORD)&Modulo_ );

      のように括弧を取ってみたら 期待通りに 0x0884 にW1が保存されました。

       C言語の演算子の優先順位は高い順に
        添字演算子[] > アドレス演算子& > キャスト演算子()
      なので括弧の有無は影響しないはずなのですが・・

       因みに 上記ニーモニックのマクロ定義は

      #define MOV_Ws_f16(Ws,freg) COND {DISP2("MOV W%d,[%xh]",Ws,freg); COND2 \
      FWRITE(0x880000|(((long)freg<<3)&0x7fff0)|Ws);} Flash+=2;

      です。
      ★2016/03/28 追記 {
       下記の「2.コンパイル時の最適化」の改善前後で比較すると改善後の変数のアドレスが 0x50 だけ小さくなっていて上記のズレと一致します。上記のズレはCコンパイラ自身ではなく、makeかリンク機能に起因している可能性があります。そう仮定すると上記の括弧削除は関係なかったことになります・・・(たまに「Cleaning and Build Project」を実行した方が良さそうです)


    • レジスタのアドレスモード(一般的な呼称は「アドレッシングモード」)
       MOV命令等、多くのマシン語コード内に「レジスタのアドレスモード」を指定する3ビットのビットフィールドがありますが、この値とアドレッシングモードとの具体的な対応が「16-bit MCU and DSC Programmer’s Reference Manual」には見当たりませんでした。
       アセンブラで確認してみれば直ぐわかることなのですが確認結果を記載しておきます。
       (「7」の場合の動作に興味が沸いてきますねw)

      // addressing mode value
      #define ADRS_MODE_DIR 0// W direct
      #define ADRS_MODE_INDIR 1// [W] indirect
      #define ADRS_MODE_POST_DEC2// [W--] post dec
      #define ADRS_MODE_POST_INC3// [W++] post inc
      #define ADRS_MODE_PRE_DEC 4// [--W] pre dec
      #define ADRS_MODE_PRE_INC 5// [++W] pre inc
      #define ADRS_MODE_BASE 6// [W+Wb] indirect with base register


  2. コンパイル時の最適化
     今回はPIC でのセルフコンパイルなのでメモリ使用量も極力最小限にしており、また JITコンパイルでは短時間でコンパイルする必要があるので大域的な最適化はしません。
     ステップレベルの最適化としてあまりにも冗長な部分を少し改善してみました。
     前回の その3 で記載したサンプル例との比較が下記です。改善が見られ、まあまあ許せる範囲になってきた感じです ^^
     尚、改善側(右側)の最後の「RETURN」の後に '7' が付いていますが、フラッシュに書込み後、実行しているための出力ですw

    IF文のコンパイル例
    前回(その3)改善後
    :l
    
       1:# if-else sentence test
       2:
       3:proc test( x ) {
       4:   if ( x <> 1 ) {
       5:           PrnDec_( x );
       6:   } else {
       7:           PrnDec_( 5 );
       8:   }
       9:}
      10:
      11:
      12:proc main() {
      13:   test(7);
      14:}
    :run
    
    8000 : MOV W15,[ba0h]
    8002 : MOV #b16h,W13
    8004 : BRA 803ch
    8006 : MOV [ba0h],W15
    8008 : RETURN
    800a : LNK #2
    800c : MOV W0,[W14+0h]
    800e : MOV [W14+0h],W0
    8010 : MOV W0,[++W13]
    8012 : MOV #1h,W0
    8014 : MOV W0,[++W13]
    8016 : MOV [W13--],W1
    8018 : CP  W1,[W13]
    801a : CLR [W13]
    801c : BRA Z,8020h
    801e : INC [W13],[W13]
    8020 : MOV [W13--],W0
    8022 : CP0 W0
    8024 : BRA Z,8030h
    8026 : MOV [W14+0h],W0
    8028 : MOV W0,[++W13]
    802a : MOV [W13--],W0
    802c : RCALL 178eh
    802e : BRA 8038h
    8030 : MOV #5h,W0
    8032 : MOV W0,[++W13]
    8034 : MOV [W13--],W0
    8036 : RCALL 178eh
    8038 : ULNK
    803a : RETURN
    803c : LNK #0
    803e : MOV #7h,W0
    8040 : MOV W0,[++W13]
    8042 : MOV [W13--],W0
    8044 : RCALL 800ah
    8046 : ULNK
    8048 : RETURN
    :
    
    :l
    
       1:# if-else sentence test
       2:
       3:proc test( x ) {
       4:   if ( x <> 1 ) {
       5:           PrnDec_( x );
       6:   } else {
       7:           PrnDec_( 5 );
       8:   }
       9:}
      10:
      11:
      12:proc main() {
      13:   test(7);
      14:}
    :run
    
    8000 : MOV W15,[b50h]
    8002 : MOV #ac6h,W13
    8004 : BRA 802eh
    8006 : MOV [b50h],W15
    8008 : RETURN
    800a : LNK #2
    800c : MOV W0,[W14+0h]
    800e : MOV [W14+0h],W0
    8010 : MOV W0,[++W13]
    8012 : MOV #1h,W0
    8014 : CP  W0,[W13--]
    8016 : CLR W0
    8018 : BTSS [42h],#1
    801a : INC W0,W0
    801c : CP0 W0
    801e : BRA Z,8026h
    8020 : MOV [W14+0h],W0
    8022 : RCALL 17b0h
    8024 : BRA 802ah
    8026 : MOV #5h,W0
    8028 : RCALL 17b0h
    802a : ULNK
    802c : RETURN
    802e : LNK #0
    8030 : MOV #7h,W0
    8032 : RCALL 800ah
    8034 : ULNK
    8036 : RETURN7
    :
    

    ★2016/03/28 追記 改善側を更に1ワード削減


[TOP] [ 前へ ] 連載記事 [ 次へ ]
nice!(0)  コメント(0)  トラックバック(3) 
共通テーマ:趣味・カルチャー

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 3