バイトオーダーの境目でアドレスが変わる?

今日は久々に在宅勤務をした気がする。

荷物が届くのを待ってたんですよ。時間指定しにくい荷物だったのでね。

またこの話は改めてBlogに書くが、けっこう大きな買い物である。


以前、バイトオーダーの話を書いた。

バイトオーダーに悩む

新しいマイコンはリトルエンディアン、旧来からのペリフェラルはビックエンディアン、

一体どうするかという話をやっていたのだが、32bit幅のバスをビット順につなぐことで決着した。

すなわち旧来からのシステムにある共有メモリに{12 34 56 78}と並んだデータは、

4byteアクセスすると新しいマイコンでも0x12345678とリードできて、

それを自身のメモリに格納すると{78 56 34 12}となるという形である。

ハードウェア的にも作りやすく、ソフトウェアの修正も少ない見込みで、

万々歳とは思うが、うまくやるにはいろいろ工夫が必要である。


で、これは職場の人に教えてもらったのだが、この方法で1byte, 2byteアクセスに対応する場合、

境界部でアドレスを調整することでつじつまを合わせることができると言われた。

ビックエンディアンのシステムにある共有メモリの0x100番地から{12 34 56 78}というデータが格納されているとき。

ビックエンディアンのシステムで0x100から4byteリードすると0x12345678、

0x100から2byteリードすると0x1234、0x102から2byteリードすると0x5678となる。


一方でリトルエンディアンのシステムにとってみれば、

0x100から4byteリードして0x12345678と読めるメモリというのは、

2byte単位で区切って読むと、下位16bit(=0x5678), 上位16bit(=0x1234)の順でリードできるべきである。

そこでリトルエンディアンとビックエンディアンの境界部で、

2byteアクセスの場合は0x100→0x102, 0x102→0x100とアドレス変換を行う。

共有メモリから0x102から2byteリードすると0x5678、0x100からリードすると0x1234となるからつじつまが合う。

同様に1byteアクセスも0x100⇔0x103, 0x101⇔0x102と変換するとつじつまが合う。

こうするとバイトオーダーの違いを吸収できるというわけである。


すなわちビックエンディアンとリトルエンディアンをまたぐ場合、

  1. 2,4byteアクセスしたときのビット順は正しい
    4byte単位でアクセスしたときのアドレスは変わらない
    バイト順と1,2byteアクセス時のアドレスは異なる
  2. バイト順とアドレスは変わらない
    2,4byteアクセスしたときのビット順が異なる

の2つの選択肢があり、今回は1.を選択したということになる。


今回の場合、多くはこれで問題ないと考えているのだが、

4byteアクセスに統一できない1byte, 2byteアクセスも多少ありそうで、

その場合にはアドレス調整が必要になるのが課題の1つ。

そういう処理をできるだけ減らすこと。残る部分は確実に対応することが求められている。

そしてバイナリデータの転送時にバイト順が変わる問題もある。

全体としてはあまり多くないが一部に存在する。

そこはどこかでバイトスワップする処理を差し込むことになる。


なかなかこの仕組みを理解するのは難しいようで、

メンバー同士の議論でもよく振り出しに戻るということが起きている。

まぁなかなか教科書的な話とは違うなとは言っていたが。