From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28026 invoked by alias); 24 Apr 2004 19:02:13 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 28004 invoked from network); 24 Apr 2004 19:02:11 -0000 Received: from unknown (HELO pippin.tausq.org) (64.81.244.94) by sources.redhat.com with SMTP; 24 Apr 2004 19:02:11 -0000 Received: by pippin.tausq.org (Postfix, from userid 1000) id 94D81CD299; Sat, 24 Apr 2004 12:02:31 -0700 (PDT) Date: Sat, 24 Apr 2004 19:02:00 -0000 From: Randolph Chung To: gdb-patches@sources.redhat.com Subject: [patch/rfa] fix call-dummies for hppa Message-ID: <20040424190231.GC2923@tausq.org> Reply-To: Randolph Chung Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-GPG: for GPG key, see http://www.tausq.org/gpg.txt User-Agent: Mutt/1.5.5.1+cvs20040105i X-SW-Source: 2004-04/txt/msg00603.txt.bz2 This fixes a few bugs in the 32-bit version of the hppa push_dummy_call method. Tested against hppa2.0w-hp-hpux11.11 and hppa-linux. All of structs.exp pass, there are still some failures in call-sc.exp and callfuncs.exp. In the latter case it appears most are due to problems with calling malloc() in the inferior (at least on hppa-linux). ok to apply? thanks randolph 2004-04-24 Randolph Chung * hppa-tdep.c (hppa32_push_dummy_call): Fix small struct and floating point argument passing, and make sure the stack frame is properly aligned. Index: hppa-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/hppa-tdep.c,v retrieving revision 1.151 diff -u -p -r1.151 hppa-tdep.c --- hppa-tdep.c 24 Apr 2004 06:13:32 -0000 1.151 +++ hppa-tdep.c 24 Apr 2004 18:51:44 -0000 @@ -758,16 +759,13 @@ hppa64_register_name (int i) We simply allocate the appropriate amount of stack space and put arguments into their proper slots. */ - + CORE_ADDR hppa32_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr, struct regcache *regcache, CORE_ADDR bp_addr, int nargs, struct value **args, CORE_ADDR sp, int struct_return, CORE_ADDR struct_addr) { - /* NOTE: cagney/2004-02-27: This is a guess - its implemented by - reverse engineering testsuite failures. */ - /* Stack base address at which any pass-by-reference parameters are stored. */ CORE_ADDR struct_end = 0; @@ -781,12 +779,15 @@ hppa32_push_dummy_call (struct gdbarch * /* Two passes. First pass computes the location of everything, second pass writes the bytes out. */ int write_pass; + for (write_pass = 0; write_pass < 2; write_pass++) { CORE_ADDR struct_ptr = 0; - CORE_ADDR param_ptr = 0; - int reg = 27; /* NOTE: Registers go down. */ + /* The first parameter goes into sp-36, each stack slot is 4-bytes. */ + CORE_ADDR param_ptr = 32; int i; + int small_struct = 0; + for (i = 0; i < nargs; i++) { struct value *arg = args[i]; @@ -795,6 +796,7 @@ hppa32_push_dummy_call (struct gdbarch * stack, and [possibly] passed in a register. */ char param_val[8]; int param_len; + memset (param_val, 0, sizeof param_val); if (TYPE_LENGTH (type) > 8) { @@ -813,27 +815,76 @@ hppa32_push_dummy_call (struct gdbarch * /* Integer value store, right aligned. "unpack_long" takes care of any sign-extension problems. */ param_len = align_up (TYPE_LENGTH (type), 4); + store_unsigned_integer (param_val, param_len, unpack_long (type, VALUE_CONTENTS (arg))); } + else if (TYPE_CODE (type) == TYPE_CODE_FLT) + { + param_len = align_up (TYPE_LENGTH (type), 4); + memcpy (param_val, VALUE_CONTENTS (arg), param_len); + } else { - /* Small struct value, store right aligned? */ param_len = align_up (TYPE_LENGTH (type), 4); + + /* Small struct value are stored right-aligned. */ memcpy (param_val + param_len - TYPE_LENGTH (type), VALUE_CONTENTS (arg), TYPE_LENGTH (type)); + + /* Structures of size 5, 6 and 7 bytes are special in that + the higher-ordered word is stored in the lower-ordered + argument, and even though it is a 8-byte quantity the + registers need not be 8-byte aligned. */ + if (param_len > 4) + small_struct = 1; } + param_ptr += param_len; - reg -= param_len / 4; + if (param_len == 8 && !small_struct) + param_ptr += (param_ptr & 4); + + /* First 4 non-FP arguments are passed in gr26-gr23. + First 4 32-bit FP arguments are passed in fr4L-fr7L. + First 2 64-bit FP arguments are passed in fr5 and fr7. + + The rest go on the stack, starting at sp-36, towards lower + addresses. 8-byte arguments must be aligned to a 8-byte + stack boundary. */ if (write_pass) { write_memory (param_end - param_ptr, param_val, param_len); - if (reg >= 23) + + /* There are some cases when we don't know the type + expected by the callee (e.g. for variadic functions), so + pass the parameters in both general and fp regs. */ + if (param_ptr <= 48) { - regcache_cooked_write (regcache, reg, param_val); + int grreg = 26 - (param_ptr - 36) / 4; + int fpLreg = 72 + (param_ptr - 36) / 4 * 2; + int fpreg = 74 + (param_ptr - 40) / 8 * 4; + + regcache_cooked_write (regcache, grreg, param_val); + regcache_cooked_write (regcache, fpLreg, param_val); + if (param_len > 4) - regcache_cooked_write (regcache, reg + 1, param_val + 4); + { + if (!small_struct) + { + regcache_cooked_write (regcache, grreg - 1, + param_val + 4); + + regcache_cooked_write (regcache, fpreg, param_val); + regcache_cooked_write (regcache, fpreg + 1, + param_val + 4); + } + else + { + regcache_cooked_write (regcache, grreg + 1, + param_val + 4); + } + } } } } @@ -841,13 +892,13 @@ hppa32_push_dummy_call (struct gdbarch * /* Update the various stack pointers. */ if (!write_pass) { - struct_end = sp + struct_ptr; + struct_end = sp + align_up (struct_ptr, 64); /* PARAM_PTR already accounts for all the arguments passed by the user. However, the ABI mandates minimum stack space allocations for outgoing arguments. The ABI also mandates minimum stack alignments which we must preserve. */ - param_end = struct_end + max (align_up (param_ptr, 8), 16); + param_end = struct_end + align_up (param_ptr, 64); } } @@ -860,10 +911,9 @@ hppa32_push_dummy_call (struct gdbarch * regcache_cooked_write_unsigned (regcache, RP_REGNUM, bp_addr); /* Update the Stack Pointer. */ - regcache_cooked_write_unsigned (regcache, SP_REGNUM, param_end + 32); + regcache_cooked_write_unsigned (regcache, SP_REGNUM, param_end); - /* The stack will have 32 bytes of additional space for a frame marker. */ - return param_end + 32; + return param_end; } /* This function pushes a stack frame with arguments as part of the -- Randolph Chung Debian GNU/Linux Developer, hppa/ia64 ports http://www.tausq.org/