MIPSのSIMD其の五

DSP命令を調べてみます。qeumのテストコードを参考にしてみます。

dsp(r1)のaddは以下のようになります。

addu_qb.c - 8bit x 4
addu_s_qb.c - 8bit x 4
addq_ph.c - 16bit x 2
addq_s_ph.c - 16bit x 2
addq_s_w.c - 32bit
addsc.c - 32bit
addwc.c - 32bit

qbが付くのが8bit演算で、phが付くのが16bit演算で、これ以外が32bit演算になります。

dspr2で以下が追加されてます。

adduh_qb.c
adduh_r_qb.c
addu_ph.c
addqh_ph.c
addqh_r_ph.c
addu_s_ph.c
addqh_r_w.c
addqh_w.c

dspで追加された64bitのac1,2,3レジスタへのアクセス

mthi.c
mtlo.c
mfhi.c
mflo.c

通常のレジスタ間で32bitの内容をやりとりします。

bitrev.c

これは演算ではなくて、レジスタの下位16ビットのビット反転してレジスタに入れます。

追加された命令は演算が8割くらいで他は特殊命令のようです。

MIPS® DSP ASE Instruction Set Quick Referenceとqeumのテストコードを見比べると理解しやすいです。

addu_qb.cをアセンブラにするとこんな感じです。

```:addu_qb.s
        .file   1 "addu_qb.c"
        .section .mdebug.abi32
        .previous
        .abicalls
        .section        .rodata
        .align  2
        .type   __func__.2074, @object
        .size   __func__.2074, 5
__func__.2074:
        .string "main"
        .align  2
.LC0:
        .string "addu_qb.c"
        .align  2
.LC1:
        .string "rd == result"
        .align  2
.LC2:
        .string "((dsp >> 20) & 0x01) == 1"
        .text
        .align  2
        .globl  main
        .ent    main
main:
        .frame  $fp,56,$31              # vars= 24, regs= 2/0, args= 16, gp= 8
        .mask   0xc0000000,-4
        .fmask  0x00000000,0
        .set    noreorder
        .cpload $25
        .set    reorder
        addiu   $sp,$sp,-56
        sw      $31,52($sp)
        sw      $fp,48($sp)
        move    $fp,$sp
        .cprestore      16
        li      $2,16711680                     # 0xff0000
        ori     $2,$2,0xff
        sw      $2,36($fp)
        li      $2,65536                        # 0x10000
        ori     $2,$2,0x1
        sw      $2,32($fp)
        sw      $0,24($fp)
        lw      $3,36($fp)
        lw      $2,32($fp)
 #APP
        addu.qb $2, $3, $2
        rddsp $3
 
 #NO_APP
        sw      $2,40($fp)
        sw      $3,28($fp)
        lw      $3,40($fp)
        lw      $2,24($fp)
        beq     $3,$2,.L2
        la      $4,__func__.2074
        la      $5,.LC0
        li      $6,19                   # 0x13
        la      $7,.LC1
        jal     __assert
.L2:
        lw      $2,28($fp)
        li      $3,1048576                      # 0x100000
        and     $2,$2,$3
        bne     $2,$0,.L4
        la      $4,__func__.2074
        la      $5,.LC0
        li      $6,20                   # 0x14
        la      $7,.LC2
        jal     __assert
.L4:
        li      $2,-65536                       # 0xffffffffffff0000
        ori     $2,$2,0x1111
        sw      $2,36($fp)
        li      $2,131072                       # 0x20000
        ori     $2,$2,0x1
        sw      $2,32($fp)
        li      $2,-16711680                    # 0xffffffffff010000
        ori     $2,$2,0x1112
        sw      $2,24($fp)
        lw      $3,36($fp)
        lw      $2,32($fp)
 #APP
        addu.qb $2, $3, $2
        rddsp $3
 
 #NO_APP
        sw      $2,40($fp)
        sw      $3,28($fp)
        lw      $3,40($fp)
        lw      $2,24($fp)
        beq     $3,$2,.L6
        la      $4,__func__.2074
        la      $5,.LC0
        li      $6,31                   # 0x1f
        la      $7,.LC1
        jal     __assert
.L6:
        lw      $2,28($fp)
        li      $3,1048576                      # 0x100000
        and     $2,$2,$3
        bne     $2,$0,.L8
        la      $4,__func__.2074
        la      $5,.LC0
        li      $6,32                   # 0x20
        la      $7,.LC2
        jal     __assert
.L8:
        move    $2,$0
        move    $sp,$fp
        lw      $31,52($sp)
        lw      $fp,48($sp)
        addiu   $sp,$sp,56
        j       $31
        .end    main
        .size   main, .-main
        .ident  "GCC: (GNU) 4.2.1 20070831 patched [FreeBSD]"
```

gcc 4.4ではBuilt-in Functionsがサポートされv4i8などの型で変数を定義すると、演算が自動的にDSP命令にされるようです。