* 何でもかんでも4bit単位で統一してみる
 -(by [[K]], 2008.11.16)
 *** (0)
 -現在ではなんでも8bit(バイト)での区切りがあって、あとはその倍数ですべてが設計されている。そうではなくて、4bitで区切って、さらに4bitずつでしか区切らないとしたら一体どうなるかを検討。はっきり言ってただの遊び。
 *** (1)
 -ダンプ
 --従来:
  0000 01 23 45 67 89 AB CD EF 01 23 45 67 89 AB CD EF
 ---これが16行並ぶと256バイト
 --案:
  0000 0123 4567 89AB CDEF
 ---これが16行並ぶと128バイト
 --一つのアドレスに4bitが存在するため、アドレスが0x10進むとその中に64bit(=8バイト)が存在することになる。
 -切りのいい大きさ
 --4bit、64bit(8バイト)、1024bit(128バイト)、2KB、32KB、512KB、8MB、128MB
 ---4bitがアドレスの一単位、8バイトをパラグラフ、128バイトをセクタ長、2KBをページ長・・・なんてやったらどうかな?
 *** (2)
 -指数付き整数
 --浮動小数点とアイデアは近い。eh4でこんなことができるという例。
 --ルールはeh4を2つ書くこと。一つ目は指数で、それを2倍した数がシフト量。もうひとつが仮数部。似たようなルールは、 [[OSA:GUIGUI01/man0003]] のスタックサイズ指定などに見られる。
 --これだとたった16bitしかなくても、こんなに表現力がある。
 ---仮数部に12bitを割り振る場合、(0〜511) * (1〜16384)。最大は約8メガ。
 ---仮数部に8bitを割り振る場合、(0〜31) * (1〜2^62)。最大は約2^67。
 --もしHDDのパーティションテーブルがこの形式で記述されていたらどうだっただろうか。8メガセクタというのはつまり4GBだが、たったの16bitで4GBまでサポートできていたことになる。既存の形式は24bitのCHSでも、8GBくらいまでしか扱えなかった。
 -もちろん16bitの指数付きeh4ではさすがに有効数字不足だが、これを同条件にするために24bitの指数付きeh4にすれば、有効数字も0〜16383や0〜8191となり、事実上不便を感じることはないだろう。しかも遠い将来指数部8bitでも足りなくなるようなら指数部を12bitにすることも考えられるが、その場合は指数部だけでも2^1022という途方もない最大値を指定できることになり、拡張性は全く申し分ない。
 -KHBIOSではもちろん自前のパーティションテーブルをもち(これは非AT互換機との互換性をとりやすくするためにも必要な処置)、そのときはこれでいこうと思っていた。そうすれば小さいテーブルでもかなりの記述力と拡張性を担保できるから。
 *** (3) 脱線
 -eh4を改造してdh4という形式を考えてみる。
 |RIGHT:4bit|RIGHT:0xxx|3(0-7)|eh4では3|s3sでは3|
 |RIGHT:8bit|RIGHT:10xxxxxx|6(0-63)|eh4では5|s3sでは6|
 |RIGHT:12bit|RIGHT:1100xxxxxxxx|8(0-255)|eh4では9|s3sでは9|
 |RIGHT:16bit|RIGHT:1101xxxx....xxxx|12(0-4095)|eh4では13|s3sでは12|
 |RIGHT:20bit|RIGHT:1110xxxx....xxxx|16(0-65535)|eh4では14|s3sでは15|
 |RIGHT:24bit|RIGHT:111100xxxx....xxxx|18|eh4では18|s3sでは18|
 |RIGHT:28bit|RIGHT:111101xxxx....xxxx|22|eh4では22|s3sでは21|
 |RIGHT:32bit|RIGHT:111110xxxx....xxxx|26|eh4では26|s3sでは24|
 |RIGHT:36bit|RIGHT:11111100xxxx....xxxx|28|eh4では30|s3sでは27|
 -eh4の用途を考えると、短い形式はよく使うが長い形式はまず使わない。だから短い形式での効率を重視したほうがよい(eh4はむしろ長い形式でヘッダが長くなりすぎないことを重視していた)。せいぜい24bit型くらいまでの比較で十分。
 -24bitでは、eh4もdh4もs3sも同じ。その前の20bitではdh4の効率が最もよい。
 -むしろs3sでもいいんじゃないか。4〜24bitの挙動を見る限りでは。s3sだと継続ビットが間に入るので、それを先頭に持ってくるという工夫は必要だが。エンコード名はsh4かな。CPUの名前みたいで紛らわしいけど。
 -sh4
 |RIGHT:4bit|RIGHT:0xxx|3(0-7)|eh4と同じ|
 |RIGHT:8bit|RIGHT:10xxxxxx|6(0-63)|eh4よりも1bit多い|
 |RIGHT:12bit|RIGHT:110xxxxxxxxx|9(0-511)|eh4と同じ|
 |RIGHT:16bit|RIGHT:1110xxxx....xxxx|12(0-4095)|eh4よりも1bit少ない|
 |RIGHT:20bit|RIGHT:11110xxxx....xxxx|15(0-32767)|eh4よりも1bit多い|
 |RIGHT:24bit|RIGHT:111100xxxx....xxxx|18|eh4と同じ|
 -eh4と比べると短い形式(特に8bit)で勝ちがあることは大きい。しかも規則が単純なこともメリットだ。これでhellok0.g01はより小さくなるなんてことはあるだろうか?ないだろうな。まあ増えることもないはず。・・・とりあえず42をエンコードしている部分があるのでそこで4bit減らせる。でも4bitじゃ効果ないので、結局NOPを入れるしかない。
 -これだと上の指数付き整数も変わる。
 |16=4+12|(1-16384)x(0-511)|最大は約8メガ|
 |16=8+8|(1-2^126)x(0-63)|最大は約2^132|
 |24=4+20|(1-16384)x(0-32767)|最大は約512メガ|
 |24=8+16|(1-2^126)x(0-4095)|最大は約2^138|
 -fh4
 --しかしやっぱりsh4では全ビットの25%が常にヘッダとして無駄になるわけで(=データを表すビットとしては活用できないわけで)、これはいかにももったいない。そもそも24bit形式の次に28bit形式などがあったとして、こんなのを使いたいと思うだろうか。そんなのすっ飛ばして、32bit形式でいいじゃないかと思わないだろうか。僕はそう思うのだが、これができない理由があって、それは半端な隙間が開いてしまったときにそれを解消するすべがないことである。しかし隙間を空けないで済むように、パディング用のコードがあれば、この問題は起きない。
 --ということで次のようなエンコードを考えた。
 |RIGHT:4bit|RIGHT:0xxx|3(0-6)|sh4と同じ、"7"は8bit形式以上でエンコード|
 |RIGHT:4bit|RIGHT:0111|prefix|主にパディング用(註)|
 |RIGHT:8bit|RIGHT:10xxxxxx|6(0-63)|sh4と同じ|
 |RIGHT:12bit|RIGHT:110xxxxxxxxx|9(0-511)|sh4と同じ|
 |RIGHT:16bit|RIGHT:1110xxxx....xxxx|12(0-4095)|sh4と同じ|
 |RIGHT:24bit|RIGHT:11110xxxx....xxxx|19|sh4よりも1bit多い|
 |RIGHT:32bit|RIGHT:111110xxxx....xxxx|26|sh4よりも2bitも多い|
 |RIGHT:48bit|RIGHT:1111110xxxx....xxxx|41|sh4よりも5bitも多い|
 |RIGHT:64bit|RIGHT:11111110xxxx....xxxx|56|sh4よりも8bitも多い|
 --註:
 ---4bit形式の7はプリフィクスであって、"7"を意味しない。またプリフィクスの直後に通常の4bit形式、8bit形式、12bit形式が続くことはない。それらはプリフィクスを含まない8bit形式、12bit形式、16bit形式をとれば済むからである。
 ---プリフィクスである4bit形式の7は、連続でいくつでもつなげられる。しかしいくつつなげても単にスペースを埋める以上の意味はなく、制御コードとしても意味が変わることはない。
 ---プリフィクスの後の0-511は制御コードとして特別な意味を持つ。・・・かもしれないので(笑)、基本的に使ってはいけない。たとえばこれらをヘッダに使うことができる。pre-0やpre-1を"111111110"や"1111111110"などの代わりにすれば、長い形式でのビット効率はさらに増す。
 --fh4だとエンコード自体にNOP用コードがあるようなものなので、このエンコードを使う仕様ではNOP的なファンクションを入れる必要はないかもしれない。
 -gh4
 --fh4では20bit形式、28bit形式、40bit形式、56bit形式を飛ばしているが、これらを入れたほうがいいかもしれない。入れたのがgh4である。この場合制御コードは0-2Mまで定義できることになる。
 --詳細は[[OSA:GUIGUI01/man0004]]に。
 --上記でリザーブした7B8などの使い道について。gh4は32768bit形式ですさまじく効率がいいとはいっても、実はこれは落とし穴がある。たとえば28672bit形式で収まらない数値はどうしたって次の32768bit形式にするしかなく、そういう意味ではかなりのxのbitが0になるだけで結局非効率になりかねない。こういう非効率は最大で12.5%くらいまでありうる。
 --そこで7BBだ。7BBの後にたとえば4bit形式で数値を書き、その後に28672bit形式で数値を書くと、先の4bit形式の3つのxbitを28672bit形式で書けなかった上位と見なしこれを連結する。さらに7BBは何度でも組み合わせられて、7BB-8bit-7BB-256bit-7BB-28672bitなどということが可能である。これらは全部あわせて一つの数値と見なす。これで非効率を大幅に改善することができる。
 --また7B8は指数つき整数プリフィクスである。これは指数つき整数を最初から仕様に含んでいないようなものでも、それなりに広いフィールドさえあれば、指数つき整数を可能にするものである。ただしこの指数部は2倍はしないでそのままシフト量とする。これで下位に0を20bit以上ムダに並べるような事態は避けられる(もしくはそのせいで長いビット長を選ばなければいけない事態を避けられる)。これはもちろん7BBと組み合わせることもできる。
 ---7B8-a-7BB-b-c という記述の場合、b_c << a ということになる [ 7B8-a-(7BB-b-c) ]。
 ---7BB-a-7B8-b-c という記述の場合、a_(c << b) = (a_c) << b ということになる [ 7BB-a-(7B8-b-c) ]。
 ---7BB-7B8-a-b-c という記述の場合、(b << a)_c ということになる [ 7BB-(7B8-a-b)-c ]。
 --7B9は7B8に非常によく似ている。これはシフトであいた下位のビットスペースに"0"を補う代わりに、"1"を補う。もちろん自由に組み合わせられる。
 --7BAは単純にまず長さ指定フィールドがあって、その後にxxxxしかないフィールドが指定した長さの4倍のビット数だけ続く。7BBよりもこちらのほうが扱いやすいかもしれない。これは7B8や7B9の仲間ともいえる。ようするにシフトであいたスペースにxxxxを詰め込んでいるのだ。これも自由に組み合わせられる。
 --7BAは単純にまず長さ指定フィールドがあって、その後にxxxxしかないフィールドが指定した長さの4倍のビット数だけ続く。7BBよりもこちらのほうが扱いやすいかもしれない。これは7B8や7B9の仲間ともいえる。ようするに数値0に対してシフトであいたスペースにxxxxを詰め込んでいるのだ。これも自由に組み合わせられる。
 --7BCは次の16bitがリトルエンディアン数値であることを示す。この16bitにはヘッダなどはなく、xxxxが16bit並ぶ。なお16bitを取り出す際にアラインが8bitになっていない場合、どうなるかは検討中である。
 --7BDは次の32bitがリトルエンディアン数値であることを示す。アラインについては上に同じ。
 --7BEは次の64bitがリトルエンディアン数値であることを示す。アラインについては上に同じ。
 --7BFは次の128bitがリトルエンディアン数値であることを示す。アラインについては上に同じ。
 --256bit以上のリトルエンディアンについては、7D00以降で対応する。
 --リトルエンディアンプリフィクスを多用すると、部分的にリトルエンディアンにしたいときに大いに助かる。まあ全部にプリフィクス付けてエンコーダで大幅な手抜きをしてもいいだろう。アラインに気をつけたとしても、せいぜい2倍にしかならないわけだし。
 --7BAがあることで、7B7を超える形式をまともにサポートする必要はないかもしれない。まあせいぜいやってもFFFEまでか。そういう意味では"0111"を使わない基本形式のヘッダは最長でも16bitである。
 --なお、gh4の実装は、これらすべての仕様をすべてサポートしなければいけないというわけではない。たとえばsh4互換の32bit形式までしかデコードできないという実装は十分ありうるし、それはそれで問題ない。単に仕様としての拡張性を担保しているだけである。
 
 * こめんと欄
 #comment

リロード   新規 編集 差分 添付   トップ 一覧 検索 最終更新 バックアップ   ヘルプ   最終更新のRSS