#include "defs.h"
#include "value.h"
#include "inferior.h"
#include "symfile.h"
#include "arch-utils.h"
#include "regcache.h"
#include "gdbcore.h"
#include "objfiles.h"
#include "gdbcmd.h"
#include "gdb_assert.h"
#include "dis-asm.h"
struct frame_extra_info
{
CORE_ADDR from_pc;
};
enum
{
h8300_reg_size = 2,
h8300h_reg_size = 4,
h8300_max_reg_size = 4,
};
static int is_h8300hmode (struct gdbarch *gdbarch);
static int is_h8300smode (struct gdbarch *gdbarch);
static int is_h8300sxmode (struct gdbarch *gdbarch);
static int is_h8300_normal_mode (struct gdbarch *gdbarch);
#define BINWORD (is_h8300hmode (current_gdbarch) && \
!is_h8300_normal_mode (current_gdbarch) ? h8300h_reg_size : h8300_reg_size)
enum gdb_regnum
{
E_R0_REGNUM, E_ER0_REGNUM = E_R0_REGNUM, E_ARG0_REGNUM = E_R0_REGNUM,
E_RET0_REGNUM = E_R0_REGNUM,
E_R1_REGNUM, E_ER1_REGNUM = E_R1_REGNUM, E_RET1_REGNUM = E_R1_REGNUM,
E_R2_REGNUM, E_ER2_REGNUM = E_R2_REGNUM, E_ARGLAST_REGNUM = E_R2_REGNUM,
E_R3_REGNUM, E_ER3_REGNUM = E_R3_REGNUM,
E_R4_REGNUM, E_ER4_REGNUM = E_R4_REGNUM,
E_R5_REGNUM, E_ER5_REGNUM = E_R5_REGNUM,
E_R6_REGNUM, E_ER6_REGNUM = E_R6_REGNUM, E_FP_REGNUM = E_R6_REGNUM,
E_SP_REGNUM,
E_CCR_REGNUM,
E_PC_REGNUM,
E_CYCLES_REGNUM,
E_TICK_REGNUM, E_EXR_REGNUM = E_TICK_REGNUM,
E_INST_REGNUM, E_TICKS_REGNUM = E_INST_REGNUM,
E_INSTS_REGNUM,
E_MACH_REGNUM,
E_MACL_REGNUM,
E_SBR_REGNUM,
E_VBR_REGNUM
};
#define E_PSEUDO_CCR_REGNUM (NUM_REGS)
#define E_PSEUDO_EXR_REGNUM (NUM_REGS+1)
#define UNSIGNED_SHORT(X) ((X) & 0xffff)
#define IS_PUSH(x) ((x & 0xfff0)==0x6df0)
#define IS_PUSH_FP(x) (x == 0x6df6)
#define IS_MOVE_FP(x) (x == 0x0d76 || x == 0x0ff6)
#define IS_MOV_SP_FP(x) (x == 0x0d76 || x == 0x0ff6)
#define IS_SUB2_SP(x) (x==0x1b87)
#define IS_SUB4_SP(x) (x==0x1b97)
#define IS_SUBL_SP(x) (x==0x7a37)
#define IS_MOVK_R5(x) (x==0x7905)
#define IS_SUB_R5SP(x) (x==0x1957)
static int
h8300_is_argument_spill (CORE_ADDR pc)
{
int w = read_memory_unsigned_integer (pc, 2);
if (((w & 0xff88) == 0x0c88
|| (w & 0xff88) == 0x0d00
|| (w & 0xff88) == 0x0f80)
&& (w & 0x70) <= 0x20
&& (w & 0x7) >= 0x3 && (w & 0x7) <= 0x5)
return 2;
if ((w & 0xfff0) == 0x6ee0
&& 8 <= (w & 0xf) && (w & 0xf) <= 10)
{
int w2 = read_memory_integer (pc + 2, 2);
if (w2 < 0)
return 4;
}
else if (w == 0x7860)
{
int w2 = read_memory_integer (pc + 2, 2);
if ((w2 & 0xfff0) == 0x6aa0)
{
LONGEST disp = read_memory_integer (pc + 4, 4);
if (disp < 0 && disp > 0xffffff)
return 8;
}
}
else if ((w & 0xfff0) == 0x6fe0
&& (w & 0xf) <= 2)
{
int w2 = read_memory_integer (pc + 2, 2);
if (w2 < 0)
return 4;
}
else if (w == 0x78e0)
{
int w2 = read_memory_integer (pc + 2, 2);
if ((w2 & 0xfff0) == 0x6ba0)
{
LONGEST disp = read_memory_integer (pc + 4, 4);
if (disp < 0 && disp > 0xffffff)
return 8;
}
}
else if (w == 0x0100)
{
int w2 = read_memory_integer (pc + 2, 2);
if ((w2 & 0xfff0) == 0x6fe0
&& (w2 & 0xf) <= 2)
{
int w3 = read_memory_integer (pc + 4, 2);
if (w3 < 0)
return 6;
}
else if (w2 == 0x78e0)
{
int w3 = read_memory_integer (pc + 4, 2);
if ((w3 & 0xfff0) == 0x6ba0)
{
LONGEST disp = read_memory_integer (pc + 6, 4);
if (disp < 0 && disp > 0xffffff)
return 10;
}
}
}
return 0;
}
static CORE_ADDR
h8300_skip_prologue (CORE_ADDR start_pc)
{
short int w;
int adjust = 0;
while (1)
{
w = read_memory_unsigned_integer (start_pc, 2);
if (w == 0x0100 || w == 0x0110 || w == 0x0120 || w == 0x0130)
{
w = read_memory_unsigned_integer (start_pc + 2, 2);
adjust = 2;
}
if (IS_PUSH (w))
{
start_pc += 2 + adjust;
w = read_memory_unsigned_integer (start_pc, 2);
continue;
}
adjust = 0;
break;
}
w = read_memory_unsigned_integer (start_pc, 2);
if (w == 0x0100)
{
w = read_memory_unsigned_integer (start_pc + 2, 2);
adjust += 2;
}
if (IS_MOVE_FP (w))
{
start_pc += 2 + adjust;
w = read_memory_unsigned_integer (start_pc, 2);
}
if (IS_MOVK_R5 (w))
{
start_pc += 2;
w = read_memory_unsigned_integer (start_pc, 2);
}
if (IS_SUB_R5SP (w))
{
start_pc += 2 + adjust;
w = read_memory_unsigned_integer (start_pc, 2);
}
while (IS_SUB2_SP (w) || IS_SUB4_SP (w))
{
start_pc += 2 + adjust;
w = read_memory_unsigned_integer (start_pc, 2);
}
if (IS_SUBL_SP (w))
start_pc += 6 + adjust;
w = read_memory_unsigned_integer (start_pc, 2);
if (w == 0x0110 || w == 0x0120 || w == 0x0130)
{
w = read_memory_unsigned_integer (start_pc + 2, 2);
if (IS_PUSH (w) && (w & 0xf) >= 0x3 && (w & 0xf) <= 0x5)
start_pc += 4;
}
for (;;)
{
int spill_size = h8300_is_argument_spill (start_pc);
if (spill_size == 0)
break;
start_pc += spill_size;
}
return start_pc;
}
static CORE_ADDR
h8300_next_prologue_insn (CORE_ADDR addr,
CORE_ADDR lim,
unsigned short* pword1)
{
char buf[2];
if (addr < lim + 8)
{
read_memory (addr, buf, 2);
*pword1 = extract_signed_integer (buf, 2);
return addr + 2;
}
return 0;
}
static CORE_ADDR
h8300_examine_prologue (CORE_ADDR ip, CORE_ADDR limit,
CORE_ADDR after_prolog_fp, CORE_ADDR *fsr,
struct frame_info *fi)
{
CORE_ADDR next_ip;
int r;
int have_fp = 0;
unsigned short insn_word;
unsigned int reg_save_depth = BINWORD;
unsigned int auto_depth = 0;
char in_frame[11];
int adjust = 0;
memset (in_frame, 1, 11);
for (r = 0; r < 8; r++)
{
fsr[r] = 0;
}
if (after_prolog_fp == 0)
{
after_prolog_fp = read_register (E_SP_REGNUM);
}
if (ip == 0 || ip & (is_h8300hmode (current_gdbarch) &&
!is_h8300_normal_mode (current_gdbarch) ? ~0xffffff : ~0xffff))
return 0;
next_ip = h8300_next_prologue_insn (ip, limit, &insn_word);
if (insn_word == 0x0100)
{
insn_word = read_memory_unsigned_integer (ip + 2, 2);
adjust = 2;
}
fsr[E_FP_REGNUM] = after_prolog_fp;
while (next_ip && IS_PUSH_FP (insn_word))
{
ip = next_ip + adjust;
in_frame[insn_word & 0x7] = reg_save_depth;
next_ip = h8300_next_prologue_insn (ip, limit, &insn_word);
reg_save_depth += 2 + adjust;
}
if (next_ip && IS_MOV_SP_FP (insn_word))
{
ip = next_ip;
next_ip = h8300_next_prologue_insn (ip, limit, &insn_word);
have_fp = 1;
}
if (next_ip && (IS_SUB2_SP (insn_word) || IS_SUB4_SP (insn_word)))
{
while (next_ip && (IS_SUB2_SP (insn_word) || IS_SUB4_SP (insn_word)))
{
auto_depth += IS_SUB2_SP (insn_word) ? 2 : 4;
ip = next_ip;
next_ip = h8300_next_prologue_insn (ip, limit, &insn_word);
}
}
else
{
if (next_ip && IS_MOVK_R5 (insn_word))
{
ip = next_ip;
next_ip = h8300_next_prologue_insn (ip, limit, &insn_word);
auto_depth += insn_word;
next_ip = h8300_next_prologue_insn (next_ip, limit, &insn_word);
auto_depth += insn_word;
}
if (next_ip && IS_SUBL_SP (insn_word))
{
ip = next_ip;
auto_depth += read_memory_unsigned_integer (ip, 4);
ip += 4;
next_ip = h8300_next_prologue_insn (ip, limit, &insn_word);
}
}
while (1)
{
adjust = 0;
if (!next_ip)
break;
if (insn_word == 0x0100)
{
ip = next_ip;
next_ip = h8300_next_prologue_insn (ip, limit, &insn_word);
adjust = 2;
}
if (IS_PUSH (insn_word))
{
auto_depth += 2 + adjust;
fsr[insn_word & 0x7] = after_prolog_fp - auto_depth;
ip = next_ip;
next_ip = h8300_next_prologue_insn (ip, limit, &insn_word);
continue;
}
if (insn_word == 0x0110 || insn_word == 0x0120 || insn_word == 0x0130)
{
int count = ((insn_word >> 4) & 0xf) + 1;
int start, i;
ip = next_ip;
next_ip = h8300_next_prologue_insn (ip, limit, &insn_word);
start = insn_word & 0x7;
for (i = start; i < start + count; i++)
{
auto_depth += 4;
fsr[i] = after_prolog_fp - auto_depth;
}
}
break;
}
get_frame_extra_info (fi)->from_pc =
read_memory_unsigned_integer (after_prolog_fp + BINWORD, BINWORD);
in_frame[E_PC_REGNUM] = 0;
if (have_fp)
fsr[E_SP_REGNUM] = read_memory_unsigned_integer (fsr[E_FP_REGNUM],
BINWORD);
else
fsr[E_SP_REGNUM] = after_prolog_fp + auto_depth;
return (ip);
}
static void
h8300_frame_init_saved_regs (struct frame_info *fi)
{
CORE_ADDR func_addr, func_end;
if (!deprecated_get_frame_saved_regs (fi))
{
frame_saved_regs_zalloc (fi);
if (find_pc_partial_function (get_frame_pc (fi), NULL,
&func_addr, &func_end))
{
struct symtab_and_line sal = find_pc_line (func_addr, 0);
CORE_ADDR limit = (sal.end && sal.end < get_frame_pc (fi))
? sal.end : get_frame_pc (fi);
h8300_examine_prologue (func_addr, limit, get_frame_base (fi),
deprecated_get_frame_saved_regs (fi), fi);
}
}
}
static CORE_ADDR
h8300_frame_chain (struct frame_info *thisframe)
{
if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (thisframe),
get_frame_base (thisframe),
get_frame_base (thisframe)))
{
get_frame_extra_info (thisframe)->from_pc =
deprecated_read_register_dummy (get_frame_pc (thisframe),
get_frame_base (thisframe),
E_PC_REGNUM);
return get_frame_base (thisframe);
}
return deprecated_get_frame_saved_regs (thisframe)[E_SP_REGNUM];
}
static CORE_ADDR
h8300_frame_saved_pc (struct frame_info *frame)
{
if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (frame),
get_frame_base (frame),
get_frame_base (frame)))
return deprecated_read_register_dummy (get_frame_pc (frame),
get_frame_base (frame),
E_PC_REGNUM);
else
return get_frame_extra_info (frame)->from_pc;
}
static void
h8300_init_extra_frame_info (int fromleaf, struct frame_info *fi)
{
if (!get_frame_extra_info (fi))
{
frame_extra_info_zalloc (fi, sizeof (struct frame_extra_info));
get_frame_extra_info (fi)->from_pc = 0;
if (!get_frame_pc (fi))
{
if (get_next_frame (fi))
deprecated_update_frame_pc_hack (fi, h8300_frame_saved_pc (get_next_frame (fi)));
}
h8300_frame_init_saved_regs (fi);
}
}
static CORE_ADDR
h8300_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 stack_alloc = 0, stack_offset = 0;
int wordsize = BINWORD;
int reg = E_ARG0_REGNUM;
int argument;
sp = align_down (sp, wordsize);
for (argument = 0; argument < nargs; argument++)
stack_alloc += align_up (TYPE_LENGTH (VALUE_TYPE (args[argument])),
wordsize);
sp -= stack_alloc;
if (struct_return)
regcache_cooked_write_unsigned (regcache, reg++, struct_addr);
for (argument = 0; argument < nargs; argument++)
{
struct type *type = VALUE_TYPE (args[argument]);
int len = TYPE_LENGTH (type);
char *contents = (char *) VALUE_CONTENTS (args[argument]);
int padded_len = align_up (len, wordsize);
char *padded = alloca (padded_len);
memset (padded, 0, padded_len);
memcpy (len < wordsize ? padded + padded_len - len : padded,
contents, len);
if (padded_len <= (E_ARGLAST_REGNUM - reg + 1) * wordsize)
{
if (len > wordsize && len % wordsize)
{
write_memory (sp + stack_offset, padded, padded_len);
stack_offset += padded_len;
reg += padded_len / wordsize;
}
else
{
int offset;
for (offset = 0; offset < padded_len; offset += wordsize)
{
ULONGEST word = extract_unsigned_integer (padded + offset,
wordsize);
regcache_cooked_write_unsigned (regcache, reg++, word);
}
}
}
else
{
write_memory (sp + stack_offset, padded, padded_len);
stack_offset += padded_len;
reg = E_ARGLAST_REGNUM + 1;
}
}
sp -= wordsize;
write_memory_unsigned_integer (sp, wordsize, bp_addr);
regcache_cooked_write_unsigned (regcache, E_SP_REGNUM, sp);
return sp;
}
static void
h8300_pop_frame (void)
{
unsigned regno;
struct frame_info *frame = get_current_frame ();
if (DEPRECATED_PC_IN_CALL_DUMMY (get_frame_pc (frame),
get_frame_base (frame),
get_frame_base (frame)))
{
generic_pop_dummy_frame ();
}
else
{
for (regno = 0; regno < 8; regno++)
{
if (deprecated_get_frame_saved_regs (frame)[regno] && regno != E_SP_REGNUM)
write_register (regno,
read_memory_integer
(deprecated_get_frame_saved_regs (frame)[regno], BINWORD));
else if (deprecated_get_frame_saved_regs (frame)[regno] && regno == E_SP_REGNUM)
write_register (regno, get_frame_base (frame) + 2 * BINWORD);
}
write_register (E_PC_REGNUM, get_frame_extra_info (frame)->from_pc);
}
flush_cached_frames ();
}
static void
h8300_extract_return_value (struct type *type, struct regcache *regcache,
void *valbuf)
{
int len = TYPE_LENGTH (type);
ULONGEST c, addr;
switch (len)
{
case 1:
case 2:
regcache_cooked_read_unsigned (regcache, E_RET0_REGNUM, &c);
store_unsigned_integer (valbuf, len, c);
break;
case 4:
regcache_cooked_read_unsigned (regcache, E_RET0_REGNUM, &c);
store_unsigned_integer (valbuf, 2, c);
regcache_cooked_read_unsigned (regcache, E_RET1_REGNUM, &c);
store_unsigned_integer ((void*)((char *)valbuf + 2), 2, c);
break;
case 8:
if (TYPE_CODE (type) == TYPE_CODE_INT)
{
regcache_cooked_read_unsigned (regcache, E_RET0_REGNUM, &addr);
c = read_memory_unsigned_integer ((CORE_ADDR) addr, len);
store_unsigned_integer (valbuf, len, c);
}
else
{
error ("I don't know how this 8 byte value is returned.");
}
break;
}
}
static void
h8300h_extract_return_value (struct type *type, struct regcache *regcache,
void *valbuf)
{
int len = TYPE_LENGTH (type);
ULONGEST c, addr;
switch (len)
{
case 1:
case 2:
case 4:
regcache_cooked_read_unsigned (regcache, E_RET0_REGNUM, &c);
store_unsigned_integer (valbuf, len, c);
break;
case 8:
if (TYPE_CODE (type) == TYPE_CODE_INT)
{
regcache_cooked_read_unsigned (regcache, E_RET0_REGNUM, &addr);
c = read_memory_unsigned_integer ((CORE_ADDR) addr, len);
store_unsigned_integer (valbuf, len, c);
}
else
{
error ("I don't know how this 8 byte value is returned.");
}
break;
}
}
static void
h8300_store_return_value (struct type *type, struct regcache *regcache,
const void *valbuf)
{
int len = TYPE_LENGTH (type);
ULONGEST val;
switch (len)
{
case 1:
case 2:
val = extract_unsigned_integer (valbuf, len);
regcache_cooked_write_unsigned (regcache, E_RET0_REGNUM, val);
break;
case 4:
val = extract_unsigned_integer (valbuf, len);
regcache_cooked_write_unsigned (regcache, E_RET0_REGNUM,
(val >> 16) &0xffff);
regcache_cooked_write_unsigned (regcache, E_RET1_REGNUM, val & 0xffff);
break;
case 8:
error ("I don't know how to return an 8 byte value.");
break;
}
}
static void
h8300h_store_return_value (struct type *type, struct regcache *regcache,
const void *valbuf)
{
int len = TYPE_LENGTH (type);
ULONGEST val;
switch (len)
{
case 1:
case 2:
case 4:
val = extract_unsigned_integer (valbuf, len);
regcache_cooked_write_unsigned (regcache, E_RET0_REGNUM, val);
break;
case 8:
error ("I don't know how to return an 8 byte value.");
break;
}
}
static struct cmd_list_element *setmachinelist;
static const char *
h8300_register_name (int regno)
{
static char *register_names[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6",
"sp", "","pc","cycles", "tick", "inst",
"ccr",
};
if (regno < 0
|| regno >= (sizeof (register_names) / sizeof (*register_names)))
internal_error (__FILE__, __LINE__,
"h8300_register_name: illegal register number %d", regno);
else
return register_names[regno];
}
static const char *
h8300s_register_name (int regno)
{
static char *register_names[] = {
"er0", "er1", "er2", "er3", "er4", "er5", "er6",
"sp", "", "pc", "cycles", "", "tick", "inst",
"mach", "macl",
"ccr", "exr"
};
if (regno < 0
|| regno >= (sizeof (register_names) / sizeof (*register_names)))
internal_error (__FILE__, __LINE__,
"h8300s_register_name: illegal register number %d", regno);
else
return register_names[regno];
}
static const char *
h8300sx_register_name (int regno)
{
static char *register_names[] = {
"er0", "er1", "er2", "er3", "er4", "er5", "er6",
"sp", "", "pc", "cycles", "", "tick", "inst",
"mach", "macl", "sbr", "vbr",
"ccr", "exr"
};
if (regno < 0
|| regno >= (sizeof (register_names) / sizeof (*register_names)))
internal_error (__FILE__, __LINE__,
"h8300sx_register_name: illegal register number %d", regno);
else
return register_names[regno];
}
static void
h8300_print_register (struct gdbarch *gdbarch, struct ui_file *file,
struct frame_info *frame, int regno)
{
LONGEST rval;
const char *name = gdbarch_register_name (gdbarch, regno);
if (!name || !*name)
return;
rval = get_frame_register_signed (frame, regno);
fprintf_filtered (file, "%-14s ", name);
if (regno == E_PSEUDO_CCR_REGNUM ||
(regno == E_PSEUDO_EXR_REGNUM && is_h8300smode (current_gdbarch)))
{
fprintf_filtered (file, "0x%02x ", (unsigned char)rval);
print_longest (file, 'u', 1, rval);
}
else
{
fprintf_filtered (file, "0x%s ", phex ((ULONGEST)rval, BINWORD));
print_longest (file, 'd', 1, rval);
}
if (regno == E_PSEUDO_CCR_REGNUM)
{
int C, Z, N, V;
unsigned char l = rval & 0xff;
fprintf_filtered (file, "\t");
fprintf_filtered (file, "I-%d ", (l & 0x80) != 0);
fprintf_filtered (file, "UI-%d ", (l & 0x40) != 0);
fprintf_filtered (file, "H-%d ", (l & 0x20) != 0);
fprintf_filtered (file, "U-%d ", (l & 0x10) != 0);
N = (l & 0x8) != 0;
Z = (l & 0x4) != 0;
V = (l & 0x2) != 0;
C = (l & 0x1) != 0;
fprintf_filtered (file, "N-%d ", N);
fprintf_filtered (file, "Z-%d ", Z);
fprintf_filtered (file, "V-%d ", V);
fprintf_filtered (file, "C-%d ", C);
if ((C | Z) == 0)
fprintf_filtered (file, "u> ");
if ((C | Z) == 1)
fprintf_filtered (file, "u<= ");
if ((C == 0))
fprintf_filtered (file, "u>= ");
if (C == 1)
fprintf_filtered (file, "u< ");
if (Z == 0)
fprintf_filtered (file, "!= ");
if (Z == 1)
fprintf_filtered (file, "== ");
if ((N ^ V) == 0)
fprintf_filtered (file, ">= ");
if ((N ^ V) == 1)
fprintf_filtered (file, "< ");
if ((Z | (N ^ V)) == 0)
fprintf_filtered (file, "> ");
if ((Z | (N ^ V)) == 1)
fprintf_filtered (file, "<= ");
}
else if (regno == E_PSEUDO_EXR_REGNUM && is_h8300smode (current_gdbarch))
{
unsigned char l = rval & 0xff;
fprintf_filtered (file, "\t");
fprintf_filtered (file, "T-%d - - - ", (l & 0x80) != 0);
fprintf_filtered (file, "I2-%d ", (l & 4) != 0);
fprintf_filtered (file, "I1-%d ", (l & 2) != 0);
fprintf_filtered (file, "I0-%d", (l & 1) != 0);
}
fprintf_filtered (file, "\n");
}
static void
h8300_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file,
struct frame_info *frame, int regno, int cpregs)
{
if (regno < 0)
{
for (regno = E_R0_REGNUM; regno <= E_SP_REGNUM; ++regno)
h8300_print_register (gdbarch, file, frame, regno);
h8300_print_register (gdbarch, file, frame, E_PSEUDO_CCR_REGNUM);
h8300_print_register (gdbarch, file, frame, E_PC_REGNUM);
if (is_h8300smode (current_gdbarch))
{
h8300_print_register (gdbarch, file, frame, E_PSEUDO_EXR_REGNUM);
if (is_h8300sxmode (current_gdbarch))
{
h8300_print_register (gdbarch, file, frame, E_SBR_REGNUM);
h8300_print_register (gdbarch, file, frame, E_VBR_REGNUM);
}
h8300_print_register (gdbarch, file, frame, E_MACH_REGNUM);
h8300_print_register (gdbarch, file, frame, E_MACL_REGNUM);
h8300_print_register (gdbarch, file, frame, E_CYCLES_REGNUM);
h8300_print_register (gdbarch, file, frame, E_TICKS_REGNUM);
h8300_print_register (gdbarch, file, frame, E_INSTS_REGNUM);
}
else
{
h8300_print_register (gdbarch, file, frame, E_CYCLES_REGNUM);
h8300_print_register (gdbarch, file, frame, E_TICK_REGNUM);
h8300_print_register (gdbarch, file, frame, E_INST_REGNUM);
}
}
else
{
if (regno == E_CCR_REGNUM)
h8300_print_register (gdbarch, file, frame, E_PSEUDO_CCR_REGNUM);
else if (regno == E_PSEUDO_EXR_REGNUM && is_h8300smode (current_gdbarch))
h8300_print_register (gdbarch, file, frame, E_PSEUDO_EXR_REGNUM);
else
h8300_print_register (gdbarch, file, frame, regno);
}
}
static CORE_ADDR
h8300_saved_pc_after_call (struct frame_info *ignore)
{
return read_memory_unsigned_integer (read_register (E_SP_REGNUM), BINWORD);
}
static struct type *
h8300_register_type (struct gdbarch *gdbarch, int regno)
{
if (regno < 0 || regno >= NUM_REGS + NUM_PSEUDO_REGS)
internal_error (__FILE__, __LINE__,
"h8300_register_type: illegal register number %d",
regno);
else
{
switch (regno)
{
case E_PC_REGNUM:
return builtin_type_void_func_ptr;
case E_SP_REGNUM:
case E_FP_REGNUM:
return builtin_type_void_data_ptr;
default:
if (regno == E_PSEUDO_CCR_REGNUM)
return builtin_type_uint8;
else if (regno == E_PSEUDO_EXR_REGNUM)
return builtin_type_uint8;
else if (is_h8300hmode (current_gdbarch))
return builtin_type_int32;
else
return builtin_type_int16;
}
}
}
static void
h8300_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
int regno, void *buf)
{
if (regno == E_PSEUDO_CCR_REGNUM)
regcache_raw_read (regcache, E_CCR_REGNUM, buf);
else if (regno == E_PSEUDO_EXR_REGNUM)
regcache_raw_read (regcache, E_EXR_REGNUM, buf);
else
regcache_raw_read (regcache, regno, buf);
}
static void
h8300_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
int regno, const void *buf)
{
if (regno == E_PSEUDO_CCR_REGNUM)
regcache_raw_write (regcache, E_CCR_REGNUM, buf);
else if (regno == E_PSEUDO_EXR_REGNUM)
regcache_raw_write (regcache, E_EXR_REGNUM, buf);
else
regcache_raw_write (regcache, regno, buf);
}
static int
h8300_dbg_reg_to_regnum (int regno)
{
if (regno == E_CCR_REGNUM)
return E_PSEUDO_CCR_REGNUM;
return regno;
}
static int
h8300s_dbg_reg_to_regnum (int regno)
{
if (regno == E_CCR_REGNUM)
return E_PSEUDO_CCR_REGNUM;
if (regno == E_EXR_REGNUM)
return E_PSEUDO_EXR_REGNUM;
return regno;
}
static CORE_ADDR
h8300_extract_struct_value_address (struct regcache *regcache)
{
ULONGEST addr;
regcache_cooked_read_unsigned (regcache, E_RET0_REGNUM, &addr);
return addr;
}
const static unsigned char *
h8300_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
{
static unsigned char breakpoint[] = { 0x01, 0x80 };
*lenptr = sizeof (breakpoint);
return breakpoint;
}
static CORE_ADDR
h8300_push_dummy_code (struct gdbarch *gdbarch,
CORE_ADDR sp, CORE_ADDR funaddr, int using_gcc,
struct value **args, int nargs,
struct type *value_type,
CORE_ADDR *real_pc, CORE_ADDR *bp_addr)
{
sp = (sp - 2) & ~1;
*bp_addr = sp;
*real_pc = funaddr;
return sp;
}
static void
h8300_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
struct frame_info *frame, const char *args)
{
fprintf_filtered (file, "\
No floating-point info available for this processor.\n");
}
static struct gdbarch *
h8300_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
struct gdbarch_tdep *tdep = NULL;
struct gdbarch *gdbarch;
arches = gdbarch_list_lookup_by_info (arches, &info);
if (arches != NULL)
return arches->gdbarch;
#if 0
tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
#endif
if (info.bfd_arch_info->arch != bfd_arch_h8300)
return NULL;
gdbarch = gdbarch_alloc (&info, 0);
switch (info.bfd_arch_info->mach)
{
case bfd_mach_h8300:
set_gdbarch_num_regs (gdbarch, 13);
set_gdbarch_num_pseudo_regs (gdbarch, 1);
set_gdbarch_ecoff_reg_to_regnum (gdbarch, h8300_dbg_reg_to_regnum);
set_gdbarch_dwarf_reg_to_regnum (gdbarch, h8300_dbg_reg_to_regnum);
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, h8300_dbg_reg_to_regnum);
set_gdbarch_stab_reg_to_regnum (gdbarch, h8300_dbg_reg_to_regnum);
set_gdbarch_register_name (gdbarch, h8300_register_name);
set_gdbarch_ptr_bit (gdbarch, 2 * TARGET_CHAR_BIT);
set_gdbarch_addr_bit (gdbarch, 2 * TARGET_CHAR_BIT);
set_gdbarch_extract_return_value (gdbarch, h8300_extract_return_value);
set_gdbarch_store_return_value (gdbarch, h8300_store_return_value);
set_gdbarch_print_insn (gdbarch, print_insn_h8300);
break;
case bfd_mach_h8300h:
case bfd_mach_h8300hn:
set_gdbarch_num_regs (gdbarch, 13);
set_gdbarch_num_pseudo_regs (gdbarch, 1);
set_gdbarch_ecoff_reg_to_regnum (gdbarch, h8300_dbg_reg_to_regnum);
set_gdbarch_dwarf_reg_to_regnum (gdbarch, h8300_dbg_reg_to_regnum);
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, h8300_dbg_reg_to_regnum);
set_gdbarch_stab_reg_to_regnum (gdbarch, h8300_dbg_reg_to_regnum);
set_gdbarch_register_name (gdbarch, h8300_register_name);
if(info.bfd_arch_info->mach != bfd_mach_h8300hn)
{
set_gdbarch_ptr_bit (gdbarch, 4 * TARGET_CHAR_BIT);
set_gdbarch_addr_bit (gdbarch, 4 * TARGET_CHAR_BIT);
}
else
{
set_gdbarch_ptr_bit (gdbarch, 2 * TARGET_CHAR_BIT);
set_gdbarch_addr_bit (gdbarch, 2 * TARGET_CHAR_BIT);
}
set_gdbarch_extract_return_value (gdbarch, h8300h_extract_return_value);
set_gdbarch_store_return_value (gdbarch, h8300h_store_return_value);
set_gdbarch_print_insn (gdbarch, print_insn_h8300h);
break;
case bfd_mach_h8300s:
case bfd_mach_h8300sn:
set_gdbarch_num_regs (gdbarch, 16);
set_gdbarch_num_pseudo_regs (gdbarch, 2);
set_gdbarch_ecoff_reg_to_regnum (gdbarch, h8300s_dbg_reg_to_regnum);
set_gdbarch_dwarf_reg_to_regnum (gdbarch, h8300s_dbg_reg_to_regnum);
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, h8300s_dbg_reg_to_regnum);
set_gdbarch_stab_reg_to_regnum (gdbarch, h8300s_dbg_reg_to_regnum);
set_gdbarch_register_name (gdbarch, h8300s_register_name);
if(info.bfd_arch_info->mach != bfd_mach_h8300sn)
{
set_gdbarch_ptr_bit (gdbarch, 4 * TARGET_CHAR_BIT);
set_gdbarch_addr_bit (gdbarch, 4 * TARGET_CHAR_BIT);
}
else
{
set_gdbarch_ptr_bit (gdbarch, 2 * TARGET_CHAR_BIT);
set_gdbarch_addr_bit (gdbarch, 2 * TARGET_CHAR_BIT);
}
set_gdbarch_extract_return_value (gdbarch, h8300h_extract_return_value);
set_gdbarch_store_return_value (gdbarch, h8300h_store_return_value);
set_gdbarch_print_insn (gdbarch, print_insn_h8300s);
break;
case bfd_mach_h8300sx:
case bfd_mach_h8300sxn:
set_gdbarch_num_regs (gdbarch, 18);
set_gdbarch_num_pseudo_regs (gdbarch, 2);
set_gdbarch_ecoff_reg_to_regnum (gdbarch, h8300s_dbg_reg_to_regnum);
set_gdbarch_dwarf_reg_to_regnum (gdbarch, h8300s_dbg_reg_to_regnum);
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, h8300s_dbg_reg_to_regnum);
set_gdbarch_stab_reg_to_regnum (gdbarch, h8300s_dbg_reg_to_regnum);
set_gdbarch_register_name (gdbarch, h8300sx_register_name);
if(info.bfd_arch_info->mach != bfd_mach_h8300sxn)
{
set_gdbarch_ptr_bit (gdbarch, 4 * TARGET_CHAR_BIT);
set_gdbarch_addr_bit (gdbarch, 4 * TARGET_CHAR_BIT);
}
else
{
set_gdbarch_ptr_bit (gdbarch, 2 * TARGET_CHAR_BIT);
set_gdbarch_addr_bit (gdbarch, 2 * TARGET_CHAR_BIT);
}
set_gdbarch_extract_return_value (gdbarch, h8300h_extract_return_value);
set_gdbarch_store_return_value (gdbarch, h8300h_store_return_value);
set_gdbarch_print_insn (gdbarch, print_insn_h8300s);
break;
}
set_gdbarch_pseudo_register_read (gdbarch, h8300_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch, h8300_pseudo_register_write);
set_gdbarch_deprecated_init_frame_pc (gdbarch, deprecated_init_frame_pc_default);
set_gdbarch_sp_regnum (gdbarch, E_SP_REGNUM);
set_gdbarch_deprecated_fp_regnum (gdbarch, E_FP_REGNUM);
set_gdbarch_pc_regnum (gdbarch, E_PC_REGNUM);
set_gdbarch_register_type (gdbarch, h8300_register_type);
set_gdbarch_print_registers_info (gdbarch, h8300_print_registers_info);
set_gdbarch_print_float_info (gdbarch, h8300_print_float_info);
set_gdbarch_skip_prologue (gdbarch, h8300_skip_prologue);
set_gdbarch_deprecated_frame_init_saved_regs (gdbarch,
h8300_frame_init_saved_regs);
set_gdbarch_deprecated_init_extra_frame_info (gdbarch,
h8300_init_extra_frame_info);
set_gdbarch_deprecated_frame_chain (gdbarch, h8300_frame_chain);
set_gdbarch_deprecated_saved_pc_after_call (gdbarch,
h8300_saved_pc_after_call);
set_gdbarch_deprecated_frame_saved_pc (gdbarch, h8300_frame_saved_pc);
set_gdbarch_deprecated_pop_frame (gdbarch, h8300_pop_frame);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
set_gdbarch_deprecated_frameless_function_invocation (gdbarch, legacy_frameless_look_for_prologue);
set_gdbarch_deprecated_extract_struct_value_address (gdbarch, h8300_extract_struct_value_address);
set_gdbarch_use_struct_convention (gdbarch, always_use_struct_convention);
set_gdbarch_breakpoint_from_pc (gdbarch, h8300_breakpoint_from_pc);
set_gdbarch_push_dummy_code (gdbarch, h8300_push_dummy_code);
set_gdbarch_push_dummy_call (gdbarch, h8300_push_dummy_call);
set_gdbarch_int_bit (gdbarch, 2 * TARGET_CHAR_BIT);
set_gdbarch_long_bit (gdbarch, 4 * TARGET_CHAR_BIT);
set_gdbarch_long_long_bit (gdbarch, 8 * TARGET_CHAR_BIT);
set_gdbarch_double_bit (gdbarch, 4 * TARGET_CHAR_BIT);
set_gdbarch_long_double_bit (gdbarch, 4 * TARGET_CHAR_BIT);
set_gdbarch_believe_pcc_promotion (gdbarch, 1);
set_gdbarch_char_signed (gdbarch, 0);
return gdbarch;
}
extern initialize_file_ftype _initialize_h8300_tdep;
void
_initialize_h8300_tdep (void)
{
register_gdbarch_init (bfd_arch_h8300, h8300_gdbarch_init);
}
static int
is_h8300hmode (struct gdbarch *gdbarch)
{
return gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_h8300sx
|| gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_h8300sxn
|| gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_h8300s
|| gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_h8300sn
|| gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_h8300h
|| gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_h8300hn;
}
static int
is_h8300smode (struct gdbarch *gdbarch)
{
return gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_h8300sx
|| gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_h8300sxn
|| gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_h8300s
|| gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_h8300sn;
}
static int
is_h8300sxmode (struct gdbarch *gdbarch)
{
return gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_h8300sx
|| gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_h8300sxn;
}
static int
is_h8300_normal_mode (struct gdbarch *gdbarch)
{
return gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_h8300sxn
|| gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_h8300sn
|| gdbarch_bfd_arch_info (gdbarch)->mach == bfd_mach_h8300hn;
}