2024ǯ07��10��
RV64I��unsigned��32bit�ͤ�����ĥ����ʤ��Ǵؿ��˥쥸�����Ϥ������ΤϤɤ�����������
RISCV RV64I �Ǥ� unsigned �� 32 bit �͡�uint32_t�ˤǤ��äƤ⡢������ѥ쥸������Ǥ�����ĥ���줿���ǰ����ޤ����㤨�� f(uint32_t) �ؿ��� f(0xc0000000) ���Ϥ�����硢���������Ϥ� a0��x10�˥쥸�����ˤ� 0x00000000c0000000 �ǤϤʤ� 0xffffffffc0000000 ���Ϥ�ޤ���Clang ����ѥ���⤳�λ��ͤ�����Ȥ�����Ŭ����ԤäƤ��ޤ���
�ʤ�С�����ĥ����ʤ����� 32 bit �ͤ��ؿ��˥쥸�����Ϥ�����Ƥ����ʤ�С�����ϥХ��ǤϤʤ������Ȥ������䤬���ޤ�ޤ������⤽�⤳���ͤϤɤ������褿�ΤǤ��礦����Ĵ�٤Ƥߤޤ�����
float _Complex x = -0.0f + -2.0f * I;������ɽ���� 0xc000000080000000 �� 64 bit �ͤη������������쥸�������ݻ�����ޤ���
������������ޤ��ȡ�����θ��ݤ�
- ��ư�������������եȥ��������ߥ�졼������FPU ̵����
- ñ���٤�ʣ�ǿ��� float _Complex �����
- �������ޤ��ϵ���������
- float _Complex �� crealf() �ޤ��� cimagf() �� float �Ȥ��Ƽ��Ф��Ʊ黻��Ԥ�
- ��Ŭ��Í��
float y = ...; ... if (y < 0.0f)�� if ʸ���� __ltsf2(y, 0.0f) �ؿ��ƤӽФ�������ѥ���ˤ����������ޤ���
����ѥ���饤�󥿥���ؿ��� C ������ͤ����ƤǤϤʤ��������˥���ѥ���μ����ȷ�ӤĤ�����Ρʥ����������ΰ����ȹͤ�����ˤʤΤǡ��ʤ�Ǥ⤢��ʤΤǤ��礦������ѥ���ΥХ��Ǥ�̵�������ʤΤǡ������ǽ���äƤ��ɤ��ΤǤ������⤦�����ܤ������Ƥߤޤ���
��ǧ�Τ��ᡢ�ʲ��Τ褦�ʥƥ��ȥ����ɤ��Ѱդ��ޤ������ե������ʬ���ʤ��ȥ���ѥ�����˷׻�����Ƥ��ޤ����ǥХå��dz�ǧ���뤳�Ȥ��Ǥ��ʤ��ʤ뤿��ʬ���Ƥ��ޤ����ޤ�����ñ�Τ��ᡢ����ѥ����󥿥���ؿ� __ltsf2 �ϡ�__ltsf2(-2, 0) �Υ�����������θ���Ƥ��ޤ��󡣤Ĥޤ���椵���ۤʤ�п����̣���� -1 ���֤��Ƥ��ޤ���
$ cat lt.c #include <stdint.h> int __ltsf2(uint32_t a, uint32_t b) { int aSign = a >> 31; int bSign = b >> 31; if (aSign != bSign) return -1; return 1; }
$ cat test_complex.c #include <complex.h> #include <stdio.h> void test_complex(float _Complex z) { float y = cimagf(z); fprintf(stderr, "%f < 0 -> ", y); if (y < 0.0f) { fprintf(stderr, "true\n"); } else { fprintf(stderr, "false\n"); } }ʣ�ǿ���ɽ����狼��䤹�����뤿��� -0.0f ����ο��ˤ��Ƥ��ޤ��������μ����Ϻ���ϻȤ��ޤ���
$ cat test_complex_main.c #include <complex.h> void test_complex(float _Complex z); int main() { float _Complex x = -0.0f + -2.0f * I; test_complex(x); return 0; }��������Ҥ� exeClang RISCV�ʳ�ȯ�ǡˤǥ���ѥ��뤷�� QEMU �Ǽ¹Ԥ���ȡ���Ŭ��̵���ξ��ϰʲ��Τ褦�������������ϰۤʤ�˷�̤ˤʤ�ޤ���
$ clang -v clang version 18.1.7 �ʾ�ά�� $ clang $CLANG_CFLAGS -g test_complex_main.c test_complex.c lt.c $PTHREAD_STUBS $QEMU_LDFLAGS $CLANG_LDFLAGS $ /c/msys64/ucrt64/bin/qemu-system-riscv64.exe -M virt -m 2G -nographic -semihosting -bios none -kernel a.out -2.000000 < 0 -> true��������Ŭ���򤫤���ȸ��ä���̤ˤʤ�ޤ���
$ clang $CLANG_CFLAGS -g -O2 test_complex_main.c test_complex.c lt.c $PTHREAD_STUBS $QEMU_LDFLAGS $CLANG_LDFLAGS $ /c/msys64/ucrt64/bin/qemu-system-riscv64.exe -M virt -m 2G -nographic -semihosting -bios none -kernel a.out -2.000000 < 0 -> false�ºݤ˲��������Ƥ���Τ��ǥХå��Ǹ��Ƥߤޤ��礦��
�ޤ���main() ��Ƭ���� test_complex() �ƤӽФ��ޤǤǤ���
main test_complex_main.c:5:int main() { �ʾ�ά�� 0000000080000398 80000537 lui a0, 0x80000������ a0 �ˤ� 0xffffffff80000000 ������ޤ���
000000008000039C 0015051B addiw a0, a0, 1 00000000800003A0 01F51513 slli a0, a0, 0x1f������ 1 ��Â���� 31 bit ���������եȡ�Shift Left Logical Immediate; slli�ˤ��뤳�Ȥ� a0 ��ʣ�ǿ� -0.0f��0x80000000�� + -2.0f��0xc0000000��i ���������� 0xc000000080000000 ���ۤ��Ƥ��ޤ����������֥ȥ�å����ʥ����ɤ��Ȼפ��ޤ����褯����ʥ����ɽФ�������ȴ������ޤ�����
test_complex_main.c:8: test_complex(x); 00000000800003A4 014000EF jal 0x14������ test_complex(a0 = 0xc000000080000000) ��ƤӽФ��ޤ���
test_complex test_complex.c:4:void test_complex(float _Complex z) { �ʾ�ά�� 00000000800003C8 02055413 srli s0, a0, 0x20������ 32 bit ���������եȡ�Shift Right Logical Immediate; srli�ˤ��뤳�Ȥˤ�� float y = cimagf(z); ��ԤäƵ���������Ф��Ƥ��ޤ������λ����Ǥ� s0 ���ͤ� 0x00000000c0000000 �ǡ����줬������ͤǤ���
�ʾ�ά�� test_complex.c:8: if (y < 0.0f) { 00000000800003F4 00040513 mv a0, s0 00000000800003F8 00000593 mv a1, zero 00000000800003FC 04C000EF jal 0x4c������ a0 �� a1 �� -2��0xc0000000�ˤ� 0 ���Ϥ��� __ltsf2(a0 = 0x00000000c0000000, a1 = 0x0000000000000000) �ƤӽФ���
���Ȥ�����ε�����Ʊ���Ǥ���
__ltsf2 lt.c:7: if (aSign != bSign) return -1; 0000000080000448 00A5C533 xor a0, a1, a0 lt.c:9:} 000000008000044C 43F55513 srai a0, a0, 0x3f 0000000080000450 00156513 ori a0, a0, 1 0000000080000454 00008067 ret�����ɤ��ñ�ˤ����Τ� bltz �ˤ��Ƚ��ǤϤʤ��ʤäƤ��ޤ��������եȤ�����ӡĤʤɤϺ�Ŭ���Ǿä��ơ�XOR ��ȯ��������Ӥ��Ƥ�������Ʊ���Ǥ���XOR����椬�ۤʤäƤ����� 1�ˤ��� 63 bit ���ѱ����եȡ�Shift Right Arithmetic Immediate; srai�ˤ��� 1 �� OR ���äƤ��ޤ����Ĥޤ���椬�ۤʤäƤ����� 0xffffffffffffffff �� 1 �� OR �ʤΤǤ��Τޤ� 0xffffffffffffffff = -1 ���֤ꡢ���פ��Ƥ����� 0x0000000000000000 �� 1 �� OR �� 0x0000000000000001 ���֤�ޤ����ʤ�����ؤ�������ˤ����������ɤ��ФƤ��ޤ�����
������Ʊ�ͤˤ��Υ����ɡ������ 31 bit �ܤ���Ӥ��ơ�0xc0000000 �� 0x00000000 ����椬�ۤʤ롢�Ȥ�����̤ˤʤ�Ϥ�����63 bit �ܤ���Ӥ��Ƥ���Τ�����Ʊ���Ȥ������ä���̤ˤʤäƤ��ޤ���
�ǤϤʤ� compiler-rt �δؿ�������פʤΤ����Ȥ������䤬���ޤ�ޤ������ɤ���쥸�����Ϥ�����Ƥ����ͤ���٥����å��˽ñ¤¹ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½Õ¤ï¿½ï¿½ï¿½ï¿½Ñ´ï¿½ï¿½ï¿½ï¿½Æ°ï¿½ï¿½Ã¤Æ¤ï¿½ï¿½ë¤«ï¿½ï¿½ï¿½ï¿½ï¿½ï¿½×¤Ê¤è¤¦ï¿½Ç¤ï¿½ï¿½ï¿½
// llvm-18.1.8/compiler-rt/lib/builtins/fp_lib.h #if defined SINGLE_PRECISION typedef uint16_t half_rep_t; typedef uint32_t rep_t; typedef uint64_t twice_rep_t; typedef int32_t srep_t; typedef float fp_t; �ʾ�ά�� static __inline rep_t toRep(fp_t x) { const union { fp_t f; rep_t i; } rep = {.f = x}; return rep.i; } // llvm-18.1.8/compiler-rt/lib/builtins/fp_compare_impl.inc static inline CMP_RESULT __leXf2__(fp_t a, fp_t b) { const srep_t aInt = toRep(a); �ʾ�ά�� // llvm-18.1.8/compiler-rt/lib/builtins/comparesf2.c COMPILER_RT_ABI CMP_RESULT __lesf2(fp_t a, fp_t b) { return __leXf2__(a, b); } �ʾ�ά�� COMPILER_RT_ALIAS(__lesf2, __ltsf2)���⤽������� __ltsf2 ���ϤäƤ���Τ� float ���Τ褦�ǡ����Τޤ� uint32_t �ǰ��äƤϤ����ʤ��Τ��⤷��ޤ���