FC2ブログ

ビット処理はunionで案外イケそう・・・

2012-12-10      
 この記事、縦にやたらと長いです

 プログラム開発のC言語化について、既存のMPASMのソースプログラムは、単純にXC8の持つ「Macro Assembler」に移植すれば済むわけですが、そんなに超高速なプログラムを作っても仕方がないことや、XC8の無償版でも案外綺麗にコンパイルしてくれそうなこと(=objがそんなに大きくならないこと)などから、ポート処理には欠かせないビット演算がそれなりの範疇に収まるようなら、殆どC言語ベースの方が後々楽だろう・・・という風に、「アセンブラ遣い」を返上した序でにもっと手を抜いてしまおうと思うに至りました。

 そこで、C言語の共用体宣言を以下のように組み、どんなニーモニック(これを逆アセンブルすれば、アセンブラのソースになります)になるかを確かめてみました。

typedef union {
    struct {
        unsigned B0    :1;        // 1ビット毎
        unsigned B1    :1;
        unsigned B2    :1;
        unsigned B3    :1;
        unsigned B4    :1;
        unsigned B5    :1;
        unsigned B6    :1;
        unsigned B7    :1;
    };
    struct {
        unsigned BL    :4;        // 4ビット毎
        unsigned BH    :4;
    };
    unsigned char BT;          // 8ビット丸ごと
} BIT_t;

 この共用体では、8ビットの符号無し変数を「1ビット単位」「4ビット単位」「8ビット丸ごと」でアクセスできるようになりますが、これに追随して、

 ・1ビット単位:bsf,bcf に置き換わる
 ・4ビット単位:swapfに置き換わる

という部分が綺麗に行くなら、多少の無駄を覚悟して「ほぼオールC言語」に持っていけるかな というわけです。

 コンパイラは勿論XC8。ソースファイル名は「lcd.c」としていますが、気にしないでください コンパイル結果をまとめてみましょう。
 なお、前提として「REG_HL」という変数を以下のように「7f 番地」に定義しています。

★extern volatile BIT_t REG_HL @ 0x7f;

  ◆ 役割の決まったレジスタは特別扱い

 PORTAやSTATUSといったPICの構成要素として役割が決まっているレジスタは、即値のセットにおいてもそのまま最適に設定されますから、ここはよくできている部分ですね。

;lcd.c: 65: PORTA = 0x0a;
    movlw    (0Ah)
    movwf    (12)    ;volatile

 ちなみに、アドレスを指定した変数にすれば上記PORTAの場合と同じかなぁ・・・と思ったら、「無駄な2ステップを暴いた記事」に示した通り(この記事の変数bbの展開形をご覧あれ)、余計な2ステップがもれなく付いてきます

;lcd.c: 67: REG_HL.BT = 0x0a;
    movlw    (0Ah)
    movwf    (??_lcd_cmd+0)+0 ←これと
    movf    (??_lcd_cmd+0)+0,w ←これ
    movwf    (127)    ;volatile

 う~ん、残念・・・。

 ◆ 1ビットのON/OFFはイイ感じ

 これは、PORTAだろうが自分で指定した固定アドレスの変数であろうが、上記のunionできちんと最適な機械語・・・つまり1ステップのアセンブラ命令にコンパイルされます。例えば、以下のような感じです。

;lcd.c: 69: REG_HL.B1 = 1;
    bsf    (127),1    ;volatile

 全く無駄がない というわけで、1ビットのON/OFFは、C言語表現のままで良さそうです。

 ◆ 4ビット一括設定もまずまず・・・

 4ビットの設定は、LCDを4ビットモードで動かすことが多いことから多用されますので、きちんと片付けておきたいところです。どのポートにアサインされるかは、ハード設計仕様に依存しますから固定的では不味いのですが、何れにせよ「どこかのポート」になりますよね。
 そこで、一捻りして「PORTx にBIT_t を被せる」という形で、4ビット一括で扱えるようにしました。
 
