3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

sub命令

Last updated at Posted at 2020-12-07

はじめに

sub.png

$ grep ^v.*sub /usr/lib/gcc/aarch64-linux-gnu/7.5.0/include/arm_neon.h | cut -f 1 -d ' ' | sed -e 's/[usf][0-9]\+//g' | sort | uniq -c
      6 vhsub_
      6 vhsubq_
      8 vqsub_
      2 vqsubb_
      2 vqsubd_
      2 vqsubh_
      8 vqsubq_
      2 vqsubs_
      6 vrsubhn_
      6 vrsubhn_high_
     11 vsub_
      2 vsubd_
      6 vsubhn_
      6 vsubhn_high_
      6 vsubl_
      6 vsubl_high_
     11 vsubq_
      6 vsubw_
      6 vsubw_high_

sub命令

  • 従来と同じく、64bit幅の引数を2つ取るsub命令と128bit幅の引数を2つ取るsubq命令がある
  • sub命令はadd命令と同じく、計算結果がオーバーフローする場合はオーバーフローした分だけが保持される
  • 浮動小数点型(float16x8_tfloat32x4_tfloat64x2_t)で使える引き算命令はこいつしかない。
  • 演算内容は第1引数-第2引数
sub.cpp
        int16_t src0[] = {-3633, 30162, 14067, 10566, -3604, 15767, -15238, 12605,};
        int16_t src1[] = {30549, -14165, 26950, 12751, 12780, 32151, 1146, 28989,};
        int16_t dst[8] = {0};
        int16x8_t vsrc0 = vld1q_s16(src0);
        int16x8_t vsrc1 = vld1q_s16(src1);
        int16x8_t vdst  = vsubq_s16(vsrc0, vsrc1);
}
0:31354   // -3633 - 30549    = -34182 だけど演算結果が 31354 (=-34182+65536)
1:-21209  // 30162 - (-14165) =  44327 だけど演算結果が-21209 (= 44327-65536)
2:-12883
3:-2185
4:-16384
5:-16384
6:-16384
7:-16384

qsub命令

  • 末尾にqが付くのが64bit/128bitの違いだが、頭にqがつく場合は、飽和演算を意味する
  • 符号なし整数型の場合は最小値0、最大値255、符号あり整数型の場合は最小値-128、最大値127でクランプするので、演算結果がこの範囲を超えても、結果はこの範囲にクランプされる
    • いずれも8bit整数型の場合。レーンのbit幅に応じて最大値/最小値は変わる
sub.cpp
        int16_t src0[] = {-3633, 30162, 14067, 10566, -3604, 15767, -15238, 12605,};
        int16_t src1[] = {30549, -14165, 26950, 12751, 12780, 32151, 1146, 28989,};
        int16_t dst[8] = {0};
        int16x8_t vsrc0 = vld1q_s16(src0);
        int16x8_t vsrc1 = vld1q_s16(src1);
        int16x8_t vdst  = vqsubq_s16(vsrc0, vsrc1);
}
0:-32768   // int16_tの最小の値=-32768
1:32767    // int16_tの最大の値= 32767
2:-12883
3:-2185
4:-16384
5:-16384
6:-16384
7:-16384

subl命令

  • 演算結果をbit拡張しながら結果レジスタに書き込む
  • 引数がint8x8_t型ならば、結果はint16x8_t型。引数がint16x4_t型ならば、結果はint32x4_t型。
    • bit拡張されるので、引数として64bit幅のレジスタしか取れないことに注意
  • subl_high命令では、128bit幅レジスタを引数に取るが、使われるのは上位64bit分だけ。

subw命令

  • 演算結果がオーバーフローしないようにbit拡張されたレジスタから引く
  • 第1引数が128bit幅、第2引数が64bit幅、要素数は同じだけど各要素のbit幅が違う型のみ引数に取る
    • ex: int16x8_tint8x8_tで戻り値はint16x8_tuint32x4_tuint16x4_tで戻り値はuint32x4_tなど
  • subw_high命令では、第2引数に128bit幅レジスタを取るが、使われるのは上位64bit分だけ。
  • このあたりの構成はadd命令と全く同じである

その他

  • hsub命令とsubhnrsubhn命令は後日また解説する
  • 明日も手島が執筆の予定で、今の所load命令解説の予定です
3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?