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 <i...@google.com>: > daniel tian <daniel.xnt...@gmail.com> 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 >