SSブログ

「ルネサスの本気」、SH-2Aセミナーに行ってきました。LESSON1 SH-2とSH-2Aの比較7 [RX&SH&H8]

※絶対アドレスの取得に32bit命令を使うメリットが判りました、、、と言うか指摘していただいたのですけれど。詳細は追記して置きます。
※20bitアドレスに関して修正が有ります。
K3300018.jpg今回は新たに追加された命令の内、特徴的な32bit命令について解説します。

その前にSH-2では命令の種類は62種類でしたが、SH-2Aでは随分追加されて112種類となっています。
SH-2の命令長は全て16bitでしたが、SH-2Aでは従来の16bitに加えて32bit命令が追加されています。
32bit命令が追加された理由は、使い勝手の向上だそうです。
具体的にどの様な命令が32bit命令かと言えば、
1.イミディエイト転送命令
2.構造体アクセス用命令
3.メモリを対象としたビット操作命令
です。

うーん、32bit命令ですか。わざわざ追加すると言う事はやっぱり効果が大きいのでしょうね。
随分昔の話になりますが、初めて使う32bitマイコンを選択する段階で候補としてはNECのV850か日立のSHかで悩んでいましたが、日系エレクトロニクスのSH開発秘話の記事を読んでSHを選んだ経験が有ります。
その当時の話では、こだわって16bit固定長を採用していると言う事だったので、SH-2Aでは32bit命令が追加されたと聞いてちょっと微妙な感じがします。
16bit固定長の理由としてはパイプラインの効率を最大限にする為だった筈です。
確かにそうですよね、命令フェッチが必ず1回と決まっていれば、パイプラインに隙間無くインストラクションフェッチ(IF)、インストラクションデコード(ID)、実行(EX)を並べる事が可能で、つまり1クロック1命令ができます。

ではこの32bit命令ではどうなるのでしょうか?。

ソフトウエアマニュアルにはパイプラインの動作を解説しているページがありますのでそこを参考にすると、当然インストラクションフェッチは32bitである為に1クロックでは終了できず2クロック必要としています。(305ページ、図8.5より)

またスーパースカラーの動作にも制限を与えてしまうようです。スーパースカラーの最大の長所である2命令同時実行が一部の条件を除いてできません。(311ページ、「32ビット命令による競合の詳細」)

まあでも、逆に言えばこの程度のデメリットであると。

ではSH-2の16bit固定長の何が問題で32bit命令が追加されたのでしょうか。
最大の問題はイミディエイトデータまたはディスプレースメントの扱いにあります。

16bit命令では、その命令の中に埋め込めるイミディエイトデータの最大サイズは8bitまでとなっています。ディスプレイスメントも同じです。
※SH-2命令でも12bitディスプレースメントが存在します。

では32bitのデータを扱う為にはどうすれば良いのでしょうか。
従来のSH-2では以下の様にして32bitデータにアクセスしていました。
mov.l @(disp,pc),r1
add r1,r0
   ・
   ・
   ・
   ・
data.l h'12345678

この様に直接データを命令の中に埋め込む事が出来ないので、そのデータをテーブルに配置し、PC相対でアクセスして値を取得しています。

ではでは32bit命令が追加されたSH-2Aではどうなるでしょうか。
実はSH-2と変わりません(笑)、やっぱり32bitデータは命令の中に(当然)埋め込む事ができないのです。でもこれは32bitだからであって、SH-2Aでは20bitまでのイミディエイト(またはディスプレイスメント)なら32bit命令の中に埋め込めます。また28bitまでなら2つの命令に別ける事でやはり命令中に置く事ができます。
こんな命令にになります。
movi20 #h'12345,r1 ;20bitイミディエイト

movi20s #h'12345,r1 ;28bitイミディエイト
or #h'67,r1 ;結果はr1にh'1234567が代入される

※共に符号は拡張されます。

でもなんで20bitなのでしょうか。それには理由が有ります。
20bitをアドレスとした場合、0番地から1Mbyteの範囲にアクセスできますが、実際には符号拡張されます。これを実際のSHのメモリに当てはめると、0番地から512Kbyte、0xFFFFFFFF番地からマイナス方向にも512Kbyteアクセス可能となります。
この範囲は、例えばSH7216ならば内蔵ROMの前半と、内蔵RAMや内蔵周辺IOの全てをカバーできる事となります。もっとも利用頻度の高いと思われる領域を32bit命令1個だけでアクセスできるからです。

