rxのマイコンにはメモリに対するbit操作命令があるのですが
char foo;
void
bit0_set(void)
{
foo |=1;
}こういうことをやろうとする、rx-elf-gccは
0000 FB E2 00 00 00 00 mov.L #_foo, r14
0006 CC E4 mov.B [r14], r4
0008 65 14 or #1, r4
000a C3 E4 mov.B r4, [r14]
なぜか、こういう上のコードを出力しています。
rx.mdにはbit操作命令を使うような記述はあるのですが、無視されています。
0000 FB E2 00 00 00 00 mov.L #_foo, r14
0006 F0 E0 bset #0, [r14].B
(set (mem/c:QI (reg/f:SI 26) [0 foo+0 S1 A8])
(subreg:QI (ior:SI (subreg:SI (mem/c:QI (reg/f:SI 26) [0 foo+0 S1 A8]) 0)
(const_int 1 [0x1])) 0))
これは、上の命令パターンを認識できていないために起こっています。
この命令パターン認識される記述は下のようになります。
(define_insn "*bitset_in_memory_little"
[(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
(subreg:QI (ior:SI (subreg:SI (match_dup 0) 0)
(match_operand:QI 1 "const_int_operand" "i")) 0))]
"exact_log2 (INTVAL (operands[1]) & 0xff) >= 0
&& exact_log2 (INTVAL (operands[1]) & 0xff) <= 7"
"*
{
rtx xoperands[2];
xoperands[0] = operands[0];
xoperands[1] = GEN_INT (exact_log2 (INTVAL (operands[1]) & 0xff));
output_asm_insn (\"bset\\t%1, %0.B\", xoperands);
return \"\";
}
"
[(set_attr "length" "3")
(set_attr "timings" "33")]
)
今度は、コンパイル時に-mbig-endian-dataをつけた場合を考えてみます。
(set (mem/c:QI (reg/f:SI 26) [0 foo+0 S1 A8])
(subreg:QI (ior:SI (subreg:SI (mem/c:QI (reg/f:SI 26) [0 foo+0 S1 A8]) 0)
(const_int 1 [0x1])) 3))
このパターンを認識される記述はこうなります。
(define_insn "*bitset_in_memory_big"
[(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
(subreg:QI (ior:SI (subreg:SI (match_dup 0) 0)
(match_operand:QI 1 "const_int_operand" "i")) 3))]
"exact_log2 (INTVAL (operands[1]) & 0xff) >= 0
&& exact_log2 (INTVAL (operands[1]) & 0xff) <= 7"
"*
{
rtx xoperands[2];
xoperands[0] = operands[0];
xoperands[1] = GEN_INT (exact_log2 (INTVAL (operands[1]) & 0xff));
output_asm_insn (\"bset\\t%1, %0.B\", xoperands);
return \"\";
}
"
[(set_attr "length" "3")
(set_attr "timings" "33")]
)
この記述方法は、v850.mdの記述を参考にしています。
次に、ビットフィールドの時の場合を考えてみます。
union
{
unsigned char BYTE;
struct
{
#ifdef __RX_BIG_ENDIAN__
unsigned char B7:1;
unsigned char B6:1;
unsigned char B5:1;
unsigned char B4:1;
unsigned char B3:1;
unsigned char B2:1;
unsigned char B1:1;
unsigned char B0:1;
#else
unsigned char B0:1;
unsigned char B1:1;
unsigned char B2:1;
unsigned char B3:1;
unsigned char B4:1;
unsigned char B5:1;
unsigned char B6:1;
unsigned char B7:1;
#endif
} BIT;
void
set_bit0(void)
{
foo.BIT.B0 = 1;
}
0000 FB E2 00 00 00 00 mov.L #_foo, r14
0006 CC E4 mov.B [r14], r4
0008 78 04 bset #0, r4
000a C3 E4 mov.B r4, [r14]
この時に、必要な記述は
(set (mem/j/c:QI (reg/f:SI 24) [0+0 S1 A8])
(ior:QI (mem/j/c:QI (reg/f:SI 24) [0+0 S1 A8])
(const_int 1 [0x1])))
こうなので
(define_insn "*bitset_in_memory_bitfiled"
[(set (match_operand:QI 0 "rx_restricted_mem_operand" "+Q")
(ior:QI (match_dup 0)
(match_operand:QI 1 "const_int_operand" "i")))]
"exact_log2 (INTVAL (operands[1]) & 0xff) >= 0
&& exact_log2 (INTVAL (operands[1]) & 0xff) <= 7"
"*
{
rtx xoperands[2];
xoperands[0] = operands[0];
xoperands[1] = GEN_INT (exact_log2 (INTVAL (operands[1]) & 0xff));
output_asm_insn (\"bset\\t%1, %0.B\", xoperands);
return \"\";
}
"
[(set_attr "length" "3")
(set_attr "timings" "33")]
)
記述はこうなります。この場合、エンディアンは無視できます。
bitmem.patchbclr,bnotを使えるようにしました。
[0回]
PR