From 8b0f5a9df9bd20b51eb9e088350330fdbc96a9dc Mon Sep 17 00:00:00 2001 From: David Edelsohn Date: Fri, 3 Mar 1995 09:06:51 +0000 Subject: [PATCH] * sparc-tdep.c (decode_asi): New function. (sparc_print_register_hook): Pretty print more v9 registers. --- gdb/ChangeLog | 6 + gdb/sparc-tdep.c | 443 ++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 388 insertions(+), 61 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index c0fb9dde07..f0bf658dae 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +Fri Mar 3 00:54:58 1995 Doug Evans + + * sparc-tdep.c (decode_asi): New function. + (sparc_print_register_hook): Pretty print more v9 registers. + * sparc/tm-sp64.h (REGISTER_NAMES): Fix some typos. + Thu Mar 2 22:20:22 1995 Doug Evans * dwarfread.c (struct dieinfo): Use CORE_ADDR for at_{low,high}_pc. diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c index 96cea9df10..c83cbcde5b 100644 --- a/gdb/sparc-tdep.c +++ b/gdb/sparc-tdep.c @@ -1,5 +1,5 @@ /* Target-dependent code for the SPARC for GDB, the GNU debugger. - Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994 + Copyright 1986, 1987, 1989, 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc. This file is part of GDB. @@ -18,6 +18,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +/* ??? Support for calling functions from gdb in sparc64 is unfinished. */ + #include "defs.h" #include "frame.h" #include "inferior.h" @@ -31,6 +33,14 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "gdbcore.h" +#ifdef GDB_TARGET_IS_SPARC64 +#define NUM_SPARC_FPREGS 64 +#else +#define NUM_SPARC_FPREGS 32 +#endif + +#define SPARC_INTREG_SIZE (REGISTER_RAW_SIZE (G0_REGNUM)) + /* From infrun.c */ extern int stop_after_trap; @@ -42,6 +52,9 @@ extern int stop_after_trap; int deferred_stores = 0; /* Cumulates stores we want to do eventually. */ +/* Branches with prediction are treated like their non-predicting cousins. */ +/* FIXME: What about floating point branches? */ + /* Macros to extract fields from sparc instructions. */ #define X_OP(i) (((i) >> 30) & 0x3) #define X_RD(i) (((i) >> 25) & 0x1f) @@ -56,10 +69,21 @@ int deferred_stores = 0; /* Cumulates stores we want to do eventually. */ /* Sign extension macros. */ #define X_SIMM13(i) ((X_IMM13 (i) ^ 0x1000) - 0x1000) #define X_DISP22(i) ((X_IMM22 (i) ^ 0x200000) - 0x200000) +#ifdef GDB_TARGET_IS_SPARC64 +#define X_CC(i) (((i) >> 20) & 3) +#define X_P(i) (((i) >> 19) & 1) +#define X_DISP19(i) ((((i) & 0x7ffff) ^ 0x40000) - 0x40000) +#define X_RCOND(i) (((i) >> 25) & 7) +#define X_DISP16(i) ((((((i) >> 6) && 0xc000) | ((i) & 0x3fff)) ^ 0x8000) - 0x8000) +#define X_FCN(i) (((i) >> 25) & 31) +#endif typedef enum { - Error, not_branch, bicc, bicca, ba, baa, ticc, ta + Error, not_branch, bicc, bicca, ba, baa, ticc, ta, +#ifdef GDB_TARGET_IS_SPARC64 + done_retry +#endif } branch_type; /* Simulate single-step ptrace call for sun4. Code written by Gary @@ -91,7 +115,7 @@ void single_step (ignore) int ignore; /* pid, but we don't need it */ { - branch_type br, isannulled(); + branch_type br, isbranch(); CORE_ADDR pc; long pc_instruction; @@ -106,7 +130,7 @@ single_step (ignore) pc = read_register (PC_REGNUM); pc_instruction = read_memory_integer (pc, 4); - br = isannulled (pc_instruction, pc, &target); + br = isbranch (pc_instruction, pc, &target); brknpc4 = brktrg = 0; if (br == bicca) @@ -124,6 +148,13 @@ single_step (ignore) brktrg = 1; target_insert_breakpoint (target, break_mem[2]); } +#ifdef GDB_TARGET_IS_SPARC64 + else if (br == done_retry) + { + brktrg = 1; + target_insert_breakpoint (target, break_mem[2]); + } +#endif /* We are ready to let it go */ one_stepped = 1; @@ -248,7 +279,7 @@ CORE_ADDR sparc_extract_struct_value_address (regbuf) char regbuf[REGISTER_BYTES]; { - return read_memory_integer (((int *)(regbuf))[SP_REGNUM]+(16*4), + return read_memory_integer (((int *)(regbuf)) [SP_REGNUM] + (16 * SPARC_INTREG_SIZE), TARGET_PTR_BIT / TARGET_CHAR_BIT); } @@ -285,7 +316,7 @@ sparc_frame_saved_pc (frame) /* The sigcontext address is contained in register O2. */ get_saved_register (buf, (int *)NULL, (CORE_ADDR *)NULL, frame, O0_REGNUM + 2, (enum lval_type *)NULL); - sigcontext_addr = extract_address (buf, REGISTER_RAW_SIZE (O0_REGNUM)); + sigcontext_addr = extract_address (buf, REGISTER_RAW_SIZE (O0_REGNUM + 2)); /* Don't cause a memory_error when accessing sigcontext in case the stack layout has changed or the stack is corrupt. */ @@ -297,15 +328,15 @@ sparc_frame_saved_pc (frame) addr = frame->pc_addr; else addr = frame->bottom + FRAME_SAVED_I0 + - REGISTER_RAW_SIZE (I7_REGNUM) * (I7_REGNUM - I0_REGNUM); + SPARC_INTREG_SIZE * (I7_REGNUM - I0_REGNUM); if (addr == 0) /* A flat frame leaf function might not save the PC anywhere, just leave it in %o7. */ return PC_ADJUST (read_register (O7_REGNUM)); - read_memory (addr, buf, REGISTER_RAW_SIZE (I7_REGNUM)); - return PC_ADJUST (extract_address (buf, REGISTER_RAW_SIZE (I7_REGNUM))); + read_memory (addr, buf, SPARC_INTREG_SIZE); + return PC_ADJUST (extract_address (buf, SPARC_INTREG_SIZE)); } /* Since an individual frame in the frame cache is defined by two @@ -469,12 +500,14 @@ skip_prologue (start_pc, frameless_p) return examine_prologue (start_pc, frameless_p, NULL, NULL); } -/* Check instruction at ADDR to see if it is an annulled branch. - All other instructions will go to NPC or will trap. - Set *TARGET if we find a candidate branch; set to zero if not. */ - +/* Check instruction at ADDR to see if it is a branch. + All non-annulled instructions will go to NPC or will trap. + Set *TARGET if we find a candidate branch; set to zero if not. + + This isn't static as it's used by remote-sa.sparc.c. */ + branch_type -isannulled (instruction, addr, target) +isbranch (instruction, addr, target) long instruction; CORE_ADDR addr, *target; { @@ -486,15 +519,58 @@ isannulled (instruction, addr, target) if (X_OP (instruction) == 0 && (X_OP2 (instruction) == 2 || X_OP2 (instruction) == 6 - || X_OP2 (instruction) == 7)) +#ifdef GDB_TARGET_IS_SPARC64 + || X_OP2 (instruction) == 1 + || X_OP2 (instruction) == 3 + || X_OP2 (instruction) == 5 +#else + || X_OP2 (instruction) == 7 +#endif + )) { if (X_COND (instruction) == 8) val = X_A (instruction) ? baa : ba; else val = X_A (instruction) ? bicca : bicc; - offset = 4 * X_DISP22 (instruction); + switch (X_OP (instruction)) + { + case 2: + case 6: +#ifndef GDB_TARGET_IS_SPARC64 + case 7: +#endif + offset = 4 * X_DISP22 (instruction); + break; +#ifdef GDB_TARGET_IS_SPARC64 + case 1: + case 5: + offset = 4 * X_DISP19 (instruction); + break; + case 3: + offset = 4 * X_DISP16 (instruction); + break; +#endif + } *target = addr + offset; } +#ifdef GDB_TARGET_IS_SPARC64 + else if (X_OP (instruction) == 2 + && X_OP3 (instruction) == 62) + { + if (X_FCN (instruction) == 0) + { + /* done */ + *target = read_register (TNPC_REGNUM); + val = done_retry; + } + else if (X_FCN (instruction) == 1) + { + /* retry */ + *target = read_register (TPC_REGNUM); + val = done_retry; + } + } +#endif return val; } @@ -534,14 +610,19 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval) && frame1->pc <= FRAME_FP (frame1)) { /* Dummy frame. All but the window regs are in there somewhere. */ + /* FIXME: The offsets are wrong for sparc64 (eg: 0xa0). */ if (regnum >= G1_REGNUM && regnum < G1_REGNUM + 7) - addr = frame1->frame + (regnum - G0_REGNUM) * 4 - 0xa0; + addr = frame1->frame + (regnum - G0_REGNUM) * SPARC_INTREG_SIZE + - (NUM_SPARC_FPREGS * 4 + 8 * SPARC_INTREG_SIZE); else if (regnum >= I0_REGNUM && regnum < I0_REGNUM + 8) - addr = frame1->frame + (regnum - I0_REGNUM) * 4 - 0xc0; - else if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM + 32) - addr = frame1->frame + (regnum - FP0_REGNUM) * 4 - 0x80; + addr = frame1->frame + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE + - (NUM_SPARC_FPREGS * 4 + 16 * SPARC_INTREG_SIZE); + else if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM + NUM_SPARC_FPREGS) + addr = frame1->frame + (regnum - FP0_REGNUM) * 4 + - (NUM_SPARC_FPREGS * 4); else if (regnum >= Y_REGNUM && regnum < NUM_REGS) - addr = frame1->frame + (regnum - Y_REGNUM) * 4 - 0xe0; + addr = frame1->frame + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE + - (NUM_SPARC_FPREGS * 4 + 24 * SPARC_INTREG_SIZE); } else if (frame1->flat) { @@ -566,11 +647,11 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval) /* Normal frame. Local and In registers are saved on stack. */ if (regnum >= I0_REGNUM && regnum < I0_REGNUM + 8) addr = (frame1->prev->bottom - + (regnum - I0_REGNUM) * REGISTER_RAW_SIZE (I0_REGNUM) + + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE + FRAME_SAVED_I0); else if (regnum >= L0_REGNUM && regnum < L0_REGNUM + 8) addr = (frame1->prev->bottom - + (regnum - L0_REGNUM) * REGISTER_RAW_SIZE (L0_REGNUM) + + (regnum - L0_REGNUM) * SPARC_INTREG_SIZE + FRAME_SAVED_L0); else if (regnum >= O0_REGNUM && regnum < O0_REGNUM + 8) { @@ -622,32 +703,53 @@ get_saved_register (raw_buffer, optimized, addrp, frame, regnum, lval) /* Definitely see tm-sparc.h for more doc of the frame format here. */ +#ifdef GDB_TARGET_IS_SPARC64 +#define DUMMY_REG_SAVE_OFFSET (128 + 16) +#else +#define DUMMY_REG_SAVE_OFFSET 0x60 +#endif + +/* See tm-sparc.h for how this is calculated. */ +#define DUMMY_STACK_REG_BUF_SIZE \ +(((8+8+8) * SPARC_INTREG_SIZE) + (32 * REGISTER_RAW_SIZE (FP0_REGNUM))) +#define DUMMY_STACK_SIZE (DUMMY_STACK_REG_BUF_SIZE + DUMMY_REG_SAVE_OFFSET) + void sparc_push_dummy_frame () { CORE_ADDR sp, old_sp; - char register_temp[0x140]; + char register_temp[DUMMY_STACK_SIZE]; old_sp = sp = read_register (SP_REGNUM); +#ifdef GDB_TARGET_IS_SPARC64 + /* FIXME: not sure what needs to be saved here. */ +#else /* Y, PS, WIM, TBR, PC, NPC, FPS, CPS regs */ read_register_bytes (REGISTER_BYTE (Y_REGNUM), ®ister_temp[0], REGISTER_RAW_SIZE (Y_REGNUM) * 8); +#endif - read_register_bytes (REGISTER_BYTE (O0_REGNUM), ®ister_temp[8 * 4], - REGISTER_RAW_SIZE (O0_REGNUM) * 8); + read_register_bytes (REGISTER_BYTE (O0_REGNUM), + ®ister_temp[8 * SPARC_INTREG_SIZE], + SPARC_INTREG_SIZE * 8); - read_register_bytes (REGISTER_BYTE (G0_REGNUM), ®ister_temp[16 * 4], - REGISTER_RAW_SIZE (G0_REGNUM) * 8); + read_register_bytes (REGISTER_BYTE (G0_REGNUM), + ®ister_temp[16 * SPARC_INTREG_SIZE], + SPARC_INTREG_SIZE * 8); - read_register_bytes (REGISTER_BYTE (FP0_REGNUM), ®ister_temp[24 * 4], + /* ??? The 32 here should be NUM_SPARC_FPREGS, but until we decide what + REGISTER_RAW_SIZE should be for fp regs, it's left as is. */ + read_register_bytes (REGISTER_BYTE (FP0_REGNUM), + ®ister_temp[24 * SPARC_INTREG_SIZE], REGISTER_RAW_SIZE (FP0_REGNUM) * 32); - sp -= 0x140; + sp -= DUMMY_STACK_SIZE; write_register (SP_REGNUM, sp); - write_memory (sp + 0x60, ®ister_temp[0], (8 + 8 + 8 + 32) * 4); + write_memory (sp + DUMMY_REG_SAVE_OFFSET, ®ister_temp[0], + DUMMY_STACK_REG_BUF_SIZE); write_register (FP_REGNUM, old_sp); @@ -712,16 +814,20 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr) /* Dummy frame. All but the window regs are in there somewhere. */ for (regnum = G1_REGNUM; regnum < G1_REGNUM+7; regnum++) saved_regs_addr->regs[regnum] = - frame_addr + (regnum - G0_REGNUM) * 4 - 0xa0; + frame_addr + (regnum - G0_REGNUM) * SPARC_INTREG_SIZE + - (NUM_SPARC_FPREGS * 4 + 8 * SPARC_INTREG_SIZE); for (regnum = I0_REGNUM; regnum < I0_REGNUM+8; regnum++) saved_regs_addr->regs[regnum] = - frame_addr + (regnum - I0_REGNUM) * 4 - 0xc0; + frame_addr + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE + - (NUM_SPARC_FPREGS * 4 + 16 * SPARC_INTREG_SIZE); for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 32; regnum++) saved_regs_addr->regs[regnum] = - frame_addr + (regnum - FP0_REGNUM) * 4 - 0x80; + frame_addr + (regnum - FP0_REGNUM) * 4 + - (NUM_SPARC_FPREGS * 4); for (regnum = Y_REGNUM; regnum < NUM_REGS; regnum++) saved_regs_addr->regs[regnum] = - frame_addr + (regnum - Y_REGNUM) * 4 - 0xe0; + frame_addr + (regnum - Y_REGNUM) * SPARC_INTREG_SIZE - 0xe0; + - (NUM_SPARC_FPREGS * 4 + 24 * SPARC_INTREG_SIZE); frame_addr = fi->bottom ? fi->bottom : read_register (SP_REGNUM); } @@ -742,11 +848,11 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr) fi->bottom : read_register (SP_REGNUM); for (regnum = L0_REGNUM; regnum < L0_REGNUM+8; regnum++) saved_regs_addr->regs[regnum] = - (frame_addr + (regnum - L0_REGNUM) * REGISTER_RAW_SIZE (L0_REGNUM) + (frame_addr + (regnum - L0_REGNUM) * SPARC_INTREG_SIZE + FRAME_SAVED_L0); for (regnum = I0_REGNUM; regnum < I0_REGNUM+8; regnum++) saved_regs_addr->regs[regnum] = - (frame_addr + (regnum - I0_REGNUM) * REGISTER_RAW_SIZE (I0_REGNUM) + (frame_addr + (regnum - I0_REGNUM) * SPARC_INTREG_SIZE + FRAME_SAVED_I0); } if (fi->next) @@ -765,7 +871,7 @@ sparc_frame_find_saved_regs (fi, saved_regs_addr) for (regnum = O0_REGNUM; regnum < O0_REGNUM+8; regnum++) saved_regs_addr->regs[regnum] = (next_next_frame_addr - + (regnum - O0_REGNUM) * REGISTER_RAW_SIZE (O0_REGNUM) + + (regnum - O0_REGNUM) * SPARC_INTREG_SIZE + FRAME_SAVED_I0); } } @@ -799,9 +905,11 @@ sparc_pop_frame () sparc_frame_find_saved_regs (frame, &fsr); if (fsr.regs[FP0_REGNUM]) { - read_memory (fsr.regs[FP0_REGNUM], raw_buffer, 32 * 4); - write_register_bytes (REGISTER_BYTE (FP0_REGNUM), raw_buffer, 32 * 4); + read_memory (fsr.regs[FP0_REGNUM], raw_buffer, NUM_SPARC_FPREGS * 4); + write_register_bytes (REGISTER_BYTE (FP0_REGNUM), + raw_buffer, NUM_SPARC_FPREGS * 4); } +#ifndef GDB_TARGET_IS_SPARC64 if (fsr.regs[FPS_REGNUM]) { read_memory (fsr.regs[FPS_REGNUM], raw_buffer, 4); @@ -812,10 +920,12 @@ sparc_pop_frame () read_memory (fsr.regs[CPS_REGNUM], raw_buffer, 4); write_register_bytes (REGISTER_BYTE (CPS_REGNUM), raw_buffer, 4); } +#endif if (fsr.regs[G1_REGNUM]) { - read_memory (fsr.regs[G1_REGNUM], raw_buffer, 7 * 4); - write_register_bytes (REGISTER_BYTE (G1_REGNUM), raw_buffer, 7 * 4); + read_memory (fsr.regs[G1_REGNUM], raw_buffer, 7 * SPARC_INTREG_SIZE); + write_register_bytes (REGISTER_BYTE (G1_REGNUM), raw_buffer, + 7 * SPARC_INTREG_SIZE); } if (frame->flat) @@ -824,18 +934,22 @@ sparc_pop_frame () individually. */ for (regnum = L0_REGNUM; regnum < L0_REGNUM + 8; ++regnum) if (fsr.regs[regnum]) - write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); + write_register (regnum, read_memory_integer (fsr.regs[regnum], + SPARC_INTREG_SIZE)); for (regnum = I0_REGNUM; regnum < I0_REGNUM + 8; ++regnum) if (fsr.regs[regnum]) - write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); + write_register (regnum, read_memory_integer (fsr.regs[regnum], + SPARC_INTREG_SIZE)); /* Handle all outs except stack pointer (o0-o5; o7). */ for (regnum = O0_REGNUM; regnum < O0_REGNUM + 6; ++regnum) if (fsr.regs[regnum]) - write_register (regnum, read_memory_integer (fsr.regs[regnum], 4)); + write_register (regnum, read_memory_integer (fsr.regs[regnum], + SPARC_INTREG_SIZE)); if (fsr.regs[O0_REGNUM + 7]) write_register (O0_REGNUM + 7, - read_memory_integer (fsr.regs[O0_REGNUM + 7], 4)); + read_memory_integer (fsr.regs[O0_REGNUM + 7], + SPARC_INTREG_SIZE)); write_register (SP_REGNUM, frame->frame); } @@ -845,7 +959,7 @@ sparc_pop_frame () char reg_temp[REGISTER_BYTES]; - read_memory (fsr.regs[I0_REGNUM], raw_buffer, 8 * 4); + read_memory (fsr.regs[I0_REGNUM], raw_buffer, 8 * SPARC_INTREG_SIZE); /* Get the ins and locals which we are about to restore. Just moving the stack pointer is all that is really needed, except @@ -853,32 +967,38 @@ sparc_pop_frame () locals from the registers array, so we need to muck with the registers array. */ sp = fsr.regs[SP_REGNUM]; - read_memory (sp, reg_temp, REGISTER_RAW_SIZE (L0_REGNUM) * 16); + read_memory (sp, reg_temp, SPARC_INTREG_SIZE * 16); /* Restore the out registers. Among other things this writes the new stack pointer. */ write_register_bytes (REGISTER_BYTE (O0_REGNUM), raw_buffer, - REGISTER_RAW_SIZE (O0_REGNUM) * 8); + SPARC_INTREG_SIZE * 8); write_register_bytes (REGISTER_BYTE (L0_REGNUM), reg_temp, - REGISTER_RAW_SIZE (L0_REGNUM) * 16); + SPARC_INTREG_SIZE * 16); } +#ifndef GDB_TARGET_IS_SPARC64 if (fsr.regs[PS_REGNUM]) write_register (PS_REGNUM, read_memory_integer (fsr.regs[PS_REGNUM], 4)); +#endif if (fsr.regs[Y_REGNUM]) - write_register (Y_REGNUM, read_memory_integer (fsr.regs[Y_REGNUM], 4)); + write_register (Y_REGNUM, read_memory_integer (fsr.regs[Y_REGNUM], REGISTER_RAW_SIZE (Y_REGNUM))); if (fsr.regs[PC_REGNUM]) { /* Explicitly specified PC (and maybe NPC) -- just restore them. */ - write_register (PC_REGNUM, read_memory_integer (fsr.regs[PC_REGNUM], 4)); + write_register (PC_REGNUM, read_memory_integer (fsr.regs[PC_REGNUM], + REGISTER_RAW_SIZE (PC_REGNUM))); if (fsr.regs[NPC_REGNUM]) write_register (NPC_REGNUM, - read_memory_integer (fsr.regs[NPC_REGNUM], 4)); + read_memory_integer (fsr.regs[NPC_REGNUM], + REGISTER_RAW_SIZE (NPC_REGNUM))); } else if (frame->flat) { if (frame->pc_addr) - pc = PC_ADJUST ((CORE_ADDR) read_memory_integer (frame->pc_addr, 4)); + pc = PC_ADJUST ((CORE_ADDR) + read_memory_integer (frame->pc_addr, + REGISTER_RAW_SIZE (PC_REGNUM))); else { /* I think this happens only in the innermost frame, if so then @@ -896,7 +1016,8 @@ sparc_pop_frame () else if (fsr.regs[I7_REGNUM]) { /* Return address in %i7 -- adjust it, then restore PC and NPC from it */ - pc = PC_ADJUST ((CORE_ADDR) read_memory_integer (fsr.regs[I7_REGNUM], 4)); + pc = PC_ADJUST ((CORE_ADDR) read_memory_integer (fsr.regs[I7_REGNUM], + SPARC_INTREG_SIZE)); write_register (PC_REGNUM, pc); write_register (NPC_REGNUM, pc + 4); } @@ -1003,9 +1124,9 @@ sunos4_skip_trampoline_code (pc) */ -/* Given a pointer to a general register set in /proc format (gregset_t *), - unpack the register contents and supply them as gdb's idea of the current - register values. */ +/* Given a pointer to a general register set in /proc format (gregset_t *), + unpack the register contents and supply them as gdb's idea of the current + register values. */ void supply_gregset (gregsetp) @@ -1034,7 +1155,6 @@ int regno; { int regi; register prgreg_t *regp = (prgreg_t *) gregsetp; - extern char registers[]; for (regi = 0 ; regi <= R_I7 ; regi++) { @@ -1086,6 +1206,7 @@ prfpregset_t *fpregsetp; (fpregset_t *), update the register specified by REGNO from gdb's idea of the current floating point register set. If REGNO is -1, update them all. */ +/* ??? This will probably need some changes for sparc64. */ void fill_fpregset (fpregsetp, regno) @@ -1095,9 +1216,10 @@ int regno; int regi; char *to; char *from; - extern char registers[]; - for (regi = FP0_REGNUM ; regi < FP0_REGNUM+32 ; regi++) + /* ??? The 32 should probably be NUM_SPARC_FPREGS, but again we're + waiting on what REGISTER_RAW_SIZE should be for fp regs. */ + for (regi = FP0_REGNUM ; regi < FP0_REGNUM + 32 ; regi++) { if ((regno == -1) || (regno == regi)) { @@ -1144,3 +1266,202 @@ get_longjmp_target (pc) return 1; } #endif /* GET_LONGJMP_TARGET */ + +#ifdef STATIC_TRANSFORM_NAME +/* SunPRO (3.0 at least), encodes the static variables. This is not + related to C++ mangling, it is done for C too. */ + +char * +solaris_static_transform_name (name) + char *name; +{ + char *p; + if (name[0] == '$') + { + /* For file-local statics there will be a dollar sign, a bunch + of junk (the contents of which match a string given in the + N_OPT), a period and the name. For function-local statics + there will be a bunch of junk (which seems to change the + second character from 'A' to 'B'), a period, the name of the + function, and the name. So just skip everything before the + last period. */ + p = strrchr (name, '.'); + if (p != NULL) + name = p + 1; + } + return name; +} +#endif /* STATIC_TRANSFORM_NAME */ + +#ifdef GDB_TARGET_IS_SPARC64 + +CORE_ADDR +sparc64_extract_struct_value_address (regbuf) + char regbuf[REGISTER_BYTES]; +{ + CORE_ADDR addr; + + /* FIXME: We assume a non-leaf function. */ + addr = read_register (I0_REGNUM); + return addr; +} + +/* Utilities for printing registers. + Page numbers refer to the SPARC Architecture Manual. */ + +static void +dump_ccreg (reg, val) + char *reg; + int val; +{ + /* page 41 */ + printf_unfiltered ("%s:%s,%s,%s,%s", reg, + val & 8 ? "N" : "NN", + val & 4 ? "Z" : "NZ", + val & 2 ? "O" : "NO", + val & 1 ? "C" : "NC" + ); +} + +static char * +decode_asi (val) + int val; +{ + /* page 72 */ + switch (val) + { + case 4 : return "ASI_NUCLEUS"; + case 0x0c : return "ASI_NUCLEUS_LITTLE"; + case 0x10 : return "ASI_AS_IF_USER_PRIMARY"; + case 0x11 : return "ASI_AS_IF_USER_SECONDARY"; + case 0x18 : return "ASI_AS_IF_USER_PRIMARY_LITTLE"; + case 0x19 : return "ASI_AS_IF_USER_SECONDARY_LITTLE"; + case 0x80 : return "ASI_PRIMARY"; + case 0x81 : return "ASI_SECONDARY"; + case 0x82 : return "ASI_PRIMARY_NOFAULT"; + case 0x83 : return "ASI_SECONDARY_NOFAULT"; + case 0x88 : return "ASI_PRIMARY_LITTLE"; + case 0x89 : return "ASI_SECONDARY_LITTLE"; + case 0x8a : return "ASI_PRIMARY_NOFAULT_LITTLE"; + case 0x8b : return "ASI_SECONDARY_NOFAULT_LITTLE"; + default : return NULL; + } +} + +/* PRINT_REGISTER_HOOK routine. + Pretty print various registers. */ +/* FIXME: Would be nice if this did some fancy things for 32 bit sparc. */ + +void +sparc_print_register_hook (regno) + int regno; +{ + unsigned LONGEST val; + + if (((unsigned) (regno) - FP0_REGNUM < FP_MAX_REGNUM - FP0_REGNUM) + && ((regno) & 1) == 0) + { + char doublereg[8]; /* two float regs */ + if (!read_relative_register_raw_bytes ((regno), doublereg)) + { + printf_unfiltered("\t"); + print_floating (doublereg, builtin_type_double, gdb_stdout); + } + return; + } + + /* FIXME: Some of these are priviledged registers. + Not sure how they should be handled. */ + +#define BITS(n, mask) ((int) (((val) >> (n)) & (mask))) + + val = read_register (regno); + + /* pages 40 - 60 */ + switch (regno) + { + case CCR_REGNUM : + printf_unfiltered("\t"); + dump_ccreg ("xcc", val >> 4); + printf_unfiltered(", "); + dump_ccreg ("icc", val & 15); + break; + case FPRS_REGNUM : + printf ("\tfef:%d, du:%d, dl:%d", + BITS (2, 1), BITS (1, 1), BITS (0, 1)); + break; + case FSR_REGNUM : + { + static char *fcc[4] = { "=", "<", ">", "?" }; + static char *rd[4] = { "N", "0", "+", "-" }; + /* Long, yes, but I'd rather leave it as is and use a wide screen. */ + printf ("\t0:%s, 1:%s, 2:%s, 3:%s, rd:%s, tem:%d, ns:%d, ver:%d, ftt:%d, qne:%d, aexc:%d, cexc:%d", + fcc[BITS (10, 3)], fcc[BITS (32, 3)], + fcc[BITS (34, 3)], fcc[BITS (36, 3)], + rd[BITS (30, 3)], BITS (23, 31), BITS (22, 1), BITS (17, 7), + BITS (14, 7), BITS (13, 1), BITS (5, 31), BITS (0, 31)); + break; + } + case ASI_REGNUM : + { + char *asi = decode_asi (val); + if (asi != NULL) + printf ("\t%s", asi); + break; + } + case VER_REGNUM : + printf ("\tmanuf:%d, impl:%d, mask:%d, maxtl:%d, maxwin:%d", + BITS (48, 0xffff), BITS (32, 0xffff), + BITS (24, 0xff), BITS (8, 0xff), BITS (0, 31)); + break; + case PSTATE_REGNUM : + { + static char *mm[4] = { "tso", "pso", "rso", "?" }; + printf ("\tcle:%d, tle:%d, mm:%s, red:%d, pef:%d, am:%d, priv:%d, ie:%d, ag:%d", + BITS (9, 1), BITS (8, 1), mm[BITS (6, 3)], BITS (5, 1), + BITS (4, 1), BITS (3, 1), BITS (2, 1), BITS (1, 1), + BITS (0, 1)); + break; + } + case TSTATE_REGNUM : + /* FIXME: print all 4? */ + break; + case TT_REGNUM : + /* FIXME: print all 4? */ + break; + case TPC_REGNUM : + /* FIXME: print all 4? */ + break; + case TNPC_REGNUM : + /* FIXME: print all 4? */ + break; + case WSTATE_REGNUM : + printf ("\tother:%d, normal:%d", BITS (3, 7), BITS (0, 7)); + break; + case CWP_REGNUM : + printf ("\t%d", BITS (0, 31)); + break; + case CANSAVE_REGNUM : + printf ("\t%-2d before spill", BITS (0, 31)); + break; + case CANRESTORE_REGNUM : + printf ("\t%-2d before fill", BITS (0, 31)); + break; + case CLEANWIN_REGNUM : + printf ("\t%-2d before clean", BITS (0, 31)); + break; + case OTHERWIN_REGNUM : + printf ("\t%d", BITS (0, 31)); + break; + } + +#undef BITS +} + +#endif + +void +_initialize_sparc_tdep () +{ + tm_print_insn = print_insn_sparc; +}