From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14182 invoked by alias); 1 Jun 2003 03:57:34 -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 14149 invoked from network); 1 Jun 2003 03:57:33 -0000 Received: from unknown (HELO are.twiddle.net) (64.81.246.98) by sources.redhat.com with SMTP; 1 Jun 2003 03:57:33 -0000 Received: from are.twiddle.net (localhost.localdomain [127.0.0.1]) by are.twiddle.net (8.12.8/8.12.8) with ESMTP id h513vWLH002080 for ; Sat, 31 May 2003 20:57:32 -0700 Received: (from rth@localhost) by are.twiddle.net (8.12.8/8.12.8/Submit) id h513vWNT002078 for gdb-patches@sources.redhat.com; Sat, 31 May 2003 20:57:32 -0700 X-Authentication-Warning: are.twiddle.net: rth set sender to rth@twiddle.net using -f Date: Sun, 01 Jun 2003 03:57:00 -0000 From: Richard Henderson To: gdb-patches@sources.redhat.com Subject: [RFA] update alpha for push_dummy_call Message-ID: <20030601035732.GA2062@twiddle.net> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.4i X-SW-Source: 2003-06/txt/msg00004.txt.bz2 Ok? r~ * alpha-tdep.c (alpha_push_dummy_call): Transmography from alpha_push_arguments. Don't dump argument register data to the target stack. Fix float and 128-bit long double semantics. Store $t12 and $ra as specified by the ABI. Use regcache everywhere. (alpha_fix_call_dummy): Remove. (alpha_call_dummy_words): Remove. (alpha_gdbarch_init): Kill deprecated call hooks; add push_dummy_call. Index: alpha-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/alpha-tdep.c,v retrieving revision 1.88 diff -c -p -d -r1.88 alpha-tdep.c *** alpha-tdep.c 31 May 2003 00:27:45 -0000 1.88 --- alpha-tdep.c 1 Jun 2003 03:39:04 -0000 *************** alpha_register_convert_to_raw (struct ty *** 173,210 **** /* The alpha passes the first six arguments in the registers, the rest on ! the stack. The register arguments are eventually transferred to the ! argument transfer area immediately below the stack by the called function ! anyway. So we `push' at least six arguments on the stack, `reload' the ! argument registers and then adjust the stack pointer to point past the ! sixth argument. This algorithm simplifies the passing of a large struct ! which extends from the registers to the stack. If the called function is returning a structure, the address of the structure to be returned is passed as a hidden first argument. */ static CORE_ADDR ! alpha_push_arguments (int nargs, struct value **args, CORE_ADDR sp, ! int struct_return, CORE_ADDR struct_addr) { int i; int accumulate_size = struct_return ? 8 : 0; - int arg_regs_size = ALPHA_NUM_ARG_REGS * 8; struct alpha_arg { char *contents; int len; int offset; }; ! struct alpha_arg *alpha_args = ! (struct alpha_arg *) alloca (nargs * sizeof (struct alpha_arg)); register struct alpha_arg *m_arg; ! char raw_buffer[ALPHA_REGISTER_BYTES]; int required_arg_regs; for (i = 0, m_arg = alpha_args; i < nargs; i++, m_arg++) { struct value *arg = args[i]; struct type *arg_type = check_typedef (VALUE_TYPE (arg)); /* Cast argument to long if necessary as the compiler does it too. */ switch (TYPE_CODE (arg_type)) { --- 173,222 ---- /* The alpha passes the first six arguments in the registers, the rest on ! the stack. The register arguments are stored in ARG_REG_BUFFER, and ! then moved into the register file; this simplifies the passing of a ! large struct which extends from the registers to the stack, plus avoids ! three ptrace invocations per word. ! ! We don't bother tracking which register values should go in integer ! regs or fp regs; we load the same values into both. ! If the called function is returning a structure, the address of the structure to be returned is passed as a hidden first argument. */ static CORE_ADDR ! alpha_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) { int i; int accumulate_size = struct_return ? 8 : 0; struct alpha_arg { char *contents; int len; int offset; }; ! struct alpha_arg *alpha_args ! = (struct alpha_arg *) alloca (nargs * sizeof (struct alpha_arg)); register struct alpha_arg *m_arg; ! char arg_reg_buffer[ALPHA_REGISTER_SIZE * ALPHA_NUM_ARG_REGS]; int required_arg_regs; + /* The ABI places the address of the called function in T12. */ + regcache_cooked_write_signed (regcache, ALPHA_T12_REGNUM, func_addr); + + /* Set the return address register to point to the entry point + of the program, where a breakpoint lies in wait. */ + regcache_cooked_write_signed (regcache, ALPHA_RA_REGNUM, bp_addr); + + /* Lay out the arguments in memory. */ for (i = 0, m_arg = alpha_args; i < nargs; i++, m_arg++) { struct value *arg = args[i]; struct type *arg_type = check_typedef (VALUE_TYPE (arg)); + /* Cast argument to long if necessary as the compiler does it too. */ switch (TYPE_CODE (arg_type)) { *************** alpha_push_arguments (int nargs, struct *** 219,224 **** --- 231,260 ---- arg = value_cast (arg_type, arg); } break; + case TYPE_CODE_FLT: + /* "float" arguments loaded in registers must be passed in + register format, aka "double". */ + if (accumulate_size < sizeof (arg_reg_buffer) + && TYPE_LENGTH (arg_type) == 4) + { + arg_type = builtin_type_double; + arg = value_cast (arg_type, arg); + } + /* Tru64 5.1 has a 128-bit long double, and passes this by + invisible reference. No one else uses this data type. */ + else if (TYPE_LENGTH (arg_type) == 16) + { + /* Allocate aligned storage. */ + sp = (sp & -16) - 16; + + /* Write the real data into the stack. */ + write_memory (sp, VALUE_CONTENTS (arg), 16); + + /* Construct the indirection. */ + arg_type = lookup_pointer_type (arg_type); + arg = value_from_pointer (arg_type, sp); + } + break; default: break; } *************** alpha_push_arguments (int nargs, struct *** 235,267 **** required_arg_regs = ALPHA_NUM_ARG_REGS; /* Make room for the arguments on the stack. */ ! if (accumulate_size < arg_regs_size) ! accumulate_size = arg_regs_size; sp -= accumulate_size; ! /* Keep sp aligned to a multiple of 16 as the compiler does it too. */ sp &= ~15; /* `Push' arguments on the stack. */ for (i = nargs; m_arg--, --i >= 0;) - write_memory (sp + m_arg->offset, m_arg->contents, m_arg->len); - if (struct_return) { ! store_unsigned_integer (raw_buffer, ALPHA_REGISTER_BYTES, struct_addr); ! write_memory (sp, raw_buffer, ALPHA_REGISTER_BYTES); } /* Load the argument registers. */ for (i = 0; i < required_arg_regs; i++) { LONGEST val; ! val = read_memory_integer (sp + i * 8, ALPHA_REGISTER_BYTES); ! write_register (ALPHA_A0_REGNUM + i, val); ! write_register (ALPHA_FPA0_REGNUM + i, val); } ! return sp + arg_regs_size; } /* Given a return value in `regbuf' with a type `valtype', --- 271,328 ---- required_arg_regs = ALPHA_NUM_ARG_REGS; /* Make room for the arguments on the stack. */ ! if (accumulate_size < sizeof(arg_reg_buffer)) ! accumulate_size = 0; ! else ! accumulate_size -= sizeof(arg_reg_buffer); sp -= accumulate_size; ! /* Keep sp aligned to a multiple of 16 as the ABI requires. */ sp &= ~15; /* `Push' arguments on the stack. */ for (i = nargs; m_arg--, --i >= 0;) { ! char *contents = m_arg->contents; ! int offset = m_arg->offset; ! int len = m_arg->len; ! ! /* Copy the bytes destined for registers into arg_reg_buffer. */ ! if (offset < sizeof(arg_reg_buffer)) ! { ! if (offset + len <= sizeof(arg_reg_buffer)) ! { ! memcpy (arg_reg_buffer + offset, contents, len); ! continue; ! } ! else ! { ! int tlen = sizeof(arg_reg_buffer) - offset; ! memcpy (arg_reg_buffer + offset, contents, tlen); ! offset += tlen; ! contents += tlen; ! len -= tlen; ! } ! } ! ! /* Everything else goes to the stack. */ ! write_memory (sp + offset - sizeof(arg_reg_buffer), contents, len); } + if (struct_return) + store_unsigned_integer (arg_reg_buffer, ALPHA_REGISTER_SIZE, struct_addr); /* Load the argument registers. */ for (i = 0; i < required_arg_regs; i++) { LONGEST val; ! val = extract_unsigned_integer (arg_reg_buffer + i*ALPHA_REGISTER_SIZE, ! ALPHA_REGISTER_SIZE); ! regcache_cooked_write_signed (regcache, ALPHA_A0_REGNUM + i, val); ! regcache_cooked_write_signed (regcache, ALPHA_FPA0_REGNUM + i, val); } ! return sp; } /* Given a return value in `regbuf' with a type `valtype', *************** alpha_skip_prologue (CORE_ADDR pc) *** 438,465 **** } - /* Construct an inferior call to FUN. For Alpha this is as simple as - initializing the RA and T12 registers; everything else is set up by - generic code. */ - - static void - alpha_fix_call_dummy (char *dummy, CORE_ADDR pc, CORE_ADDR fun, int nargs, - struct value **args, struct type *type, int gcc_p) - { - CORE_ADDR bp_address = CALL_DUMMY_ADDRESS (); - - if (bp_address == 0) - error ("no place to put call"); - write_register (ALPHA_RA_REGNUM, bp_address); - write_register (ALPHA_T12_REGNUM, fun); - } - - /* On the Alpha, the call dummy code is never copied to user space - (see alpha_fix_call_dummy() above). The contents of this do not - matter. */ - LONGEST alpha_call_dummy_words[] = { 0 }; - - /* Figure out where the longjmp will land. We expect the first arg to be a pointer to the jmp_buf structure from which we extract the PC (JB_PC) that we will land at. The PC is copied --- 499,504 ---- *************** alpha_gdbarch_init (struct gdbarch_info *** 1242,1252 **** alpha_extract_struct_value_address); /* Settings for calling functions in the inferior. */ ! set_gdbarch_deprecated_push_arguments (gdbarch, alpha_push_arguments); ! set_gdbarch_deprecated_call_dummy_words (gdbarch, alpha_call_dummy_words); ! set_gdbarch_deprecated_sizeof_call_dummy_words (gdbarch, 0); ! set_gdbarch_deprecated_pc_in_call_dummy (gdbarch, deprecated_pc_in_call_dummy_at_entry_point); ! set_gdbarch_deprecated_fix_call_dummy (gdbarch, alpha_fix_call_dummy); /* Methods for saving / extracting a dummy frame's ID. */ set_gdbarch_unwind_dummy_id (gdbarch, alpha_unwind_dummy_id); --- 1281,1287 ---- alpha_extract_struct_value_address); /* Settings for calling functions in the inferior. */ ! set_gdbarch_push_dummy_call (gdbarch, alpha_push_dummy_call); /* Methods for saving / extracting a dummy frame's ID. */ set_gdbarch_unwind_dummy_id (gdbarch, alpha_unwind_dummy_id);