add系命令の5回目です。流石にそろそろaddを終わらせて次回は次の命令に行きたいと思います。addの最後を飾る?のはadc、キャリー付きのaddです。ソースオペランドレジスタ2個に加えてキャリーフラグの1ビットを加えるもの。この命令に関してだけは、オペランドのシフトも拡張もありません。良かった簡単で。
※「ぐだぐだ低レベルプログラミング」投稿順indexはこちら
※動作確認は普及価格帯のAndroidスマホで行っています。Cortex-A73/Cortex-A53 各4コアの bigLITTLE 、64ビット動作です。Android上にインストールしたTermux環境にWindowsPCからSSH接続し、clang/llvmのツールチェーンでビルドしております。
アセンブラ・ソースコード
32ビットレジスタ幅の加算と、64ビットレジスタ幅の加算を行います。それに先立ってキャリーフラグを「立てる/下す」操作のためにadds命令を使っています。キャリーの操作だけなので、addsの方は32ビット幅で行っています。先行するaddsに与えるオペランドの値によりCY=1か0か決めてからターゲットのadc命令を実行するという目論見です。
.globl adcW, adcX .text .balign 4 adcW: adds w0, w1, w2 adc w0, w3, w4 ret adcX: adds w0, w1, w2 adc x0, x3, x4 ret
被テスト・アセンブラ関数を駆動するためのCソース
以下のCソースで、上記のアセンブラ関数を呼び出しています。
-
- 関数の第1引数はダミー。上書きされてしまうのでなんでも良い
- 関数の第2、第3引数のaddsの結果でCYを事前設定する
- 関数の第4,第5引数がadcのソースオペランドとなる
4回テストしていますが、adc命令は、1+0xFFFFFFFE という同じ計算を行っています。
-
- 1回目のadcはCY=1で32ビット幅
- 2回目のadcはCY=0で32ビット幅
- 3回目のadcはCY=1で64ビット幅
- 4回目のadcはCY=0で64ビット幅
という設定です。
#include <stdio.h> #define TSTV (0xFFFFFFFE) extern uint32_t adcW(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t); extern uint64_t adcX(uint64_t, uint32_t, uint32_t, uint64_t, uint64_t); int main(void) { uint32_t result; uint64_t resultX; result = adcW(0, 2, TSTV, 1, TSTV); printf ("adcW 1+TSTV+CY1: %08x\n", result); result = adcW(0, 1, TSTV, 1, TSTV); printf ("adcW 1+TSTV+CY0: %08x\n", result); resultX = adcX(0, 2, TSTV, 1, TSTV); printf ("adcX 1+TSTV+CY1: %lx\n", resultX); resultX = adcX(0, 1, TSTV, 1, TSTV); printf ("adcX 1+TSTV+CY0: %lx\n", resultX); return 0; }
ビルドと実行結果
ビルドするときのコマンドラインが以下に。
$ clang -g -O0 -o adc adc.c adc.s
キャリーフラグが本当に立っているか否かをまずはデバッガ(gdb)で確認してみました。以下のスクリーンキャプチャの赤枠内に C が含まれていればCYが立っており、C がなければ立ってません。
まずは1回目のadc実行直前。たっとります。
次に2回目のadc実行直前。おりてます。
さて、実行結果(stdout)が以下に。
$ ./adc adcW 1+TSTV+CY1: 00000000 adcW 1+TSTV+CY0: ffffffff adcX 1+TSTV+CY1: 100000000 adcX 1+TSTV+CY0: ffffffff
以下全て符号無です。
1回目は 1+0xFFFFFFFE+CY(1) で32ビット値がクルリと回って0となりました。予定通り。
2回目は 1+0xFFFFFFFE+CY(0) で0xFFFFFFFFで止まりました。予定通り。
3回目は 1+0xFFFFFFFE+CY(1) ですが64ビット幅なので、結果は上位に突き抜けて0x100000000となりました。予定通り。
4回目は 1+0xFFFFFFFE+CY(0) で0xFFFFFFFFで止まりました。これまた予定通り。
とくに波乱もなく終了っと。