From patchwork Mon Feb 22 16:53:19 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yao Qi X-Patchwork-Id: 10989 Received: (qmail 41015 invoked by alias); 22 Feb 2016 16:53:41 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 40988 invoked by uid 89); 22 Feb 2016 16:53:40 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy=1072, Architecture, Manual, sk:finish X-HELO: mail-pf0-f169.google.com Received: from mail-pf0-f169.google.com (HELO mail-pf0-f169.google.com) (209.85.192.169) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Mon, 22 Feb 2016 16:53:33 +0000 Received: by mail-pf0-f169.google.com with SMTP id c10so98584105pfc.2 for ; Mon, 22 Feb 2016 08:53:33 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=NoExl6fkIY+KFf1UFCH/LM82AVVFyBOQBt7FTiOTksU=; b=SGV54BBbfJQBy6QjcGHrm7v5QadwKGPYSsWRq7UrqY2ZQEqe97Fiqjh5zMN+2ocoHC t3luShiZKdfmWDZLnbJHayJVM8wQFJk55idlP1XWJS9EVFtcxyFsbbLV1naclc8HFvhC 8uti+fJJTJ3XAYD1uYdr3maphQAPzddjd/0mk62KqMEZDKnhXSaBRFtdkZM+uoSy3+Qc dsJOoJTQurV/tAI3SJ568gnmIaVIQxOVog5hTyOMG3hyj5b3zhK0BU24WZ+Re/ndoQ/N qntLJb37PbUcjak8IQrFmiiIUJZMO1tTL8TD4y13qW2igMyDhvDI37av9SriAzWLIhNv Ol0g== X-Gm-Message-State: AG10YORhww//Bt5CKJpLbM3tb4y9Vw04nsPIlopfT/L/bztvJxUYieAqVcvKYGtXejo7UQ== X-Received: by 10.98.12.133 with SMTP id 5mr39826938pfm.20.1456160011545; Mon, 22 Feb 2016 08:53:31 -0800 (PST) Received: from E107787-LIN.cambridge.arm.com (gcc1-power7.osuosl.org. [140.211.15.137]) by smtp.gmail.com with ESMTPSA id f12sm38059764pfd.87.2016.02.22.08.53.30 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 22 Feb 2016 08:53:30 -0800 (PST) From: Yao Qi X-Google-Original-From: Yao Qi To: gdb-patches@sourceware.org Subject: [PATCH 3/3] Fix various bugs in arm_record_exreg_ld_st_insn Date: Mon, 22 Feb 2016 16:53:19 +0000 Message-Id: <1456159999-5644-4-git-send-email-yao.qi@linaro.org> In-Reply-To: <1456159999-5644-1-git-send-email-yao.qi@linaro.org> References: <1456159999-5644-1-git-send-email-yao.qi@linaro.org> X-IsSubscribed: yes This patch fixes various bugs in arm_record_exreg_ld_st_insn, and use gdb.reverse/insn-reverse.c to test more arm instructions. - Set flag SINGLE_REG correctly. In the arch reference manual, SING_REG is true when the bit 8 of instruction is zero. - Record the right D registers for instructions changing S registers. - Fix the order of length and address in record_buf_mem array. - Shift the offset by 2 instead of by 24. This patch also fixes one internal error, (gdb) PASS: gdb.reverse/finish-precsave.exp: BP at end of main continue^M Continuing.^M ../../binutils-gdb/gdb/utils.c:1072: internal-error: virtual memory exhausted.^M A problem internal to GDB has been detected,FAIL: gdb.reverse/finish-precsave.exp: run to end of main (GDB internal error) gdb: 2016-02-22 Yao Qi * arm-tdep.c (arm_record_exreg_ld_st_insn): Set 'single_reg' per bit 8. Check bit 20 instead of bit 4 for VMOV instruction. Record D registers for instructions changing S registers. Change of the order of length and address in record_buf_mem array. gdb/testsuite: 2016-02-22 Yao Qi * gdb.reverse/insn-reverse.c [__arm__] (ext_reg_load): New. [__arm__] (ext_reg_mov, ext_reg_push_pop): New. (testcases): Update. --- gdb/arm-tdep.c | 93 ++++++++++++++++++++------------ gdb/testsuite/gdb.reverse/insn-reverse.c | 43 +++++++++++++++ 2 files changed, 101 insertions(+), 35 deletions(-) diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 0c0e1a5..5c5524b 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -10909,13 +10909,13 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) const int num_regs = gdbarch_num_regs (arm_insn_r->gdbarch); opcode = bits (arm_insn_r->arm_insn, 20, 24); - single_reg = bit (arm_insn_r->arm_insn, 8); + single_reg = !bit (arm_insn_r->arm_insn, 8); op_vldm_vstm = opcode & 0x1b; /* Handle VMOV instructions. */ if ((opcode & 0x1e) == 0x04) { - if (bit (arm_insn_r->arm_insn, 4)) + if (bit (arm_insn_r->arm_insn, 20)) /* to_arm_registers bit 20? */ { record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15); record_buf[1] = bits (arm_insn_r->arm_insn, 16, 19); @@ -10923,18 +10923,29 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) } else { - uint8_t reg_m = ((bits (arm_insn_r->arm_insn, 0, 3) << 1) - | bit (arm_insn_r->arm_insn, 5)); + uint8_t reg_m = bits (arm_insn_r->arm_insn, 0, 3); + uint8_t bit_m = bit (arm_insn_r->arm_insn, 5); - if (!single_reg) + if (single_reg) { - record_buf[0] = num_regs + reg_m; - record_buf[1] = num_regs + reg_m + 1; - arm_insn_r->reg_rec_count = 2; + /* The first S register number m is REG_M:M (M is bit 5), + the corresponding D register number is REG_M:M / 2, which + is REG_M. */ + record_buf[arm_insn_r->reg_rec_count++] = ARM_D0_REGNUM + reg_m; + /* The second S register number is REG_M:M + 1, the + corresponding D register number is (REG_M:M + 1) / 2. + IOW, if bit M is 1, the first and second S registers + are mapped to different D registers, otherwise, they are + in the same D register. */ + if (bit_m) + { + record_buf[arm_insn_r->reg_rec_count++] + = ARM_D0_REGNUM + reg_m + 1; + } } else { - record_buf[0] = reg_m + ARM_D0_REGNUM; + record_buf[0] = ((bit_m << 4) + reg_m + ARM_D0_REGNUM); arm_insn_r->reg_rec_count = 1; } } @@ -10949,7 +10960,7 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) reg_rn = bits (arm_insn_r->arm_insn, 16, 19); regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval); imm_off8 = bits (arm_insn_r->arm_insn, 0, 7); - imm_off32 = imm_off8 << 24; + imm_off32 = imm_off8 << 2; memory_count = imm_off8; if (bit (arm_insn_r->arm_insn, 23)) @@ -10965,19 +10976,19 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) while (memory_count > 0) { - if (!single_reg) + if (single_reg) { - record_buf_mem[memory_index] = start_address; - record_buf_mem[memory_index + 1] = 4; + record_buf_mem[memory_index] = 4; + record_buf_mem[memory_index + 1] = start_address; start_address = start_address + 4; memory_index = memory_index + 2; } else { - record_buf_mem[memory_index] = start_address; - record_buf_mem[memory_index + 1] = 4; - record_buf_mem[memory_index + 2] = start_address + 4; - record_buf_mem[memory_index + 3] = 4; + record_buf_mem[memory_index] = 4; + record_buf_mem[memory_index + 1] = start_address; + record_buf_mem[memory_index + 2] = 4; + record_buf_mem[memory_index + 3] = start_address + 4; start_address = start_address + 8; memory_index = memory_index + 4; } @@ -10991,25 +11002,36 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) { uint32_t reg_count, reg_vd; uint32_t reg_index = 0; + uint32_t bit_d = bit (arm_insn_r->arm_insn, 22); reg_vd = bits (arm_insn_r->arm_insn, 12, 15); reg_count = bits (arm_insn_r->arm_insn, 0, 7); - if (single_reg) - reg_vd = reg_vd | (bit (arm_insn_r->arm_insn, 22) << 4); - else - reg_vd = (reg_vd << 1) | bit (arm_insn_r->arm_insn, 22); + /* REG_VD is the first D register number. If the instruction + loads memory to S registers (SINGLE_REG is TRUE), the register + number is (REG_VD << 1 | bit D), so the corresponding D + register number is (REG_VD << 1 | bit D) / 2 = REG_VD. */ + if (!single_reg) + reg_vd = reg_vd | (bit_d << 4); - if (bit (arm_insn_r->arm_insn, 21)) + if (bit (arm_insn_r->arm_insn, 21) /* write back */) record_buf[reg_index++] = bits (arm_insn_r->arm_insn, 16, 19); - while (reg_count > 0) + /* If the instruction loads memory to D register, REG_COUNT should + divide 2, according to the ARM Architecture Reference Manual. + If the instruction loads memory to S register, divide 2 as well + because two S registers are mapped to D register. */ + reg_count = reg_count / 2; + if (single_reg && bit_d) { - if (single_reg) - record_buf[reg_index++] = num_regs + reg_vd + reg_count - 1; - else - record_buf[reg_index++] = ARM_D0_REGNUM + reg_vd + reg_count - 1; + /* Increase the register count if S register list starts from + odd number (bit d is one). */ + reg_count++; + } + while (reg_count > 0) + { + record_buf[reg_index++] = ARM_D0_REGNUM + reg_vd + reg_count - 1; reg_count--; } arm_insn_r->reg_rec_count = reg_index; @@ -11023,7 +11045,7 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) reg_rn = bits (arm_insn_r->arm_insn, 16, 19); regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval); imm_off8 = bits (arm_insn_r->arm_insn, 0, 7); - imm_off32 = imm_off8 << 24; + imm_off32 = imm_off8 << 2; if (bit (arm_insn_r->arm_insn, 23)) start_address = u_regval + imm_off32; @@ -11032,16 +11054,16 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) if (single_reg) { - record_buf_mem[memory_index] = start_address; - record_buf_mem[memory_index + 1] = 4; + record_buf_mem[memory_index] = 4; + record_buf_mem[memory_index + 1] = start_address; arm_insn_r->mem_rec_count = 1; } else { - record_buf_mem[memory_index] = start_address; - record_buf_mem[memory_index + 1] = 4; - record_buf_mem[memory_index + 2] = start_address + 4; - record_buf_mem[memory_index + 3] = 4; + record_buf_mem[memory_index] = 4; + record_buf_mem[memory_index + 1] = start_address; + record_buf_mem[memory_index + 2] = 4; + record_buf_mem[memory_index + 3] = start_address + 4; arm_insn_r->mem_rec_count = 2; } } @@ -11058,7 +11080,8 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) else { reg_vd = (reg_vd << 1) | bit (arm_insn_r->arm_insn, 22); - record_buf[0] = num_regs + reg_vd; + /* Record register D rather than pseudo register S. */ + record_buf[0] = ARM_D0_REGNUM + reg_vd / 2; } arm_insn_r->reg_rec_count = 1; } diff --git a/gdb/testsuite/gdb.reverse/insn-reverse.c b/gdb/testsuite/gdb.reverse/insn-reverse.c index 1bfb8b0..22cd267 100644 --- a/gdb/testsuite/gdb.reverse/insn-reverse.c +++ b/gdb/testsuite/gdb.reverse/insn-reverse.c @@ -88,6 +88,45 @@ adv_simd_vect_shift (void) { asm ("fcvtzs s0, s0, #1"); } +#elif (defined __arm__) +static void +ext_reg_load (void) +{ + char in[8]; + + asm ("vldr d0, [%0]" : : "r" (in)); + asm ("vldr s3, [%0]" : : "r" (in)); + + asm ("vldm %0, {d3-d4}" : : "r" (in)); + asm ("vldm %0, {s9-s11}" : : "r" (in)); +} + +static void +ext_reg_mov (void) +{ + int i, j; + double d; + + i = 1; + j = 2; + + asm ("vmov s4, s5, %0, %1" : "=r" (i), "=r" (j): ); + asm ("vmov s7, s8, %0, %1" : "=r" (i), "=r" (j): ); + asm ("vmov %0, %1, s10, s11" : : "r" (i), "r" (j)); + asm ("vmov %0, %1, s1, s2" : : "r" (i), "r" (j)); + + asm ("vmov %P2, %0, %1" : "=r" (i), "=r" (j): "w" (d)); + asm ("vmov %1, %2, %P0" : "=w" (d) : "r" (i), "r" (j)); +} + +static void +ext_reg_push_pop (void) +{ + double d; + + asm ("vpush {%P0}" : : "w" (d)); + asm ("vpop {%P0}" : : "w" (d)); +} #endif typedef void (*testcase_ftype) (void); @@ -104,6 +143,10 @@ static testcase_ftype testcases[] = adv_simd_scalar_index, adv_simd_smlal, adv_simd_vect_shift, +#elif (defined __arm__) + ext_reg_load, + ext_reg_mov, + ext_reg_push_pop, #endif };