★extern volatile BIT_t LCD_DT_PORT @ (&PORTA);
 
 これで、「LCD_DT_PORT.BH」と「LCD_DT_PORT.BL」で、各々PORTAの上位4ビット/下位4ビットが扱えます。

;lcd.c: 71: LCD_DT_PORT.BH = 0x04;
    movf    (12),w    ;volatile
    andlw    not (((1<<4)-1)<<4)
    iorlw    (04h & ((1<<4)-1))<<4
    movwf    (12)    ;volatile

 セオリー通り、PORTAから読み取ったデータの上位に「0x04」を設定して書き戻してますね。これも合格です。ちなみに、自分で指定した固定アドレスの変数も同じ展開形でした。

 ◆ 4ビットのハイ・ロー

 これもLCDの処理では定番に当たるかも知れませんが、8ビットの上位4ビット⇒下位4ビットの順で出力する場合があります。PICのアセンブラ命令の「swapf」は、この処理に最適なんですが、果たしてC言語で表現した場合、この命令を使って効率的な機械語が吐き出されるか・・・。

;lcd.c: 74: LCD_DT_PORT.BL = REG_HL.BH;
    swapf    (127),w    ;volatile
    andlw    (1<<4)-1
    movwf    (??_lcd_cmd+0)+0
    movf    (12),w    ;volatile
    xorwf    (??_lcd_cmd+0)+0,w
    andlw    not ((1<<4)-1)
    xorwf    (??_lcd_cmd+0)+0,w
    movwf    (12)    ;volatile

 ちょいと冗長・・・でも、論理演算を使って上手く処理していると思います。やはり変数「(??_lcd_cmd+0)+0」に纏わる部分がもたついてますね。
 ただ、この上位⇒下位の出力処理があちこちにあるわけではないため、そんなに目くじらを立てなくても良いかも知れません。

 ◆ オマケ・・・

 LCD制御にはストローブを与える必要がありますが、これもちょっとマクロで作ってみました。

extern volatile BIT_t LCD_E_PORT @ (&PORTB);
#define LCD_E   LCD_E_PORT.B2

#define    nop    asm("nop")
#define toggle { LCD_E = 1; nop; LCD_E = 0; }

 これでC言語1ラインでストローブ処理「toggle」が使えるようになりました。この部分の展開形を参考に。どういうわけかバンク指定が入ってしまいますが、まぁ良しとしました。

;lcd.c: 67: { LCD_E_PORT.B2 = 1; asm("nop"); LCD_E_PORT.B2 = 0; };
    bsf    (13),2    ;volatile
    nop ;#
    movlb 0    ; select bank0
    bcf    (13),2    ;volatile

 ◆ 結果的には

 LCDにコマンドを送る処理をアセンブラで記述したサブルーチンが24ステップ。一方、上記を駆使して作ったC言語の関数が吐き出した機械語が36ステップ・・・約1.5倍になりました。これが多いのか少ないのかの議論とは別に、C言語のソースライン数は何と8行 これは、圧倒的に見通しが良い処理になりましたから、ひとまずこの調子でC言語ベースのLCDドライバを完成させ、既に動いているアセンブラ版と比較してみようと思います。

 どんどん方針が変わるって いいのいいの、仕事じゃないんだから
関連記事

コメントの投稿

非公開コメント

Calendar
08 | 2019/09 | 10
Sun Mon Tue Wed Thu Fri Sat
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 - - - - -
New !
Category
Comments
Monthly Archives
Track Backs
Counter
Sunspot Now !

 


Survey Results

 

Profile

どよよん無線技士

Author :どよよん無線技士
こおるさいん:JM1DPL

アパマンというハンデにさらにQRPまで課し、失敗連続のヘッポコリグや周辺機器の製作・・・趣味というより「荒行」か!?

メールは「JARL経由」でお願いします。

Links
Follow me !
RSS Links
QR Code
QR