私は現在、ゲームボーイエミュレーターを開発しており、エミュレーターの正確性をテストするために、GBDK を使用してエミュレーター用の C プログラムをコンパイルしています。
コンパイラは (予想どおり) 回転を行うことで、2 の累乗である定数を使用して乗算を最適化することに気付きました。ただし、特定のパワーに対して正しい量の回転を生成していないようです。
たとえば、次の非常に単純なプログラム:
#include <gb/gb.h>
unsigned char one() { return 1; }
void main()
{
unsigned char r;
// Force compiler to generate muliplication by deferring the '1'
r = one() * 32;
// Store result somewhere
*((unsigned char*)(0xFFFE)) = r;
}
次のアセンブリを生成します。
___main_start:
_main:
push bc
; reproduce.c 14
; genCall
call _one
ld c,e
; genLeftShift
ld a,c
rr a
rr a
rr a
and a,#0xE0
ld c,a
; reproduce.c 16
; genAssign
ld de,#0xFFFE
; genAssign (pointer)
ld a,c
ld (de),a
; genLabel
00101$:
; genEndFunction
pop bc
ret
___main_end:
.area _CODE
RR命令は実際にはキャリーフラグを介して回転し、効果的に9ビットの回転になるため、これは正しくないように見えます。これは、現在 (0x40) の間違った結果ではなく、正しい結果を生成するために追加のローテーションが必要であることを意味します。
視覚化:
Start: A = 00000001 Carry = 0
RR A: A = 00000000 Carry = 1
RR A: A = 10000000 Carry = 0
RR A: A = 01000000 Carry = 0 <- WRONG!
これが実際に GBDK に付属する SDCC コンパイラのバグであることを確認できる人はいますか? ローテーションに続く and 命令の使用にも興味があります。
sourceforge の Windows 用 GBDK の最新 (3-2.93) バージョンを使用します。