PXレジスタを経由したポート出力はできましたが、今度はポート入力を考えてみます。やはりPXレジスタを読むアセンブラコードを書かなければなりませんがasm()文では引数でそのあたりの制御ができるようです。
ここでは以下のように記述しました。”=a”はAX系レジスタを経由してCの変数resultに代入することを指定します。
asm("%0=px;":"=a"(result));
これを使ってLCDの制御関数を記述してみました。データレジスタに出力するlcd_dat()はLEDのポートに出力する関数と同じ作りです。その中でLCDのステータスレジスタを読んでBUSYフラグが落ちるのを待つlcd_wait()でPXレジスタの読み取りをやっています。
このlcd_wait()ルーチンが最初はうまく動作せずちょっと悩みました。BUSYフラグを全くチェックせずに即時リタンしてしまうので初期化がうまくいかなかったり文字列が歯抜けして表示したりしたのですが、これはCの変数dumy,resultがC言語自体のルーチンの中では代入だけして参照しない、代入せずに参照するなどで最適化によって行ごと削除されてしまったためでした。つまりlcd_wait()の中身自体が何もしてないとみなされて中が空っぽになってしまいます。ここは変数dumy,resultをvolatile 宣言して最適化で消されないようにします。
できあがったlcd_wait()をコンパイルしたアセンブリ中間ファイルはこのような感じです。関数の入口・出口処理:FUNCTION PROLOGUE、FUNCTION EPILOGUEは省いていますがそれでもかなり迂遠なコードを出力しています。80系のアセンブラ直書きなら2~3行で済んでしまうところですが、そもそもDSPにトロトロ遅いヒューマンI/Fを処理させていること自体かわいそうなのかもしれません。