| /* Mitsubishi Electric Corp. D30V Simulator. | |
| Copyright (C) 1997, Free Software Foundation, Inc. | |
| Contributed by Cygnus Support. | |
| This file is part of GDB, the GNU debugger. | |
| 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 2, 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, write to the Free Software Foundation, Inc., | |
| 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ | |
| #ifndef _CPU_C_ | |
| #define _CPU_C_ | |
| #include "sim-main.h" | |
| int | |
| is_wrong_slot (SIM_DESC sd, | |
| address_word cia, | |
| itable_index index) | |
| { | |
| switch (STATE_CPU (sd, 0)->unit) | |
| { | |
| case memory_unit: | |
| return !itable[index].option[itable_option_mu]; | |
| case integer_unit: | |
| return !itable[index].option[itable_option_iu]; | |
| case any_unit: | |
| return 0; | |
| default: | |
| sim_engine_abort (sd, STATE_CPU (sd, 0), cia, | |
| "internal error - is_wrong_slot - bad switch"); | |
| return -1; | |
| } | |
| } | |
| int | |
| is_condition_ok (SIM_DESC sd, | |
| address_word cia, | |
| int cond) | |
| { | |
| switch (cond) | |
| { | |
| case 0x0: | |
| return 1; | |
| case 0x1: | |
| return PSW_VAL(PSW_F0); | |
| case 0x2: | |
| return !PSW_VAL(PSW_F0); | |
| case 0x3: | |
| return PSW_VAL(PSW_F1); | |
| case 0x4: | |
| return !PSW_VAL(PSW_F1); | |
| case 0x5: | |
| return PSW_VAL(PSW_F0) && PSW_VAL(PSW_F1); | |
| case 0x6: | |
| return PSW_VAL(PSW_F0) && !PSW_VAL(PSW_F1); | |
| case 0x7: | |
| sim_engine_abort (sd, STATE_CPU (sd, 0), cia, | |
| "is_condition_ok - bad instruction condition bits"); | |
| return 0; | |
| default: | |
| sim_engine_abort (sd, STATE_CPU (sd, 0), cia, | |
| "internal error - is_condition_ok - bad switch"); | |
| return -1; | |
| } | |
| } | |
| /* If --trace-call, trace calls, remembering the current state of | |
| registers. */ | |
| typedef struct _call_stack { | |
| struct _call_stack *prev; | |
| registers regs; | |
| } call_stack; | |
| static call_stack *call_stack_head = (call_stack *)0; | |
| static int call_depth = 0; | |
| void call_occurred (SIM_DESC sd, | |
| sim_cpu *cpu, | |
| address_word cia, | |
| address_word nia) | |
| { | |
| call_stack *ptr = ZALLOC (call_stack); | |
| ptr->regs = cpu->regs; | |
| ptr->prev = call_stack_head; | |
| call_stack_head = ptr; | |
| trace_one_insn (sd, cpu, nia, 1, "", 0, "call", | |
| "Depth %3d, Return 0x%.8lx, Args 0x%.8lx 0x%.8lx", | |
| ++call_depth, (unsigned long)cia+8, (unsigned long)GPR[2], | |
| (unsigned long)GPR[3]); | |
| } | |
| /* If --trace-call, trace returns, checking if any saved register was changed. */ | |
| void return_occurred (SIM_DESC sd, | |
| sim_cpu *cpu, | |
| address_word cia, | |
| address_word nia) | |
| { | |
| char buffer[1024]; | |
| char *buf_ptr = buffer; | |
| call_stack *ptr = call_stack_head; | |
| int regno; | |
| char *prefix = ", Registers that differ: "; | |
| *buf_ptr = '\0'; | |
| for (regno = 34; regno <= 63; regno++) { | |
| if (cpu->regs.general_purpose[regno] != ptr->regs.general_purpose[regno]) { | |
| sprintf (buf_ptr, "%sr%d", prefix, regno); | |
| buf_ptr += strlen (buf_ptr); | |
| prefix = " "; | |
| } | |
| } | |
| if (cpu->regs.accumulator[1] != ptr->regs.accumulator[1]) { | |
| sprintf (buf_ptr, "%sa1", prefix); | |
| buf_ptr += strlen (buf_ptr); | |
| prefix = " "; | |
| } | |
| trace_one_insn (sd, cpu, cia, 1, "", 0, "return", | |
| "Depth %3d, Return 0x%.8lx, Ret. 0x%.8lx 0x%.8lx%s", | |
| call_depth--, (unsigned long)nia, (unsigned long)GPR[2], | |
| (unsigned long)GPR[3], buffer); | |
| call_stack_head = ptr->prev; | |
| zfree (ptr); | |
| } | |
| /* Read/write functions for system call interface. */ | |
| int | |
| d30v_read_mem (host_callback *cb, | |
| struct cb_syscall *sc, | |
| unsigned long taddr, | |
| char *buf, | |
| int bytes) | |
| { | |
| SIM_DESC sd = (SIM_DESC) sc->p1; | |
| sim_cpu *cpu = STATE_CPU (sd, 0); | |
| return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes); | |
| } | |
| int | |
| d30v_write_mem (host_callback *cb, | |
| struct cb_syscall *sc, | |
| unsigned long taddr, | |
| const char *buf, | |
| int bytes) | |
| { | |
| SIM_DESC sd = (SIM_DESC) sc->p1; | |
| sim_cpu *cpu = STATE_CPU (sd, 0); | |
| return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes); | |
| } | |
| #endif /* _CPU_C_ */ |