※すいませんおおぼけでした。32bit命令で絶対アドレスを取得して、その後レジスタ間接を行いますので2命令です。でもそうなると16bit固定長に対する32bit命令のメリットって何だ?。

※これ以外の32bit命令にはメモリに対するビット操作命令があります。これもレジスタ間接となります。

※簡単ですがこれでSH-2との比較編は終了です。
もっと詳しく知りたい方はルネサスのセミナーを受ける事を御勧めします。有料セミナーの場合、2日間のコースで通常価格21,000円ですが、特約店経由で申し込むと、その半額で受けられるキャンペーンを行っているそうです(笑)。
http://japan.renesas.com/fmwk.jsp?cnt=seminer_category_landing.jsp&fp=/support/seminar/


追記
絶対アドレスの取得に32bit命令を使う理由。
従来のSH-2命令ではアドレスをレジスタに取り込む為にはディスプレースメント付きPC相対を利用していました。つまり以下の様な命令です。
mov.l @(disp,pc),r0
mov.l @r0,r1
この@マークが曲者で、メモリアクセスが伴うとパイプライン上では以下のステージが実行される事となります。
順番に、
インストラクションフェッチ(IF)、インストラクションデコード(ID)、実行(EX)、メモリアクセス(MA)、ライトバック(WB)

先の命令が実行されて結果がr0レジスタに代入されるタイミングがWBとなります。
後の命令でもr0レジスタを使用していますので、後の命令が実行されるタイミングは先の命令のWBの後である必要があります。
パイプラインのイメージとしては以下の様になるでしょう。スーパースカラーは取り敢えず無視して書きます。
IFIDEXMAWB------
-- IF-- -- ID EXMAWB

16bit命令で実行すると8スロット掛かる事が判ります。

32bit命令を使用した場合は以下の様になります。
movi20 #h'12345,r0
mov.l @r0,r1
この場合は先の命令に@マークが付いていない事に注意してください。
パイプラインのイメージは以下の様になると思います。
IFIDEX------
--IFIDEXMAWB

こちらは6スロットで完了できます。


SuperHファミリのCプログラミング

SuperHファミリのCプログラミング

  • 作者: 鹿取 祐二
  • 出版社/メーカー: オーム社
  • 発売日: 2008/09
  • メディア: 単行本



SuperHで学ぶμITRON仕様OS―リアルタイムOSの動作原理と実装法がわかる!

SuperHで学ぶμITRON仕様OS―リアルタイムOSの動作原理と実装法がわかる!

  • 作者: 鹿取 祐二
  • 出版社/メーカー: 電波新聞社
  • 発売日: 2005/12
  • メディア: 単行本



nice!(0)  コメント(4)  トラックバック(0) 

nice! 0

コメント 4

たけまろ

ためになります!
by たけまろ (2010-02-04 20:18) 

noritan

movi20sは, SPARC の sethi (上位ビットだけを設定する)のように見えます. SPARC の場合も, sethi/or の組み合わせは,良く出てきました.

追記部分の「先」命令処理で,32ビット命令のIFは,2サイクルを必要としないのですか?
by noritan (2010-02-04 21:52) 

hamayan

> 2サイクルを必要としないのですか?

すると思います(笑)。なのでスロットと書いています。
パイプラインってややこしいですね。
by hamayan (2010-02-04 21:58) 

木原

濱原 様

はじめまして。
質問掲示板がどこにあるのかわからないので、
ここに書かせてください。

ITRONプログラグの勉強を
始めようとおもい、濱原さんの
「ITRONプログラミング入門」を購入しました。
AKI-H8 3048Fボートをつかって実験しています。
Hewのバージョンは、
C/C++ compiler package for
the H8, H8S, and H8SX family V.7.00
Release 00 (1-25-2010 06:52:39)
です。

質問なんですが、
ITRONプログラミング入門のP75の
スイッチのサンプリングプログラム(tutorial5)の
正常動作を確認した後、
P88のタスク間通信(tutorial6)にとりかかったので
すが、
下記の本書のsystem.cfgの設定ですと、
まったくプログラムが動作しなかったのです。


