1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000 |
- /* Target-dependent code for the Texas Instruments MSP430 for GDB, the
- GNU debugger.
- Copyright (C) 2012-2022 Free Software Foundation, Inc.
- Contributed by Red Hat, Inc.
- This file is part of GDB.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
- #include "defs.h"
- #include "arch-utils.h"
- #include "prologue-value.h"
- #include "target.h"
- #include "regcache.h"
- #include "dis-asm.h"
- #include "gdbtypes.h"
- #include "frame.h"
- #include "frame-unwind.h"
- #include "frame-base.h"
- #include "value.h"
- #include "gdbcore.h"
- #include "dwarf2/frame.h"
- #include "reggroups.h"
- #include "gdbarch.h"
- #include "elf/msp430.h"
- #include "opcode/msp430-decode.h"
- #include "elf-bfd.h"
- /* Register Numbers. */
- enum
- {
- MSP430_PC_RAW_REGNUM,
- MSP430_SP_RAW_REGNUM,
- MSP430_SR_RAW_REGNUM,
- MSP430_CG_RAW_REGNUM,
- MSP430_R4_RAW_REGNUM,
- MSP430_R5_RAW_REGNUM,
- MSP430_R6_RAW_REGNUM,
- MSP430_R7_RAW_REGNUM,
- MSP430_R8_RAW_REGNUM,
- MSP430_R9_RAW_REGNUM,
- MSP430_R10_RAW_REGNUM,
- MSP430_R11_RAW_REGNUM,
- MSP430_R12_RAW_REGNUM,
- MSP430_R13_RAW_REGNUM,
- MSP430_R14_RAW_REGNUM,
- MSP430_R15_RAW_REGNUM,
- MSP430_NUM_REGS,
- MSP430_PC_REGNUM = MSP430_NUM_REGS,
- MSP430_SP_REGNUM,
- MSP430_SR_REGNUM,
- MSP430_CG_REGNUM,
- MSP430_R4_REGNUM,
- MSP430_R5_REGNUM,
- MSP430_R6_REGNUM,
- MSP430_R7_REGNUM,
- MSP430_R8_REGNUM,
- MSP430_R9_REGNUM,
- MSP430_R10_REGNUM,
- MSP430_R11_REGNUM,
- MSP430_R12_REGNUM,
- MSP430_R13_REGNUM,
- MSP430_R14_REGNUM,
- MSP430_R15_REGNUM,
- MSP430_NUM_TOTAL_REGS,
- MSP430_NUM_PSEUDO_REGS = MSP430_NUM_TOTAL_REGS - MSP430_NUM_REGS
- };
- enum
- {
- /* TI MSP430 Architecture. */
- MSP_ISA_MSP430,
- /* TI MSP430X Architecture. */
- MSP_ISA_MSP430X
- };
- enum
- {
- /* The small code model limits code addresses to 16 bits. */
- MSP_SMALL_CODE_MODEL,
- /* The large code model uses 20 bit addresses for function
- pointers. These are stored in memory using four bytes (32 bits). */
- MSP_LARGE_CODE_MODEL
- };
- /* Architecture specific data. */
- struct msp430_gdbarch_tdep : gdbarch_tdep
- {
- /* The ELF header flags specify the multilib used. */
- int elf_flags = 0;
- /* One of MSP_ISA_MSP430 or MSP_ISA_MSP430X. */
- int isa = 0;
- /* One of MSP_SMALL_CODE_MODEL or MSP_LARGE_CODE_MODEL. If, at
- some point, we support different data models too, we'll probably
- structure things so that we can combine values using logical
- "or". */
- int code_model = 0;
- };
- /* This structure holds the results of a prologue analysis. */
- struct msp430_prologue
- {
- /* The offset from the frame base to the stack pointer --- always
- zero or negative.
- Calling this a "size" is a bit misleading, but given that the
- stack grows downwards, using offsets for everything keeps one
- from going completely sign-crazy: you never change anything's
- sign for an ADD instruction; always change the second operand's
- sign for a SUB instruction; and everything takes care of
- itself. */
- int frame_size;
- /* Non-zero if this function has initialized the frame pointer from
- the stack pointer, zero otherwise. */
- int has_frame_ptr;
- /* If has_frame_ptr is non-zero, this is the offset from the frame
- base to where the frame pointer points. This is always zero or
- negative. */
- int frame_ptr_offset;
- /* The address of the first instruction at which the frame has been
- set up and the arguments are where the debug info says they are
- --- as best as we can tell. */
- CORE_ADDR prologue_end;
- /* reg_offset[R] is the offset from the CFA at which register R is
- saved, or 1 if register R has not been saved. (Real values are
- always zero or negative.) */
- int reg_offset[MSP430_NUM_TOTAL_REGS];
- };
- /* Implement the "register_type" gdbarch method. */
- static struct type *
- msp430_register_type (struct gdbarch *gdbarch, int reg_nr)
- {
- if (reg_nr < MSP430_NUM_REGS)
- return builtin_type (gdbarch)->builtin_uint32;
- else if (reg_nr == MSP430_PC_REGNUM)
- return builtin_type (gdbarch)->builtin_func_ptr;
- else
- return builtin_type (gdbarch)->builtin_uint16;
- }
- /* Implement another version of the "register_type" gdbarch method
- for msp430x. */
- static struct type *
- msp430x_register_type (struct gdbarch *gdbarch, int reg_nr)
- {
- if (reg_nr < MSP430_NUM_REGS)
- return builtin_type (gdbarch)->builtin_uint32;
- else if (reg_nr == MSP430_PC_REGNUM)
- return builtin_type (gdbarch)->builtin_func_ptr;
- else
- return builtin_type (gdbarch)->builtin_uint32;
- }
- /* Implement the "register_name" gdbarch method. */
- static const char *
- msp430_register_name (struct gdbarch *gdbarch, int regnr)
- {
- static const char *const reg_names[] = {
- /* Raw registers. */
- "", "", "", "", "", "", "", "",
- "", "", "", "", "", "", "", "",
- /* Pseudo registers. */
- "pc", "sp", "sr", "cg", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
- };
- return reg_names[regnr];
- }
- /* Implement the "register_reggroup_p" gdbarch method. */
- static int
- msp430_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
- const struct reggroup *group)
- {
- if (group == all_reggroup)
- return 1;
- /* All other registers are saved and restored. */
- if (group == save_reggroup || group == restore_reggroup)
- return (MSP430_NUM_REGS <= regnum && regnum < MSP430_NUM_TOTAL_REGS);
- return group == general_reggroup;
- }
- /* Implement the "pseudo_register_read" gdbarch method. */
- static enum register_status
- msp430_pseudo_register_read (struct gdbarch *gdbarch,
- readable_regcache *regcache,
- int regnum, gdb_byte *buffer)
- {
- if (MSP430_NUM_REGS <= regnum && regnum < MSP430_NUM_TOTAL_REGS)
- {
- enum register_status status;
- ULONGEST val;
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- int regsize = register_size (gdbarch, regnum);
- int raw_regnum = regnum - MSP430_NUM_REGS;
- status = regcache->raw_read (raw_regnum, &val);
- if (status == REG_VALID)
- store_unsigned_integer (buffer, regsize, byte_order, val);
- return status;
- }
- else
- gdb_assert_not_reached ("invalid pseudo register number");
- }
- /* Implement the "pseudo_register_write" gdbarch method. */
- static void
- msp430_pseudo_register_write (struct gdbarch *gdbarch,
- struct regcache *regcache,
- int regnum, const gdb_byte *buffer)
- {
- if (MSP430_NUM_REGS <= regnum && regnum < MSP430_NUM_TOTAL_REGS)
- {
- ULONGEST val;
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- int regsize = register_size (gdbarch, regnum);
- int raw_regnum = regnum - MSP430_NUM_REGS;
- val = extract_unsigned_integer (buffer, regsize, byte_order);
- regcache_raw_write_unsigned (regcache, raw_regnum, val);
- }
- else
- gdb_assert_not_reached ("invalid pseudo register number");
- }
- /* Implement the `register_sim_regno' gdbarch method. */
- static int
- msp430_register_sim_regno (struct gdbarch *gdbarch, int regnum)
- {
- gdb_assert (regnum < MSP430_NUM_REGS);
- /* So long as regnum is in [0, RL78_NUM_REGS), it's valid. We
- just want to override the default here which disallows register
- numbers which have no names. */
- return regnum;
- }
- constexpr gdb_byte msp430_break_insn[] = { 0x43, 0x43 };
- typedef BP_MANIPULATION (msp430_break_insn) msp430_breakpoint;
- /* Define a "handle" struct for fetching the next opcode. */
- struct msp430_get_opcode_byte_handle
- {
- CORE_ADDR pc;
- };
- /* Fetch a byte on behalf of the opcode decoder. HANDLE contains
- the memory address of the next byte to fetch. If successful,
- the address in the handle is updated and the byte fetched is
- returned as the value of the function. If not successful, -1
- is returned. */
- static int
- msp430_get_opcode_byte (void *handle)
- {
- struct msp430_get_opcode_byte_handle *opcdata
- = (struct msp430_get_opcode_byte_handle *) handle;
- int status;
- gdb_byte byte;
- status = target_read_memory (opcdata->pc, &byte, 1);
- if (status == 0)
- {
- opcdata->pc += 1;
- return byte;
- }
- else
- return -1;
- }
- /* Function for finding saved registers in a 'struct pv_area'; this
- function is passed to pv_area::scan.
- If VALUE is a saved register, ADDR says it was saved at a constant
- offset from the frame base, and SIZE indicates that the whole
- register was saved, record its offset. */
- static void
- check_for_saved (void *result_untyped, pv_t addr, CORE_ADDR size, pv_t value)
- {
- struct msp430_prologue *result = (struct msp430_prologue *) result_untyped;
- if (value.kind == pvk_register
- && value.k == 0
- && pv_is_register (addr, MSP430_SP_REGNUM)
- && size == register_size (target_gdbarch (), value.reg))
- result->reg_offset[value.reg] = addr.k;
- }
- /* Analyze a prologue starting at START_PC, going no further than
- LIMIT_PC. Fill in RESULT as appropriate. */
- static void
- msp430_analyze_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc,
- CORE_ADDR limit_pc, struct msp430_prologue *result)
- {
- CORE_ADDR pc, next_pc;
- int rn;
- pv_t reg[MSP430_NUM_TOTAL_REGS];
- CORE_ADDR after_last_frame_setup_insn = start_pc;
- msp430_gdbarch_tdep *tdep = (msp430_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- int code_model = tdep->code_model;
- int sz;
- memset (result, 0, sizeof (*result));
- for (rn = 0; rn < MSP430_NUM_TOTAL_REGS; rn++)
- {
- reg[rn] = pv_register (rn, 0);
- result->reg_offset[rn] = 1;
- }
- pv_area stack (MSP430_SP_REGNUM, gdbarch_addr_bit (gdbarch));
- /* The call instruction has saved the return address on the stack. */
- sz = code_model == MSP_LARGE_CODE_MODEL ? 4 : 2;
- reg[MSP430_SP_REGNUM] = pv_add_constant (reg[MSP430_SP_REGNUM], -sz);
- stack.store (reg[MSP430_SP_REGNUM], sz, reg[MSP430_PC_REGNUM]);
- pc = start_pc;
- while (pc < limit_pc)
- {
- int bytes_read;
- struct msp430_get_opcode_byte_handle opcode_handle;
- MSP430_Opcode_Decoded opc;
- opcode_handle.pc = pc;
- bytes_read = msp430_decode_opcode (pc, &opc, msp430_get_opcode_byte,
- &opcode_handle);
- next_pc = pc + bytes_read;
- if (opc.id == MSO_push && opc.op[0].type == MSP430_Operand_Register)
- {
- int rsrc = opc.op[0].reg;
- reg[MSP430_SP_REGNUM] = pv_add_constant (reg[MSP430_SP_REGNUM], -2);
- stack.store (reg[MSP430_SP_REGNUM], 2, reg[rsrc]);
- after_last_frame_setup_insn = next_pc;
- }
- else if (opc.id == MSO_push /* PUSHM */
- && opc.op[0].type == MSP430_Operand_None
- && opc.op[1].type == MSP430_Operand_Register)
- {
- int rsrc = opc.op[1].reg;
- int count = opc.repeats + 1;
- int size = opc.size == 16 ? 2 : 4;
- while (count > 0)
- {
- reg[MSP430_SP_REGNUM]
- = pv_add_constant (reg[MSP430_SP_REGNUM], -size);
- stack.store (reg[MSP430_SP_REGNUM], size, reg[rsrc]);
- rsrc--;
- count--;
- }
- after_last_frame_setup_insn = next_pc;
- }
- else if (opc.id == MSO_sub
- && opc.op[0].type == MSP430_Operand_Register
- && opc.op[0].reg == MSR_SP
- && opc.op[1].type == MSP430_Operand_Immediate)
- {
- int addend = opc.op[1].addend;
- reg[MSP430_SP_REGNUM] = pv_add_constant (reg[MSP430_SP_REGNUM],
- -addend);
- after_last_frame_setup_insn = next_pc;
- }
- else if (opc.id == MSO_mov
- && opc.op[0].type == MSP430_Operand_Immediate
- && 12 <= opc.op[0].reg && opc.op[0].reg <= 15)
- after_last_frame_setup_insn = next_pc;
- else
- {
- /* Terminate the prologue scan. */
- break;
- }
- pc = next_pc;
- }
- /* Is the frame size (offset, really) a known constant? */
- if (pv_is_register (reg[MSP430_SP_REGNUM], MSP430_SP_REGNUM))
- result->frame_size = reg[MSP430_SP_REGNUM].k;
- /* Record where all the registers were saved. */
- stack.scan (check_for_saved, result);
- result->prologue_end = after_last_frame_setup_insn;
- }
- /* Implement the "skip_prologue" gdbarch method. */
- static CORE_ADDR
- msp430_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
- {
- const char *name;
- CORE_ADDR func_addr, func_end;
- struct msp430_prologue p;
- /* Try to find the extent of the function that contains PC. */
- if (!find_pc_partial_function (pc, &name, &func_addr, &func_end))
- return pc;
- msp430_analyze_prologue (gdbarch, pc, func_end, &p);
- return p.prologue_end;
- }
- /* Given a frame described by THIS_FRAME, decode the prologue of its
- associated function if there is not cache entry as specified by
- THIS_PROLOGUE_CACHE. Save the decoded prologue in the cache and
- return that struct as the value of this function. */
- static struct msp430_prologue *
- msp430_analyze_frame_prologue (struct frame_info *this_frame,
- void **this_prologue_cache)
- {
- if (!*this_prologue_cache)
- {
- CORE_ADDR func_start, stop_addr;
- *this_prologue_cache = FRAME_OBSTACK_ZALLOC (struct msp430_prologue);
- func_start = get_frame_func (this_frame);
- stop_addr = get_frame_pc (this_frame);
- /* If we couldn't find any function containing the PC, then
- just initialize the prologue cache, but don't do anything. */
- if (!func_start)
- stop_addr = func_start;
- msp430_analyze_prologue (get_frame_arch (this_frame), func_start,
- stop_addr,
- (struct msp430_prologue *) *this_prologue_cache);
- }
- return (struct msp430_prologue *) *this_prologue_cache;
- }
- /* Given a frame and a prologue cache, return this frame's base. */
- static CORE_ADDR
- msp430_frame_base (struct frame_info *this_frame, void **this_prologue_cache)
- {
- struct msp430_prologue *p
- = msp430_analyze_frame_prologue (this_frame, this_prologue_cache);
- CORE_ADDR sp = get_frame_register_unsigned (this_frame, MSP430_SP_REGNUM);
- return sp - p->frame_size;
- }
- /* Implement the "frame_this_id" method for unwinding frames. */
- static void
- msp430_this_id (struct frame_info *this_frame,
- void **this_prologue_cache, struct frame_id *this_id)
- {
- *this_id = frame_id_build (msp430_frame_base (this_frame,
- this_prologue_cache),
- get_frame_func (this_frame));
- }
- /* Implement the "frame_prev_register" method for unwinding frames. */
- static struct value *
- msp430_prev_register (struct frame_info *this_frame,
- void **this_prologue_cache, int regnum)
- {
- struct msp430_prologue *p
- = msp430_analyze_frame_prologue (this_frame, this_prologue_cache);
- CORE_ADDR frame_base = msp430_frame_base (this_frame, this_prologue_cache);
- if (regnum == MSP430_SP_REGNUM)
- return frame_unwind_got_constant (this_frame, regnum, frame_base);
- /* If prologue analysis says we saved this register somewhere,
- return a description of the stack slot holding it. */
- else if (p->reg_offset[regnum] != 1)
- {
- struct value *rv = frame_unwind_got_memory (this_frame, regnum,
- frame_base +
- p->reg_offset[regnum]);
- if (regnum == MSP430_PC_REGNUM)
- {
- ULONGEST pc = value_as_long (rv);
- return frame_unwind_got_constant (this_frame, regnum, pc);
- }
- return rv;
- }
- /* Otherwise, presume we haven't changed the value of this
- register, and get it from the next frame. */
- else
- return frame_unwind_got_register (this_frame, regnum, regnum);
- }
- static const struct frame_unwind msp430_unwind = {
- "msp430 prologue",
- NORMAL_FRAME,
- default_frame_unwind_stop_reason,
- msp430_this_id,
- msp430_prev_register,
- NULL,
- default_frame_sniffer
- };
- /* Implement the "dwarf2_reg_to_regnum" gdbarch method. */
- static int
- msp430_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int reg)
- {
- if (reg >= 0 && reg < MSP430_NUM_REGS)
- return reg + MSP430_NUM_REGS;
- return -1;
- }
- /* Implement the "return_value" gdbarch method. */
- static enum return_value_convention
- msp430_return_value (struct gdbarch *gdbarch,
- struct value *function,
- struct type *valtype,
- struct regcache *regcache,
- gdb_byte *readbuf, const gdb_byte *writebuf)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- LONGEST valtype_len = TYPE_LENGTH (valtype);
- msp430_gdbarch_tdep *tdep = (msp430_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- int code_model = tdep->code_model;
- if (TYPE_LENGTH (valtype) > 8
- || valtype->code () == TYPE_CODE_STRUCT
- || valtype->code () == TYPE_CODE_UNION)
- return RETURN_VALUE_STRUCT_CONVENTION;
- if (readbuf)
- {
- ULONGEST u;
- int argreg = MSP430_R12_REGNUM;
- int offset = 0;
- while (valtype_len > 0)
- {
- int size = 2;
- if (code_model == MSP_LARGE_CODE_MODEL
- && valtype->code () == TYPE_CODE_PTR)
- {
- size = 4;
- }
- regcache_cooked_read_unsigned (regcache, argreg, &u);
- store_unsigned_integer (readbuf + offset, size, byte_order, u);
- valtype_len -= size;
- offset += size;
- argreg++;
- }
- }
- if (writebuf)
- {
- ULONGEST u;
- int argreg = MSP430_R12_REGNUM;
- int offset = 0;
- while (valtype_len > 0)
- {
- int size = 2;
- if (code_model == MSP_LARGE_CODE_MODEL
- && valtype->code () == TYPE_CODE_PTR)
- {
- size = 4;
- }
- u = extract_unsigned_integer (writebuf + offset, size, byte_order);
- regcache_cooked_write_unsigned (regcache, argreg, u);
- valtype_len -= size;
- offset += size;
- argreg++;
- }
- }
- return RETURN_VALUE_REGISTER_CONVENTION;
- }
- /* Implement the "frame_align" gdbarch method. */
- static CORE_ADDR
- msp430_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
- {
- return align_down (sp, 2);
- }
- /* Implement the "push_dummy_call" gdbarch method. */
- static CORE_ADDR
- msp430_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
- struct regcache *regcache, CORE_ADDR bp_addr,
- int nargs, struct value **args, CORE_ADDR sp,
- function_call_return_method return_method,
- CORE_ADDR struct_addr)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- int write_pass;
- int sp_off = 0;
- CORE_ADDR cfa;
- msp430_gdbarch_tdep *tdep = (msp430_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- int code_model = tdep->code_model;
- struct type *func_type = value_type (function);
- /* Dereference function pointer types. */
- while (func_type->code () == TYPE_CODE_PTR)
- func_type = TYPE_TARGET_TYPE (func_type);
- /* The end result had better be a function or a method. */
- gdb_assert (func_type->code () == TYPE_CODE_FUNC
- || func_type->code () == TYPE_CODE_METHOD);
- /* We make two passes; the first does the stack allocation,
- the second actually stores the arguments. */
- for (write_pass = 0; write_pass <= 1; write_pass++)
- {
- int i;
- int arg_reg = MSP430_R12_REGNUM;
- int args_on_stack = 0;
- if (write_pass)
- sp = align_down (sp - sp_off, 4);
- sp_off = 0;
- if (return_method == return_method_struct)
- {
- if (write_pass)
- regcache_cooked_write_unsigned (regcache, arg_reg, struct_addr);
- arg_reg++;
- }
- /* Push the arguments. */
- for (i = 0; i < nargs; i++)
- {
- struct value *arg = args[i];
- const gdb_byte *arg_bits = value_contents_all (arg).data ();
- struct type *arg_type = check_typedef (value_type (arg));
- ULONGEST arg_size = TYPE_LENGTH (arg_type);
- int offset;
- int current_arg_on_stack;
- gdb_byte struct_addr_buf[4];
- current_arg_on_stack = 0;
- if (arg_type->code () == TYPE_CODE_STRUCT
- || arg_type->code () == TYPE_CODE_UNION)
- {
- /* Aggregates of any size are passed by reference. */
- store_unsigned_integer (struct_addr_buf, 4, byte_order,
- value_address (arg));
- arg_bits = struct_addr_buf;
- arg_size = (code_model == MSP_LARGE_CODE_MODEL) ? 4 : 2;
- }
- else
- {
- /* Scalars bigger than 8 bytes such as complex doubles are passed
- on the stack. */
- if (arg_size > 8)
- current_arg_on_stack = 1;
- }
- for (offset = 0; offset < arg_size; offset += 2)
- {
- /* The condition below prevents 8 byte scalars from being split
- between registers and memory (stack). It also prevents other
- splits once the stack has been written to. */
- if (!current_arg_on_stack
- && (arg_reg
- + ((arg_size == 8 || args_on_stack)
- ? ((arg_size - offset) / 2 - 1)
- : 0) <= MSP430_R15_REGNUM))
- {
- int size = 2;
- if (code_model == MSP_LARGE_CODE_MODEL
- && (arg_type->code () == TYPE_CODE_PTR
- || TYPE_IS_REFERENCE (arg_type)
- || arg_type->code () == TYPE_CODE_STRUCT
- || arg_type->code () == TYPE_CODE_UNION))
- {
- /* When using the large memory model, pointer,
- reference, struct, and union arguments are
- passed using the entire register. (As noted
- earlier, aggregates are always passed by
- reference.) */
- if (offset != 0)
- continue;
- size = 4;
- }
- if (write_pass)
- regcache_cooked_write_unsigned (regcache, arg_reg,
- extract_unsigned_integer
- (arg_bits + offset, size,
- byte_order));
- arg_reg++;
- }
- else
- {
- if (write_pass)
- write_memory (sp + sp_off, arg_bits + offset, 2);
- sp_off += 2;
- args_on_stack = 1;
- current_arg_on_stack = 1;
- }
- }
- }
- }
- /* Keep track of the stack address prior to pushing the return address.
- This is the value that we'll return. */
- cfa = sp;
- /* Push the return address. */
- {
- int sz = tdep->code_model == MSP_SMALL_CODE_MODEL ? 2 : 4;
- sp = sp - sz;
- write_memory_unsigned_integer (sp, sz, byte_order, bp_addr);
- }
- /* Update the stack pointer. */
- regcache_cooked_write_unsigned (regcache, MSP430_SP_REGNUM, sp);
- return cfa;
- }
- /* In order to keep code size small, the compiler may create epilogue
- code through which more than one function epilogue is routed. I.e.
- the epilogue and return may just be a branch to some common piece of
- code which is responsible for tearing down the frame and performing
- the return. These epilog (label) names will have the common prefix
- defined here. */
- static const char msp430_epilog_name_prefix[] = "__mspabi_func_epilog_";
- /* Implement the "in_return_stub" gdbarch method. */
- static int
- msp430_in_return_stub (struct gdbarch *gdbarch, CORE_ADDR pc,
- const char *name)
- {
- return (name != NULL
- && startswith (name, msp430_epilog_name_prefix));
- }
- /* Implement the "skip_trampoline_code" gdbarch method. */
- static CORE_ADDR
- msp430_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
- {
- struct bound_minimal_symbol bms;
- const char *stub_name;
- struct gdbarch *gdbarch = get_frame_arch (frame);
- bms = lookup_minimal_symbol_by_pc (pc);
- if (!bms.minsym)
- return pc;
- stub_name = bms.minsym->linkage_name ();
- msp430_gdbarch_tdep *tdep = (msp430_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- if (tdep->code_model == MSP_SMALL_CODE_MODEL
- && msp430_in_return_stub (gdbarch, pc, stub_name))
- {
- CORE_ADDR sp = get_frame_register_unsigned (frame, MSP430_SP_REGNUM);
- return read_memory_integer
- (sp + 2 * (stub_name[strlen (msp430_epilog_name_prefix)] - '0'),
- 2, gdbarch_byte_order (gdbarch));
- }
- return pc;
- }
- /* Allocate and initialize a gdbarch object. */
- static struct gdbarch *
- msp430_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
- {
- struct gdbarch *gdbarch;
- int elf_flags, isa, code_model;
- /* Extract the elf_flags if available. */
- if (info.abfd != NULL
- && bfd_get_flavour (info.abfd) == bfd_target_elf_flavour)
- elf_flags = elf_elfheader (info.abfd)->e_flags;
- else
- elf_flags = 0;
- if (info.abfd != NULL)
- switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_PROC,
- OFBA_MSPABI_Tag_ISA))
- {
- case 1:
- isa = MSP_ISA_MSP430;
- code_model = MSP_SMALL_CODE_MODEL;
- break;
- case 2:
- isa = MSP_ISA_MSP430X;
- switch (bfd_elf_get_obj_attr_int (info.abfd, OBJ_ATTR_PROC,
- OFBA_MSPABI_Tag_Code_Model))
- {
- case 1:
- code_model = MSP_SMALL_CODE_MODEL;
- break;
- case 2:
- code_model = MSP_LARGE_CODE_MODEL;
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("Unknown msp430x code memory model"));
- break;
- }
- break;
- case 0:
- /* This can happen when loading a previously dumped data structure.
- Use the ISA and code model from the current architecture, provided
- it's compatible. */
- {
- struct gdbarch *ca = get_current_arch ();
- if (ca && gdbarch_bfd_arch_info (ca)->arch == bfd_arch_msp430)
- {
- msp430_gdbarch_tdep *ca_tdep
- = (msp430_gdbarch_tdep *) gdbarch_tdep (ca);
- elf_flags = ca_tdep->elf_flags;
- isa = ca_tdep->isa;
- code_model = ca_tdep->code_model;
- break;
- }
- }
- /* Fall through. */
- default:
- error (_("Unknown msp430 isa"));
- break;
- }
- else
- {
- isa = MSP_ISA_MSP430;
- code_model = MSP_SMALL_CODE_MODEL;
- }
- /* Try to find the architecture in the list of already defined
- architectures. */
- for (arches = gdbarch_list_lookup_by_info (arches, &info);
- arches != NULL;
- arches = gdbarch_list_lookup_by_info (arches->next, &info))
- {
- msp430_gdbarch_tdep *candidate_tdep
- = (msp430_gdbarch_tdep *) gdbarch_tdep (arches->gdbarch);
- if (candidate_tdep->elf_flags != elf_flags
- || candidate_tdep->isa != isa
- || candidate_tdep->code_model != code_model)
- continue;
- return arches->gdbarch;
- }
- /* None found, create a new architecture from the information
- provided. */
- msp430_gdbarch_tdep *tdep = new msp430_gdbarch_tdep;
- gdbarch = gdbarch_alloc (&info, tdep);
- tdep->elf_flags = elf_flags;
- tdep->isa = isa;
- tdep->code_model = code_model;
- /* Registers. */
- set_gdbarch_num_regs (gdbarch, MSP430_NUM_REGS);
- set_gdbarch_num_pseudo_regs (gdbarch, MSP430_NUM_PSEUDO_REGS);
- set_gdbarch_register_name (gdbarch, msp430_register_name);
- if (isa == MSP_ISA_MSP430)
- set_gdbarch_register_type (gdbarch, msp430_register_type);
- else
- set_gdbarch_register_type (gdbarch, msp430x_register_type);
- set_gdbarch_pc_regnum (gdbarch, MSP430_PC_REGNUM);
- set_gdbarch_sp_regnum (gdbarch, MSP430_SP_REGNUM);
- set_gdbarch_register_reggroup_p (gdbarch, msp430_register_reggroup_p);
- set_gdbarch_pseudo_register_read (gdbarch, msp430_pseudo_register_read);
- set_gdbarch_pseudo_register_write (gdbarch, msp430_pseudo_register_write);
- set_gdbarch_dwarf2_reg_to_regnum (gdbarch, msp430_dwarf2_reg_to_regnum);
- set_gdbarch_register_sim_regno (gdbarch, msp430_register_sim_regno);
- /* Data types. */
- set_gdbarch_char_signed (gdbarch, 0);
- set_gdbarch_short_bit (gdbarch, 16);
- set_gdbarch_int_bit (gdbarch, 16);
- set_gdbarch_long_bit (gdbarch, 32);
- set_gdbarch_long_long_bit (gdbarch, 64);
- if (code_model == MSP_SMALL_CODE_MODEL)
- {
- set_gdbarch_ptr_bit (gdbarch, 16);
- set_gdbarch_addr_bit (gdbarch, 16);
- }
- else /* MSP_LARGE_CODE_MODEL */
- {
- set_gdbarch_ptr_bit (gdbarch, 32);
- set_gdbarch_addr_bit (gdbarch, 32);
- }
- set_gdbarch_dwarf2_addr_size (gdbarch, 4);
- set_gdbarch_float_bit (gdbarch, 32);
- set_gdbarch_float_format (gdbarch, floatformats_ieee_single);
- set_gdbarch_double_bit (gdbarch, 64);
- set_gdbarch_long_double_bit (gdbarch, 64);
- set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
- set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
- /* Breakpoints. */
- set_gdbarch_breakpoint_kind_from_pc (gdbarch,
- msp430_breakpoint::kind_from_pc);
- set_gdbarch_sw_breakpoint_from_kind (gdbarch,
- msp430_breakpoint::bp_from_kind);
- set_gdbarch_decr_pc_after_break (gdbarch, 1);
- /* Frames, prologues, etc. */
- set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
- set_gdbarch_skip_prologue (gdbarch, msp430_skip_prologue);
- set_gdbarch_frame_align (gdbarch, msp430_frame_align);
- dwarf2_append_unwinders (gdbarch);
- frame_unwind_append_unwinder (gdbarch, &msp430_unwind);
- /* Dummy frames, return values. */
- set_gdbarch_push_dummy_call (gdbarch, msp430_push_dummy_call);
- set_gdbarch_return_value (gdbarch, msp430_return_value);
- /* Trampolines. */
- set_gdbarch_in_solib_return_trampoline (gdbarch, msp430_in_return_stub);
- set_gdbarch_skip_trampoline_code (gdbarch, msp430_skip_trampoline_code);
- /* Virtual tables. */
- set_gdbarch_vbit_in_delta (gdbarch, 0);
- return gdbarch;
- }
- /* Register the initialization routine. */
- void _initialize_msp430_tdep ();
- void
- _initialize_msp430_tdep ()
- {
- register_gdbarch_init (bfd_arch_msp430, msp430_gdbarch_init);
- }
|