Thank you for your advice. Compared RICE (my processor name) RTL and
MIPS RTL, I found the problem. Because of the subreg operations which
I missed to add support in my RTL. I noticed the mips rtl code which
will convert the QImode and HI mode to SImode operations. Like the
following:
(insn 28 26 29 2 (set (reg:QI 198)
(mem:QI (reg/v/f:SI 193 [ data ]) [0 S1 A8])) -1 (nil)
(nil))
(insn 29 28 30 2 (set (reg:SI 191 [ D.1099 ])
(zero_extend:SI (reg:QI 198))) -1 (nil)
(nil))
(insn 30 29 31 2 (set (reg:SI 199)
(lshiftrt:SI (reg:SI 191 [ D.1099 ])
(const_int 4 [0x4]))) -1 (nil)
(nil))
But in my port, the rtl code is like this:
(insn 25 23 26 2 (set (reg:QI 45 [ D.1059 ])
(mem:QI (reg/v/f:SI 47 [ data ]) [0 S1 A8])) -1 (nil)
(nil))
(insn 26 25 27 2 (set (reg:QI 50)
(lshiftrt:QI (reg:QI 45 [ D.1059 ])
(const_int 4 [0x4]))) -1 (nil)
(nil))
If I extend the QI operands, then do the shift operations, the logic
will be right.
But the question is how I make the gcc know to extend every smaller
mode to SImode. Now I check the MIPS port, maybe I can find some clue.
Thank you for your guys.
daniel.tian
2009/3/27 Ian Lance Taylor <[email protected]>:
> daniel tian <[email protected]> writes:
>
>> I am porting gcc to a 32bit RISC chip, and I met a logical
>> error with 16bit arithmetic operations in generating assemble code.
>> the error is between two 16bit data movement(unsigned short).
>> While like A = B, A, and B are all unsigned short type. B is a
>> result of a series of computation, which may have value in high 16bit.
>> Because A , B are both HImode, so the move insn doesn't take zero
>> extend operation, so A will have value in high 16bit which will caused
>> a wrong result in computation.
>
> The relevant types in your code are "unsigned short". I assume that on
> your processor that is a 16 bit type. An variable of an unsigned 16 bit
> type can hold values from 0 to 0xffff, inclusive. There is nothing
> wrong with having the high bit be set in such a variable. It just means
> that the value is between 0x8000 and 0xffff.
>
>
>> ;; 1--> 23 R5=R6 0>>0xc :nothing
>> //R5 and R6 are both unsigned short type. But R6 will
>> have it's value in high 16bit because of series of logical operations
>> (AND, OR, XOR and so on). Doing it like this way will cause R5 also
>> being valued in high 16bit. This will cause a wrong value. The correct
>> one is : R5 = R2 0 >> 0xC. because R2 did zero extend in former insn
>>>From R6. But How I let gcc know it.
>
> No. 0>> means a logical right shift, not an arithmetic right shift
> (LSHIFTRT rathre than ASHIFTRT). When doing a logical right shift, the
> sign bit is moved right also; it is not sticky. This instruction is
> fine. Perhaps there is a problem in your implementation of LSHIFTRT.
>
> Ian
>