From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1482 invoked by alias); 27 Mar 2009 09:12:25 -0000 Received: (qmail 1474 invoked by uid 22791); 27 Mar 2009 09:12:23 -0000 X-SWARE-Spam-Status: No, hits=-1.4 required=5.0 tests=AWL,BAYES_00,SARE_MSGID_LONG40,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mail-fx0-f165.google.com (HELO mail-fx0-f165.google.com) (209.85.220.165) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 27 Mar 2009 09:12:18 +0000 Received: by fxm9 with SMTP id 9so898812fxm.8 for ; Fri, 27 Mar 2009 02:12:15 -0700 (PDT) MIME-Version: 1.0 Received: by 10.223.113.3 with SMTP id y3mr1405421fap.71.1238145134878; Fri, 27 Mar 2009 02:12:14 -0700 (PDT) Date: Fri, 27 Mar 2009 12:49:00 -0000 Message-ID: <121fadb80903270212p5ab2c977t86778eed45b94d23@mail.gmail.com> Subject: logical error with 16bit arithmatic operations From: daniel tian To: gcc@gcc.gnu.org, uday@cse.iitb.ac.in, yxun lan , iant@google.com Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Mailing-List: contact gcc-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-owner@gcc.gnu.org X-SW-Source: 2009-03/txt/msg00812.txt.bz2 Hello, 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. Like the following CRC calculation. There is a comment added with "//" in logical error position. Here is the .sched2 script: ;; ====================================================== ;; -- basic block 0 from 10 to 92 -- after reload ;; ====================================================== ;; 0--> 10 R3=R4 :nothing ;; 1--> 11 R7=R5 :nothing ;; 2--> 89 R0=`x25_crc_table' :nothing ;; 3--> 92 pc=L58 :nothing ;; Ready list (final): ;; total time = 3 ;; new head = 10 ;; new tail = 92 ;; ====================================================== ;; -- basic block 1 from 25 to 53 -- after reload ;; ====================================================== ;; 0--> 25 R6=[post_modify] :rice_load,nothing ;; 1--> 57 R7=R7-0x1 :nothing ;; 2--> 26 R4=R6 0>>0x4 :nothing ;; 3--> 27 R4=zxn(R4) :nothing ;; 4--> 28 R4=R5^R4 :nothing ;; 5--> 32 R4=zxn(R4) :nothing ;; 6--> 35 R4=R4+R4 :nothing ;; 7--> 37 R5=[R4+R0] :rice_load,nothing ;; 8--> 42 R6=zxn(R6) :nothing ;; 9--> 38 R5=R5^R13 :nothing ;; 10--> 40 R4=R5 0>>0xc :nothing ;; 11--> 43 R4=R4^R6 :nothing ;; 12--> 47 R4=zxn(R4) :nothing ;; 13--> 48 R4=R4&0xf :nothing ;; 14--> 50 R4=R4+R4 :nothing ;; 15--> 52 R4=[R4+R0] :rice_load,nothing ;; 16--> 46 R5=R5<<0x4 :nothing ;; 17--> 53 R6=R5^R4 :nothing ;; Ready list (final): ;; total time = 17 ;; new head = 25 ;; new tail = 53 ;; ====================================================== ;; -- basic block 2 from 23 to 62 -- after reload ;; ====================================================== ;; 0--> 87 R2=zxn(R6) :nothing ;; 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. ;; 2--> 31 R13=R2<<0x4 :nothing ;; 3--> 62 pc={(R7>0x0)?L20:pc} :nothing ;; Ready list (final): ;; total time = 3 ;; new head = 87 ;; new tail = 62 ;; ====================================================== ;; -- basic block 3 from 100 to 100 -- after reload ;; ====================================================== ;; 0--> 100 return :nothing ;; Ready list (final): ;; total time = 0 ;; new head = 100 ;; new tail = 100 PS, I compile the c code with -Os command. Here is C code: static const unsigned short x25_crc_table[16] = { 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7, 0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF }; /* ** FUNCTION: crc_X25 ** ** DESCRIPTION: This function generates a crc on from the data given ** using the X 25 CRC lookup table. ** ** ** PARAMETERS: Data to check: ** Array of data: UTINY * ** Length of data in array: LONG ** CRC initial value: USHORT ** ** RETURNS: USHORT, The CRC calculated. ** */ unsigned short crc_X25(unsigned char *data, long length, unsigned short crc_reg) { unsigned short temp; /* Use 4 bits out of the data/polynomial at a time */ while (length > 0) { /* step through the data */ temp = crc_reg; temp >>= 12u; temp ^= (*data) >> 4u; /* xor data (MS 4 bits) with the MS 4 bits */ temp &= 0xf; /* of the CRC reg to be used as index in array */ temp = crc_reg = (unsigned short )((crc_reg << 4u) ^ x25_crc_table[temp]); /* Now do second half of byte */ temp >>= 12u; temp ^= *data; /* xor data with the 4 MS bits of the CRC reg */ temp &= 0xf; /* to be used as index in array */ crc_reg = (unsigned short )((crc_reg << 4u) ^ x25_crc_table[temp]); crc_reg = crc_reg & 0xFFFF; data++; /* move on through data array */ length--; } return (crc_reg); } from the C language, It occurred in statement: temp = crc_reg; R5 register stands for 'temp'. R6 register is "crc_reg" Any, any suggestion is appreciated. Thank you very much. Tianxiaonan