CRE_TSK(TSKID_TASK_A, {TA_HLNG | TA_ACT, 0, task_SW_Input,
1, 256, NULL});
CRE_TSK(TSKID_TASK_B, {TA_HLNG | TA_ACT, 0,
task_SW_Num_Display, 2, 256, NULL});
CRE_TSK(TSKID_TASK_C, {TA_HLNG | TA_ACT, 1,
task_SW_Num_Display, 2, 256, NULL});
CRE_TSK(TSKID_TASK_D, {TA_HLNG | TA_ACT, 2,
task_SW_Num_Display, 2, 256, NULL});
CRE_TSK(TSKID_TASK_E, {TA_HLNG | TA_ACT, 3,
task_SW_Num_Display, 2, 256, NULL});


そこで、いろいろ実験した結果、
下記のように、system.cfgにおいて、
task_SW_Inputの優先順位を2、
task_SW_Num_Displayの優先順位を1に
変更したところ、正常に動作するようになったのです。
ただ、現在3つのスイッチ入力に応じた処理しか
行われないのです。ここに、
CRE_TSK(TSKID_TASK_D, {TA_HLNG | TA_ACT, 3,
task_SW_Num_Display, 1, 256, NULL});
をつけたすと、ビルドは正常に行われますが、
プログラムが動作しないのです。
HOSさえ出力されません。
4つめのスイッチについて、ハード的に問題はないことは
確認しています。

ここで、質問なのですが、

1)優先順位は誤記でしょうか?
2)4つめのスイッチ入力に応じた処理を
  行わせたいのですが、どのようにすればよろしい
  のでしょうか?


【正常に動作したときの設定】

CRE_TSK(TSKID_TASK_A, {TA_HLNG | TA_ACT, 0,
task_SW_Num_Display, 1, 256, NULL});
CRE_TSK(TSKID_TASK_B, {TA_HLNG | TA_ACT, 1,
task_SW_Num_Display, 1, 256, NULL});
CRE_TSK(TSKID_TASK_C, {TA_HLNG | TA_ACT, 2,
task_SW_Num_Display, 1, 256, NULL});
CRE_TSK(TSKID_TASK_MONITOR, {TA_HLNG | TA_ACT, 0,
task_SW_Input, 2, 256, NULL});


この実験結果より、ひょっとして評価版では
登録できるタスクに制限があるのでは?と考え、
下記の実験を行いました。
登録できるタスク数に制限があるという考えは
私の勘違いなのでしょうか?
ご多忙とは存じますが、ご教示のほど宜しくお願い申し上げます。


------------------------------------------------------
<実験1>

P43のプログラムをベースに、
タスクを5つにして実行してみたところ、
ハイパーターミナルの出力結果は下記のように、
Task2とTask3しか表示されず、正常に動作しません
でした。

【system.cfg】

ATT_INI({TA_HLNG, 0, Initialize});
CRE_TSK(TSKID_SAMPLE1, {TA_HLNG | TA_ACT, 1, Task1, 1,
256, NULL});
CRE_TSK(TSKID_SAMPLE2, {TA_HLNG | TA_ACT, 2, Task1, 1,
256, NULL});
CRE_TSK(TSKID_SAMPLE3, {TA_HLNG | TA_ACT, 3, Task1, 1,
256, NULL});
CRE_TSK(TSKID_SAMPLE4, {TA_HLNG | TA_ACT, 4, Task1, 1,
256, NULL});
CRE_TSK(TSKID_SAMPLE5, {TA_HLNG | TA_ACT, 5, Task1, 1,
256, NULL});


【ハイパーターミナル】
HOS

00618:Task2

00618:Task3

------------------------------------------------------
<実験2>

今度は、タスクを4つにしてみたところ、
下記のように正常に動作しました。
この実験結果より、評価版ではタスクは4つしか登録できない
ということがわかりました。

【system.cfg】

ATT_INI({TA_HLNG, 0, Initialize});
CRE_TSK(TSKID_SAMPLE1, {TA_HLNG | TA_ACT, 1, Task1, 1,
256, NULL});
CRE_TSK(TSKID_SAMPLE2, {TA_HLNG | TA_ACT, 2, Task1, 1,
256, NULL});
CRE_TSK(TSKID_SAMPLE3, {TA_HLNG | TA_ACT, 3, Task1, 1,
256, NULL});
CRE_TSK(TSKID_SAMPLE4, {TA_HLNG | TA_ACT, 4, Task1, 1,
256, NULL});


【ハイパーターミナル】

・・・

05026:Task1

05033:Task2

05040:Task3

05047:Task4

06031:Task1

06038:Task2

06045:Task3

06052:Task4

・・・

以上

by 木原 (2010-02-09 06:33) 

コメントを書く

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

※ブログオーナーが承認したコメントのみ表示されます。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。