nptclのブログ

Common Lisp処理系nptの開発メモです。https://github.com/nptcl/npt

deposit-field, dpbの使い方をいつも忘れる

ちゃんとメモしておきます。
まずはbytespecから

1. bytespec

位置とサイズを保有するオブジェクトです。
次のようにして生成します。

(byte size pos)

下記の例は「3番目から7個」という意味。

(byte 7 3)

図であらわします。

098769876543210
---------------
           3...  3番目から
     7654321...  7個
     ******3     以降こうやって表します

2. deposit-field

(deposit-field left bytespec right)

例を示します。

(deposit-field #b1111000011110000 (byte 7 3) #b1010101010101010)
-> #b1010100011110010

         ******3      (byte 7 3)
#b111100 0011110 000  left
#b101010 1010101 010  right
--------------------
#b101010 0011110 010

つまりはこんな感じ。

         ******3      (byte 7 3)
#b...... 0011110 ...  left
#b101010 ....... 010  right
--------------------
#b101010 0011110 010

3. dpb (deposit-byte)

(deposit-field left bytespec right)

例を示します。

(dpb #b1111000011110000 (byte 7 3) #b1010101010101010)
-> #b1010101110000010

            ******3      (byte 7 3)
#b111100001 1110000      left
   #b101010 1010101 010  right
-----------------------
   #b101010 1110000 010

つまり

            ******3      (byte 7 3)
#b......... 1110000      left
   #b101010 ....... 010  right
-----------------------
   #b101010 1110000 010

deposit-fieldは左辺右辺はどちらも同じ位置ですが、 dpb(deposit-byte)は左辺と右辺で違った場所を取るようです。

4. ldb (load-byte)

(ldb bytespec integer)

こちらはbytespecの内容を取り出すだけ。

(ldb (byte 7 3) #b1111000011110000)
-> #b11110

つまり

         ******3      (byte 7 3)
#b111100 0011110 000  integer
--------------------
#b...... 0011110 ...

5. mask-field

(ldb bytespec integer)

bytespecの内容を取り出しますが右詰めしません。

(mask-field (byte 7 3) #b1100110011001100)
-> #b11001000

つまり

         ******3      (byte 7 3)
#b110011 0011001 100  integer
--------------------
#b...... 0011001 000

mask-fieldは引数と同じ位置ですが、 ldb(load-byte)は右詰されます。

6. ldb-test

(ldb-test bytespec integer)

こちらはldbで抜き出した内容が0ならnil
下記の実行と同じです。

(ldb-test bytespec n) == (not (zerop (ldb bytespec n)))

なんで上記のようにしないのかというと、 ldbでいちいち値を作成してたら時間もメモリも もったいないということで最適化されています。
logtestなんかもそうです。

まとめ

★(deposit-field #b1111000011110000 (byte 7 3) #b1010101010101010)

         ******3      (byte 7 3)
#b...... 0011110 ...  left
#b101010 ....... 010  right
--------------------
#b101010 0011110 010
★(dpb #b1111000011110000 (byte 7 3) #b1010101010101010)

            ******3      (byte 7 3)
#b......... 1110000      left
   #b101010 ....... 010  right
-----------------------
   #b101010 1110000 010
★(ldb (byte 7 3) #b1111000011110000)

         ******3      (byte 7 3)
#b111100 0011110 000  integer
--------------------
#b...... 0011110 ...
★(mask-field (byte 7 3) #b1100110011001100)

         ******3      (byte 7 3)
#b110011 0011001 100  integer
--------------------
#b...... 0011001 000