GR-SAKURA で遊んでみる(1)

以前オープンソースカンファレンス 2012 Kansai@Kyoto に立ち寄った際、GR-SAKURA ボードの紹介をみて興味を持ったのだが、結局何もしないまま二年が経過してしまった。
ブースでお話を伺った方からは「このボードでどんなことをしてみたいですか?」と尋ねられ、「とりあえず何かしら遊んでみたい」と答えたのに...

しかし、先日日本橋共立電子に立ち寄ったところ、GR-SAKURA が販売されているのを見掛けた。

二種類の GR-SAKURA

SDカードソケット、LANコネクタ、DCジャック、ピンソケットが実装済の GR-SAKURA-FULL と、未実装の GR-SAKURA の二種類が販売されていた。
前者は 5,081 円、後者は 3,785 円であるが、半田付けが苦手なので前者を購入した。
欲を言えば、JTAG I/F のピンヘッダも半田付けしてくれていれば最高だった。

家に帰ってから、早速開封してみた。
ボードの他に、MCU の各端子がピンソケットのどの箇所に対応するかを図示したカードと、USB ホストコネクタが同梱されていた。

GR-SAKURA は MCU に Renesas の RX63N を搭載したボードである。
※より具体的な MCU の型名は「R5F563NBDDFP」(ROM:1 MiB/RAM:128 KiB/LQFP)

遊んでみる前に、この MCU のソフトウェアマニュアルとハードウェアマニュアルを入手し、少し勉強してみた。
以下に RX の特徴を、備忘録として残しておく。

Renesas RX の特徴

RX は、Renesas の既存の MCU である H8S、H8SX、M16C、R32C の後継機種という位置付けにあたる。H8S/H8SX からは

  • (アドレス/データの両方に使える)汎用レジスタ
  • ポインタ演算向けのアドレッシング(インデックス付きレジスタ間接、プレデクリメント、ポストインクリメント)

という長所を、M16C/R32C からは

  • 割り込み/ユーザの 2 スタックポインタ
  • FPU*1

という長所を「いいとこどり」している。

プログラマの視点からは、 RX は CISC の特徴を備えた MCU に見える。すなわち、

  • 可変長命令
  • 命令の種類が豊富
  • 豊富なアドレッシングモードと直交性の高い命令セット

により、高いコード密度を期待できる。

しかし MCU 内部では、CISC よりはむしろ RISC に近い動作をするようだ。
幾つかの命令は、内部で複数の mop(micro-operation)に置き換えられ、mop 単位でパイプライン処理が行われる。
例えば加算を行う add 命令の場合、レジスタ直接アドレッシングだと

               +----+---+---+----+
    add r1, r2 | IF | D | E | WB | (mop) add
               +----+---+---+----+

のように、レジスタ間の加算を行う単一の mop に変換される。
一方、レジスタ間接アドレッシングを使用した add 命令の場合、

                 +----+---+---+-------+
    add [r1], r2 | IF | D | E |  M1   |          (mop) load
                 +----+---+---+-------+---+----+
                          | D | stall | E | M1 | (mop) add
                          +---+-------+---+----+

のように、メモリからのロードを行う mop と、レジスタ間の加算を行う mop に分解される。

なお、割り込みは(mop 単位ではなく)命令の区切りで受け付ける。割り込み処理から復帰すると、次の命令から開始する。
但し、積和演算命令(rmpa)およびストリング操作命令群(scmpu/smovb/smovf/smovu/sstr/suntil/swhile)のみ例外で、命令の途中であっても割り込みを受け付け、割り込み処理終了後に命令の続きを再開する。

何に使うのかよくわからない命令群

命令セットに目を通してみて、ストリング操作命令群(scmpu/smovb/smovf/smovu/sstr/suntil/swhile)が何のために存在するのかが、よくわからなかった。

例えば memcpy(3) を

          ; void *memcpy(void *dst, const void *src, size_t len);
  _memcpy:
          pushm   r1-r3
          smovf
          popm    r1-r3
          rts

の僅か 4 行で実装できる*2 *3、という程度の事柄は理解できるが、それ以外の用途は…?

後は、実際に動かしながら勉強していくことにしよう。

*1:RX100 シリーズと RX200 シリーズは対応していない

*2:ここでは ABI を、第一引数〜第三引数をそれぞれ R1 〜 R3 に割り当てるものと仮定している。なお、R2 や R3 をスクラッチレジスタとして扱う ABI の場合は、これらのレジスタの退避は不要である。

*3:memmove(3)の場合は、コピー元とコピー先の重なり具合に応じて、smovf と smovb を使い分ける必要がでてくる