最近はスタートアップルーチン手書きに嵌まっています。その時に見つけた RX の命令で「おっ!?」となったものがあったのでかる〜くご紹介します。
SSTR命令
C言語におけるスタートアップルーチンでは .bss
セクションを全てゼロ初期化する必要があります。ルネサス社謹製のスタートアップルーチンではここをどう処理しているのかあと思ってみてみたら...
/* bss initialisation : zero out bss */
mov #00h,r2 /* load R2 reg with zero */
mov #_ebss, r3 /* store the end address of bss in R3 */
mov #_bss, r1 /* store the start address of bss in R1 */
sub r1,r3 /* size of bss section in R3 (R3=R3-R1) */
sstr.b
こんな感じです。レジスタの順番が謎ですが、これはこの sstr
命令に起因しています。 _ebss
や _bss
はおなじみリンカスクリプトで定義されているものです。以下のように。
.bss :
{
_bss = .;
*(.bss)
*(.bss.**)
*(COMMON)
*(B)
*(B_1)
*(B_2)
_ebss = .;
_end = .;
} > RAM
以上を鑑みて、上のアセンブリコードは以下の処理をしているのだと推測が付きます。
r2
レジスタに 0 を入れているr3
レジスタに.bss
セクションの末尾アドレスを入れているr1
レジスタに.bss
セクションの開始アドレスを入れている
...とまあここまで来ると「memsetか??」と察しが付きますね。「RX ファミリ ユーザーズマニュアル ソフトウェア編」によると...
とまあドンピシャですね。しかも r3
を更新さえすれば、連続してストリングストア(memset)することが出来ます。
ふとここで気づくのが、「これって C言語の memset
の引数順じゃね?」ということです。すなわち、第1引数に開始アドレス、第2引数に値、第3引数に末尾アドレスを渡しているということです。man
ページによると
名前
memset - ある一定のバイトでメモリー領域を埋める。書式
#include <string.h>void *memset(void *s, int c, size_t n);
説明
memset() は s で示されるメモリー領域の先頭から n バイトを c で埋める。返り値
memset() は s へのポインターを返す。
とのことです。返り値の仕様は異なりますが、引数順はこのとおりですよね。では _memset
の中身を見てみましょう。
...とまあまんまこれを使っています。アーキテクチャが C言語 に寄せてきた、とも考えられそうです。
ところでちょっと違う命令に memcpy
とか言うのがありますよね。その部分も見ていて「ん?」ってなったのでご紹介。
ここに smovf
という命令が使われています。もふもふみたいですね。こんな機能のようです。
これもまんまです。
名前
memcpy - メモリー領域をコピーする。書式
#include <string.h>void *memcpy(void *dest, const void *src, size_t n);
説明
memcpy() はメモリー領域 src の先頭 n バイトを メモリー領域 dest にコピーする。コピー元の領域と コピー先の領域が重なってはならない。重なっている場合は
memmove(3) を使うこと。返り値
memcpy() は dest へのポインターを返す。
というわけで以上、CISC だからこそできる、特殊命令の一部の紹介でした。
アセンブリでLチカ
ARM でやったので、この次にいじっている時間が長いであろう RX でもやってみようとなったのでコードをぺたっと貼るだけで失礼します。まあ、RX ちゃんとも直接お話したいよね。
CMT (コンペアマッチタイマ)ですが、やはりコンペアマッチ値レジスタの値が端数だと上手くカウントしてくれなかったり、色々癖があるようです(多分。それか日頃の行いが悪いから?)。ですがチカチカ出来たので良いということにします。
コメント
RX220のCMTならPeripheral Driver Generator v2というツールを使うと比較的楽にタイマーの動作を確認しながらパラメータを決められるかもしれません。
私はRX62NのMTUやRX210のRSPIを利用するにあたりこのツールを使って動作を把握しました。
コード生成まで使うと巨大なライブラリ(Renesas Peripheral Driver Library)がリンクされるのでパラメータだけ参考にするといいかもしれません。
e2studioやCS+のコード生成ツールにも似たような機能が入っているとは思うのだけれどそちらは調べてません。
コメント有難うございます!
PDGは視覚的にわかりやすいツールですよね。クロックの分周やタイマのPWM値等目で見てその挙動が分かるのはとても嬉しいです。多分STM32のCubeMX等でもこのようなわかりやすい表示はないと思います。
実際にコードを生成してみましたが関数のトレースが億劫になってしまい進捗はありません。
暇ができ次第、また気が向き次第調査していこうとは思います。ありがとうございました。
ご存じかもですが、Z80 LDIR で検索してみては?
実はZ80、まだ未開拓なんです。古いトラ技を買ったりとやる気はあるんですが、まだ手が出せていません。
この LDIR 命令、まさに memcpy() なんですね!勉強になりました。
現状Z80はシミュレータ的なのをいじっただけなのですが、知りませんでした〜