Add Blackfin commands.
git-svn-id: https://urjtag.svn.sourceforge.net/svnroot/urjtag/trunk@1733 b68d4a1b-bc3d-0410-92ed-d4ac073336b7master
parent
8abd3a255d
commit
4aa24728f9
@ -0,0 +1,367 @@
|
||||
/* Copyright (C) 2008, 2009, 2010 Analog Devices, Inc.
|
||||
*
|
||||
* 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
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef BFIN_H
|
||||
#define BFIN_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "tap.h"
|
||||
#include "part.h"
|
||||
|
||||
|
||||
/* High-Nibble: group code, low nibble: register code. */
|
||||
#define T_REG_R 0x00
|
||||
#define T_REG_P 0x10
|
||||
#define T_REG_I 0x20
|
||||
#define T_REG_B 0x30
|
||||
#define T_REG_L 0x34
|
||||
#define T_REG_M 0x24
|
||||
#define T_REG_A 0x40
|
||||
|
||||
enum core_regnum
|
||||
{
|
||||
REG_R0 = T_REG_R, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7,
|
||||
REG_P0 = T_REG_P, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_SP, REG_FP,
|
||||
REG_I0 = T_REG_I, REG_I1, REG_I2, REG_I3,
|
||||
REG_M0 = T_REG_M, REG_M1, REG_M2, REG_M3,
|
||||
REG_B0 = T_REG_B, REG_B1, REG_B2, REG_B3,
|
||||
REG_L0 = T_REG_L, REG_L1, REG_L2, REG_L3,
|
||||
REG_A0x = T_REG_A, REG_A0w, REG_A1x, REG_A1w,
|
||||
REG_ASTAT = 0x46,
|
||||
REG_RETS = 0x47,
|
||||
REG_LC0 = 0x60, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1,
|
||||
REG_CYCLES, REG_CYCLES2,
|
||||
REG_USP = 0x70, REG_SEQSTAT, REG_SYSCFG,
|
||||
REG_RETI, REG_RETX, REG_RETN, REG_RETE, REG_EMUDAT,
|
||||
};
|
||||
|
||||
#define CLASS_MASK 0xf0
|
||||
#define GROUP(x) (((x) & CLASS_MASK) >> 4)
|
||||
#define DREG_P(x) (((x) & CLASS_MASK) == T_REG_R)
|
||||
#define PREG_P(x) (((x) & CLASS_MASK) == T_REG_P)
|
||||
|
||||
|
||||
#define DTEST_COMMAND 0xffe00300
|
||||
#define DTEST_DATA0 0xffe00400
|
||||
#define DTEST_DATA1 0xffe00404
|
||||
|
||||
#define ITEST_COMMAND 0xffe01300
|
||||
#define ITEST_DATA0 0xffe01400
|
||||
#define ITEST_DATA1 0xffe01404
|
||||
|
||||
/* OAB stands for Operations and Bits. */
|
||||
|
||||
struct emu_oab
|
||||
{
|
||||
/* Operations */
|
||||
|
||||
void (*dbgctl_init) (urj_part_t *part, uint16_t value);
|
||||
uint16_t (*dbgstat_value) (urj_part_t *part);
|
||||
|
||||
/* Generate TEST_COMMAND from ADDR and W(rite). */
|
||||
uint32_t (*test_command) (uint32_t addr, int w);
|
||||
|
||||
/* For existing Blackfin processors, it's actually DTEST_COMMAND
|
||||
address. */
|
||||
uint32_t test_command_addr;
|
||||
|
||||
/* For existing Blackfin processors, they are actually DTEST_DATA
|
||||
addresses. */
|
||||
uint32_t test_data0_addr;
|
||||
uint32_t test_data1_addr;
|
||||
|
||||
/* No existing Blackfin processors use this. It should be 0. */
|
||||
int dbgctl_dbgstat_in_one_chain;
|
||||
|
||||
/* No existing Blackfin processors use this. It should be 0. */
|
||||
int sticky_in_reset;
|
||||
|
||||
/* Bits */
|
||||
uint16_t dbgctl_sram_init;
|
||||
uint16_t dbgctl_wakeup;
|
||||
uint16_t dbgctl_sysrst;
|
||||
uint16_t dbgctl_esstep;
|
||||
uint16_t dbgctl_emudatsz_32;
|
||||
uint16_t dbgctl_emudatsz_40;
|
||||
uint16_t dbgctl_emudatsz_48;
|
||||
uint16_t dbgctl_emudatsz_mask;
|
||||
uint16_t dbgctl_emuirlpsz_2;
|
||||
uint16_t dbgctl_emuirsz_64;
|
||||
uint16_t dbgctl_emuirsz_48;
|
||||
uint16_t dbgctl_emuirsz_32;
|
||||
uint16_t dbgctl_emuirsz_mask;
|
||||
uint16_t dbgctl_empen;
|
||||
uint16_t dbgctl_emeen;
|
||||
uint16_t dbgctl_emfen;
|
||||
uint16_t dbgctl_empwr;
|
||||
|
||||
uint16_t dbgstat_lpdec1;
|
||||
uint16_t dbgstat_in_powrgate;
|
||||
uint16_t dbgstat_core_fault;
|
||||
uint16_t dbgstat_idle;
|
||||
uint16_t dbgstat_in_reset;
|
||||
uint16_t dbgstat_lpdec0;
|
||||
uint16_t dbgstat_bist_done;
|
||||
uint16_t dbgstat_emucause_mask;
|
||||
uint16_t dbgstat_emuack;
|
||||
uint16_t dbgstat_emuready;
|
||||
uint16_t dbgstat_emudiovf;
|
||||
uint16_t dbgstat_emudoovf;
|
||||
uint16_t dbgstat_emudif;
|
||||
uint16_t dbgstat_emudof;
|
||||
};
|
||||
|
||||
struct bfin_part_data
|
||||
{
|
||||
int bypass;
|
||||
struct emu_oab *emu_oab;
|
||||
int scan;
|
||||
uint16_t dbgctl;
|
||||
uint16_t dbgstat;
|
||||
uint64_t emuir_a;
|
||||
uint64_t emuir_b;
|
||||
uint64_t emudat_out;
|
||||
uint64_t emudat_in;
|
||||
uint32_t emupc;
|
||||
uint32_t emupc_orig;
|
||||
};
|
||||
|
||||
#define BFIN_PART_BYPASS(part) (((struct bfin_part_data *)((part)->params->data))->bypass)
|
||||
#define EMU_OAB(part) (((struct bfin_part_data *)((part)->params->data))->emu_oab)
|
||||
|
||||
#define BFIN_PART_SCAN(part) (((struct bfin_part_data *)((part)->params->data))->scan)
|
||||
#define BFIN_PART_WPSTAT(part) (((struct bfin_part_data *)((part)->params->data))->wpstat)
|
||||
#define BFIN_PART_DBGCTL(part) (((struct bfin_part_data *)((part)->params->data))->dbgctl)
|
||||
#define BFIN_PART_DBGSTAT(part) (((struct bfin_part_data *)((part)->params->data))->dbgstat)
|
||||
#define BFIN_PART_EMUIR_A(part) (((struct bfin_part_data *)((part)->params->data))->emuir_a)
|
||||
#define BFIN_PART_EMUIR_B(part) (((struct bfin_part_data *)((part)->params->data))->emuir_b)
|
||||
#define BFIN_PART_EMUDAT_OUT(part) (((struct bfin_part_data *)((part)->params->data))->emudat_out)
|
||||
#define BFIN_PART_EMUDAT_IN(part) (((struct bfin_part_data *)((part)->params->data))->emudat_in)
|
||||
#define BFIN_PART_EMUPC(part) (((struct bfin_part_data *)((part)->params->data))->emupc)
|
||||
#define BFIN_PART_EMUPC_ORIG(part) (((struct bfin_part_data *)((part)->params->data))->emupc_orig)
|
||||
|
||||
extern struct emu_oab bfin_emu_oab;
|
||||
|
||||
|
||||
#define IDCODE_SCAN 0
|
||||
#define DBGSTAT_SCAN 1
|
||||
#define DBGCTL_SCAN 2
|
||||
#define EMUIR_SCAN 3
|
||||
#define EMUDAT_SCAN 4
|
||||
#define EMUPC_SCAN 5
|
||||
#define BYPASS 6
|
||||
#define EMUIR64_SCAN 7
|
||||
#define NUM_SCANS 8
|
||||
|
||||
extern const char *scans[];
|
||||
|
||||
#define INSN_NOP 0x0000
|
||||
#define INSN_RTE 0x0014
|
||||
#define INSN_CSYNC 0x0023
|
||||
#define INSN_SSYNC 0x0024
|
||||
#define INSN_ILLEGAL 0xffffffff
|
||||
|
||||
#define INSN_BIT_MULTI 0x08
|
||||
#define INSN_IS_MULTI(insn) \
|
||||
(((insn) & 0xc0) == 0xc0 && ((insn) & INSN_BIT_MULTI) \
|
||||
&& ((insn) & 0xe8) != 0xe8 /* not linkage */)
|
||||
|
||||
enum bfin_insn_type
|
||||
{
|
||||
/* Instruction is a normal instruction. */
|
||||
BFIN_INSN_NORMAL,
|
||||
|
||||
/* Instruction is a value which should be set to EMUDAT. */
|
||||
BFIN_INSN_SET_EMUDAT
|
||||
};
|
||||
|
||||
struct bfin_insn
|
||||
{
|
||||
/* The instruction or the value to be set to EMUDAT. */
|
||||
uint64_t i;
|
||||
|
||||
/* The type of this instruction. */
|
||||
enum bfin_insn_type type;
|
||||
|
||||
/* Instructions to be executed are kept on a linked list.
|
||||
This is the link. */
|
||||
struct bfin_insn *next;
|
||||
};
|
||||
|
||||
enum {
|
||||
LEAVE_NOP_DEFAULT,
|
||||
LEAVE_NOP_YES,
|
||||
LEAVE_NOP_NO
|
||||
};
|
||||
|
||||
extern int bfin_check_emuready;
|
||||
|
||||
/* From src/bfin/bfin.c */
|
||||
|
||||
int part_is_bfin (urj_chain_t *, int);
|
||||
void part_bypass (urj_chain_t *, int);
|
||||
|
||||
urj_tap_register_t *register_init_value (urj_tap_register_t *, uint64_t);
|
||||
uint64_t register_value (urj_tap_register_t *);
|
||||
int part_scan_select (urj_chain_t *, int, int);
|
||||
int chain_scan_select (urj_chain_t *, int);
|
||||
|
||||
#define DECLARE_PART_DBGCTL_SET_BIT(name) \
|
||||
void part_dbgctl_bit_set_##name (urj_chain_t *chain, int n);
|
||||
|
||||
#define DECLARE_PART_DBGCTL_CLEAR_BIT(name) \
|
||||
void part_dbgctl_bit_clear_##name (urj_chain_t *chain, int n);
|
||||
|
||||
#define DECLARE_PART_DBGCTL_IS(name) \
|
||||
int part_dbgctl_is_##name (urj_chain_t *chain, int n);
|
||||
|
||||
#define DECLARE_CHAIN_DBGCTL_SET_BIT(name) \
|
||||
void chain_dbgctl_bit_set_##name (urj_chain_t *chain);
|
||||
|
||||
#define DECLARE_CHAIN_DBGCTL_CLEAR_BIT(name) \
|
||||
void chain_dbgctl_bit_clear_##name (urj_chain_t *chain);
|
||||
|
||||
#define DECLARE_DBGCTL_BIT_OP(name) \
|
||||
DECLARE_PART_DBGCTL_SET_BIT(name) \
|
||||
DECLARE_PART_DBGCTL_CLEAR_BIT(name) \
|
||||
DECLARE_PART_DBGCTL_IS(name) \
|
||||
DECLARE_CHAIN_DBGCTL_SET_BIT(name) \
|
||||
DECLARE_CHAIN_DBGCTL_CLEAR_BIT(name)
|
||||
|
||||
/* These functions check cached DBGSTAT. So before calling them,
|
||||
chain_dbgstat_get or part_dbgstat_get has to be called to update cached
|
||||
DBGSTAT value. */
|
||||
|
||||
#define DECLARE_PART_DBGSTAT_BIT_IS(name) \
|
||||
int part_dbgstat_is_##name (urj_chain_t *chain, int n);
|
||||
|
||||
DECLARE_DBGCTL_BIT_OP (sram_init)
|
||||
DECLARE_DBGCTL_BIT_OP (wakeup)
|
||||
DECLARE_DBGCTL_BIT_OP (sysrst)
|
||||
DECLARE_DBGCTL_BIT_OP (esstep)
|
||||
DECLARE_DBGCTL_BIT_OP (emudatsz_32)
|
||||
DECLARE_DBGCTL_BIT_OP (emudatsz_40)
|
||||
DECLARE_DBGCTL_BIT_OP (emudatsz_48)
|
||||
DECLARE_DBGCTL_BIT_OP (emuirlpsz_2)
|
||||
DECLARE_DBGCTL_BIT_OP (emuirsz_64)
|
||||
DECLARE_DBGCTL_BIT_OP (emuirsz_48)
|
||||
DECLARE_DBGCTL_BIT_OP (emuirsz_32)
|
||||
DECLARE_DBGCTL_BIT_OP (empen)
|
||||
DECLARE_DBGCTL_BIT_OP (emeen)
|
||||
DECLARE_DBGCTL_BIT_OP (emfen)
|
||||
DECLARE_DBGCTL_BIT_OP (empwr)
|
||||
|
||||
DECLARE_PART_DBGSTAT_BIT_IS (lpdec1)
|
||||
DECLARE_PART_DBGSTAT_BIT_IS (in_powrgate)
|
||||
DECLARE_PART_DBGSTAT_BIT_IS (core_fault)
|
||||
DECLARE_PART_DBGSTAT_BIT_IS (idle)
|
||||
DECLARE_PART_DBGSTAT_BIT_IS (in_reset)
|
||||
DECLARE_PART_DBGSTAT_BIT_IS (lpdec0)
|
||||
DECLARE_PART_DBGSTAT_BIT_IS (bist_done)
|
||||
DECLARE_PART_DBGSTAT_BIT_IS (emuack)
|
||||
DECLARE_PART_DBGSTAT_BIT_IS (emuready)
|
||||
DECLARE_PART_DBGSTAT_BIT_IS (emudiovf)
|
||||
DECLARE_PART_DBGSTAT_BIT_IS (emudoovf)
|
||||
DECLARE_PART_DBGSTAT_BIT_IS (emudif)
|
||||
DECLARE_PART_DBGSTAT_BIT_IS (emudof)
|
||||
|
||||
uint16_t part_dbgstat_emucause (urj_chain_t *, int);
|
||||
void chain_dbgstat_get (urj_chain_t *);
|
||||
void part_dbgstat_get (urj_chain_t *, int);
|
||||
void chain_emupc_get (urj_chain_t *, int);
|
||||
uint32_t part_emupc_get (urj_chain_t *, int, int);
|
||||
void chain_dbgstat_clear_ovfs (urj_chain_t *);
|
||||
void part_dbgstat_clear_ovfs (urj_chain_t *, int);
|
||||
void chain_check_emuready (urj_chain_t *);
|
||||
int part_sticky_in_reset (urj_chain_t *, int);
|
||||
void chain_wait_in_reset (urj_chain_t *);
|
||||
void part_wait_in_reset (urj_chain_t *, int);
|
||||
void chain_wait_reset (urj_chain_t *);
|
||||
void part_wait_reset (urj_chain_t *, int);
|
||||
void part_check_emuready (urj_chain_t *, int);
|
||||
void part_emudat_set (urj_chain_t *, int, uint32_t, int);
|
||||
uint32_t part_emudat_get (urj_chain_t *, int, int);
|
||||
void part_emudat_defer_get (urj_chain_t *, int, int);
|
||||
uint32_t part_emudat_get_done (urj_chain_t *, int, int);
|
||||
uint64_t emudat_value (urj_tap_register_t *);
|
||||
void emudat_init_value (urj_tap_register_t *, uint32_t);
|
||||
void chain_register_get (urj_chain_t *, enum core_regnum, uint32_t *);
|
||||
uint32_t part_register_get (urj_chain_t *, int, enum core_regnum);
|
||||
void chain_register_set (urj_chain_t *, enum core_regnum, uint32_t *);
|
||||
void chain_register_set_same (urj_chain_t *, enum core_regnum, uint32_t);
|
||||
void part_register_set (urj_chain_t *, int, enum core_regnum, uint32_t);
|
||||
void chain_emuir_set_same (urj_chain_t *, uint64_t, int);
|
||||
void part_emuir_set (urj_chain_t *, int, uint64_t, int);
|
||||
void chain_emuir_set_same_2 (urj_chain_t *, uint64_t, uint64_t, int);
|
||||
void part_emuir_set_2 (urj_chain_t *, int, uint64_t, uint64_t, int);
|
||||
uint32_t part_get_r0 (urj_chain_t *, int);
|
||||
uint32_t part_get_p0 (urj_chain_t *, int);
|
||||
void part_set_r0 (urj_chain_t *, int, uint32_t);
|
||||
void part_set_p0 (urj_chain_t *, int, uint32_t);
|
||||
void chain_emulation_enable (urj_chain_t *);
|
||||
void part_emulation_enable (urj_chain_t *, int);
|
||||
void chain_emulation_disable (urj_chain_t *);
|
||||
void part_emulation_disable (urj_chain_t *, int);
|
||||
void chain_emulation_trigger (urj_chain_t *);
|
||||
void part_emulation_trigger (urj_chain_t *, int);
|
||||
void chain_emulation_return (urj_chain_t *);
|
||||
void part_emulation_return (urj_chain_t *, int);
|
||||
void part_execute_instructions (urj_chain_t *, int n, struct bfin_insn *);
|
||||
void chain_system_reset (urj_chain_t *);
|
||||
void bfin_core_reset (urj_chain_t *);
|
||||
void software_reset (urj_chain_t *);
|
||||
void chain_emupc_reset (urj_chain_t *, uint32_t *);
|
||||
uint32_t part_mmr_read_clobber_r0 (urj_chain_t *, int, int32_t, int);
|
||||
void part_mmr_write_clobber_r0 (urj_chain_t *, int, int32_t, uint32_t, int);
|
||||
uint32_t part_mmr_read (urj_chain_t *, int, uint32_t, int);
|
||||
void part_mmr_write (urj_chain_t *, int, uint32_t, uint32_t, int);
|
||||
|
||||
/* From src/bfin/insn-gen.c */
|
||||
|
||||
uint32_t gen_move (enum core_regnum dest, enum core_regnum src);
|
||||
uint32_t gen_load32_offset (enum core_regnum dest, enum core_regnum base, int32_t offset);
|
||||
uint32_t gen_store32_offset (enum core_regnum base, int32_t offset, enum core_regnum src);
|
||||
uint32_t gen_load16z_offset (enum core_regnum dest, enum core_regnum base, int32_t offset);
|
||||
uint32_t gen_store16_offset (enum core_regnum base, int32_t offset, enum core_regnum src);
|
||||
uint32_t gen_load8z_offset (enum core_regnum dest, enum core_regnum base, int32_t offset);
|
||||
uint32_t gen_store8_offset (enum core_regnum base, int32_t offset, enum core_regnum src);
|
||||
uint32_t gen_load32pi (enum core_regnum dest, enum core_regnum base);
|
||||
uint32_t gen_store32pi (enum core_regnum base, enum core_regnum src);
|
||||
uint32_t gen_load16zpi (enum core_regnum dest, enum core_regnum base);
|
||||
uint32_t gen_store16pi (enum core_regnum base, enum core_regnum src);
|
||||
uint32_t gen_load8zpi (enum core_regnum dest, enum core_regnum base);
|
||||
uint32_t gen_store8pi (enum core_regnum base, enum core_regnum src);
|
||||
uint32_t gen_load32 (enum core_regnum dest, enum core_regnum base);
|
||||
uint32_t gen_store32 (enum core_regnum base, enum core_regnum src);
|
||||
uint32_t gen_load16z (enum core_regnum dest, enum core_regnum base);
|
||||
uint32_t gen_store16 (enum core_regnum base, enum core_regnum src);
|
||||
uint32_t gen_load8z (enum core_regnum dest, enum core_regnum base);
|
||||
uint32_t gen_store8 (enum core_regnum base, enum core_regnum src);
|
||||
uint32_t gen_iflush (enum core_regnum addr);
|
||||
uint32_t gen_iflush_pm (enum core_regnum addr);
|
||||
uint32_t gen_flush (enum core_regnum addr);
|
||||
uint32_t gen_flush_pm (enum core_regnum addr);
|
||||
uint32_t gen_flushinv (enum core_regnum addr);
|
||||
uint32_t gen_flushinv_pm (enum core_regnum addr);
|
||||
uint32_t gen_prefetch (enum core_regnum addr);
|
||||
uint32_t gen_prefetch_pm (enum core_regnum addr);
|
||||
uint32_t gen_jump_reg (enum core_regnum addr);
|
||||
|
||||
#endif /* BFIN_H */
|
@ -0,0 +1,34 @@
|
||||
#
|
||||
# $Id: Makefile.am 506 2003-08-13 10:05:15Z telka $
|
||||
#
|
||||
# Copyright (C) 2002 ETC s.r.o.
|
||||
#
|
||||
# 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
|
||||
# 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, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
#
|
||||
# Written by Marcel Telka <marcel@telka.sk>, 2002.
|
||||
#
|
||||
|
||||
include $(top_srcdir)/Makefile.rules
|
||||
|
||||
noinst_LTLIBRARIES = libbfin.la
|
||||
|
||||
libbfin_la_SOURCES = \
|
||||
insn-gen.c \
|
||||
bfin.c \
|
||||
bfin-part.c \
|
||||
bfin-part-bfin.c
|
||||
|
||||
AM_CFLAGS = $(WARNINGCFLAGS)
|
@ -0,0 +1,159 @@
|
||||
/* Copyright (C) 2008, 2009, 2010 Analog Devices, Inc.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2, or (at your option) any later
|
||||
* version. See the file COPYING for more details.
|
||||
*
|
||||
* This file 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.
|
||||
*
|
||||
* Non-GPL License is also available. Please contact
|
||||
* <david.babicz@analog.com> for more information.
|
||||
*
|
||||
* Implementation of `Blackfin' target for the GDB proxy server.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <urjtag/part.h>
|
||||
#include <urjtag/data_register.h>
|
||||
#include <urjtag/part_instruction.h>
|
||||
#include <urjtag/bfin.h>
|
||||
|
||||
/* The helper functions for Blackfin DBGCTL and DBGSTAT operations. */
|
||||
|
||||
static void
|
||||
bfin_dbgctl_init (urj_part_t *part, uint16_t v)
|
||||
{
|
||||
register_init_value (part->active_instruction->data_register->in, v);
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
bfin_dbgstat_value (urj_part_t *part)
|
||||
{
|
||||
return register_value (part->active_instruction->data_register->out);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
bfin_test_command (uint32_t addr, int w)
|
||||
{
|
||||
uint32_t test_command;
|
||||
|
||||
/* We can only access [15:0] range. */
|
||||
if ((addr & 0xf0000) != 0)
|
||||
return 0;
|
||||
|
||||
test_command =
|
||||
(addr & 0x0800) << 15 /* Address bit 11 */
|
||||
| (addr & 0x8000) << 8 /* Address bit 15 */
|
||||
| (addr & 0x3000) << 4 /* Address bits [13:12] */
|
||||
| (addr & 0x47f8) /* Address bits 14 and [10:3] */
|
||||
| 0x1000000 /* Access instruction */
|
||||
| 0x4; /* Access data array */
|
||||
|
||||
if (w)
|
||||
test_command |= 0x2; /* Write */
|
||||
|
||||
return test_command;
|
||||
}
|
||||
|
||||
struct emu_oab bfin_emu_oab =
|
||||
{
|
||||
bfin_dbgctl_init,
|
||||
bfin_dbgstat_value,
|
||||
|
||||
bfin_test_command,
|
||||
|
||||
DTEST_COMMAND,
|
||||
DTEST_DATA0,
|
||||
DTEST_DATA1,
|
||||
|
||||
0, /* dbgctl_dbgstat_in_one_chain */
|
||||
0, /* sticky_in_reset */
|
||||
|
||||
0x1000, /* DBGCTL_SRAM_INIT */
|
||||
0x0800, /* DBGCTL_WAKEUP */
|
||||
0x0400, /* DBGCTL_SYSRST */
|
||||
0x0200, /* DBGCTL_ESSTEP */
|
||||
0x0000, /* DBGCTL_EMUDATSZ_32 */
|
||||
0x0080, /* DBGCTL_EMUDATSZ_40 */
|
||||
0x0100, /* DBGCTL_EMUDATSZ_48 */
|
||||
0x0180, /* DBGCTL_EMUDATSZ_MASK */
|
||||
0x0040, /* DBGCTL_EMUIRLPSZ_2 */
|
||||
0x0000, /* DBGCTL_EMUIRSZ_64 */
|
||||
0x0010, /* DBGCTL_EMUIRSZ_48 */
|
||||
0x0020, /* DBGCTL_EMUIRSZ_32 */
|
||||
0x0030, /* DBGCTL_EMUIRSZ_MASK */
|
||||
0x0008, /* DBGCTL_EMPEN */
|
||||
0x0004, /* DBGCTL_EMEEN */
|
||||
0x0002, /* DBGCTL_EMFEN */
|
||||
0x0001, /* DBGCTL_EMPWR */
|
||||
|
||||
0x8000, /* DBGSTAT_LPDEC1 */
|
||||
0x0000, /* No DBGSTAT_IN_POWRGATE for bfin */
|
||||
0x4000, /* DBGSTAT_CORE_FAULT */
|
||||
0x2000, /* DBGSTAT_IDLE */
|
||||
0x1000, /* DBGSTAT_IN_RESET */
|
||||
0x0800, /* DBGSTAT_LPDEC0 */
|
||||
0x0400, /* DBGSTAT_BIST_DONE */
|
||||
0x03c0, /* DBGSTAT_EMUCAUSE_MASK */
|
||||
0x0020, /* DBGSTAT_EMUACK */
|
||||
0x0010, /* DBGSTAT_EMUREADY */
|
||||
0x0008, /* DBGSTAT_EMUDIOVF */
|
||||
0x0004, /* DBGSTAT_EMUDOOVF */
|
||||
0x0002, /* DBGSTAT_EMUDIF */
|
||||
0x0001, /* DBGSTAT_EMUDOF */
|
||||
};
|
||||
|
||||
static void
|
||||
bfin_part_init (urj_part_t *part)
|
||||
{
|
||||
int i;
|
||||
|
||||
assert (part && part->params);
|
||||
|
||||
part->params->free = free;
|
||||
part->params->data = malloc (sizeof (struct bfin_part_data));
|
||||
EMU_OAB (part) = &bfin_emu_oab;
|
||||
|
||||
BFIN_PART_BYPASS (part) = 0;
|
||||
|
||||
for (i = 0; i < NUM_SCANS; i++)
|
||||
if (strcmp (part->active_instruction->name, scans[i]) == 0)
|
||||
break;
|
||||
|
||||
assert (i < NUM_SCANS);
|
||||
|
||||
BFIN_PART_SCAN (part) = i;
|
||||
BFIN_PART_DBGCTL (part) = 0;
|
||||
BFIN_PART_DBGSTAT (part) = 0;
|
||||
BFIN_PART_EMUIR_A (part) = INSN_ILLEGAL;
|
||||
BFIN_PART_EMUIR_B (part) = INSN_ILLEGAL;
|
||||
BFIN_PART_EMUDAT_OUT (part) = 0;
|
||||
BFIN_PART_EMUDAT_IN (part) = 0;
|
||||
BFIN_PART_EMUPC (part) = -1;
|
||||
}
|
||||
|
||||
extern void bfin_init (void);
|
||||
|
||||
void
|
||||
bfin_init ()
|
||||
{
|
||||
urj_part_init_register ("BF506", bfin_part_init);
|
||||
urj_part_init_register ("BF518", bfin_part_init);
|
||||
urj_part_init_register ("BF526", bfin_part_init);
|
||||
urj_part_init_register ("BF527", bfin_part_init);
|
||||
urj_part_init_register ("BF533", bfin_part_init);
|
||||
urj_part_init_register ("BF534", bfin_part_init);
|
||||
urj_part_init_register ("BF537", bfin_part_init);
|
||||
urj_part_init_register ("BF538", bfin_part_init);
|
||||
urj_part_init_register ("BF548", bfin_part_init);
|
||||
urj_part_init_register ("BF561", bfin_part_init);
|
||||
}
|
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (C) 2008, 2009, 2010 Analog Devices, Inc.
|
||||
*
|
||||
* 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
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <urjtag/part.h>
|
||||
#include <urjtag/bfin.h>
|
||||
#include "bfin-part.h"
|
||||
|
||||
/* Wrappers of the helper functions. */
|
||||
|
||||
void
|
||||
_part_dbgctl_init (urj_part_t *part, uint16_t value)
|
||||
{
|
||||
EMU_OAB (part)->dbgctl_init (part, value);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
_part_dbgstat_value (urj_part_t *part)
|
||||
{
|
||||
return EMU_OAB (part)->dbgstat_value (part);
|
||||
}
|
||||
|
||||
/* Routines to access DBGCTL and DBGSTAT bits. */
|
||||
|
||||
#define _PART_DBGCTL_CLEAR_OR_SET_BIT(name) \
|
||||
uint16_t \
|
||||
_part_dbgctl_bit_clear_or_set_##name (urj_part_t *part, uint16_t dbgctl, int set) \
|
||||
{ \
|
||||
if (set) \
|
||||
return dbgctl | EMU_OAB (part)->dbgctl_##name; \
|
||||
else \
|
||||
return dbgctl & ~EMU_OAB (part)->dbgctl_##name; \
|
||||
}
|
||||
|
||||
#define _PART_DBGCTL_BIT_IS(name) \
|
||||
int \
|
||||
_part_dbgctl_is_##name (urj_part_t *part, uint16_t dbgctl) \
|
||||
{ \
|
||||
if (dbgctl & EMU_OAB (part)->dbgctl_##name) \
|
||||
return 1; \
|
||||
else \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define _PART_DBGCTL(name) \
|
||||
_PART_DBGCTL_CLEAR_OR_SET_BIT(name) \
|
||||
_PART_DBGCTL_BIT_IS(name)
|
||||
|
||||
#define _PART_DBGCTL_BIT_IS_MASK(base, sfx) \
|
||||
int \
|
||||
_part_dbgctl_is_##base##_##sfx (urj_part_t *part, uint16_t dbgctl) \
|
||||
{ \
|
||||
if ((dbgctl & EMU_OAB (part)->dbgctl_##base##_mask) == \
|
||||
EMU_OAB (part)->dbgctl_##base##_##sfx) \
|
||||
return 1; \
|
||||
else \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define _PART_DBGCTL_MASK(base, sfx) \
|
||||
_PART_DBGCTL_CLEAR_OR_SET_BIT(base##_##sfx) \
|
||||
_PART_DBGCTL_BIT_IS_MASK(base, sfx)
|
||||
|
||||
_PART_DBGCTL (sram_init)
|
||||
_PART_DBGCTL (wakeup)
|
||||
_PART_DBGCTL (sysrst)
|
||||
_PART_DBGCTL (esstep)
|
||||
_PART_DBGCTL_MASK (emudatsz, 32)
|
||||
_PART_DBGCTL_MASK (emudatsz, 40)
|
||||
_PART_DBGCTL_MASK (emudatsz, 48)
|
||||
_PART_DBGCTL (emuirlpsz_2)
|
||||
_PART_DBGCTL_MASK (emuirsz, 64)
|
||||
_PART_DBGCTL_MASK (emuirsz, 48)
|
||||
_PART_DBGCTL_MASK (emuirsz, 32)
|
||||
_PART_DBGCTL (empen)
|
||||
_PART_DBGCTL (emeen)
|
||||
_PART_DBGCTL (emfen)
|
||||
_PART_DBGCTL (empwr)
|
||||
|
||||
#define _PART_DBGSTAT_BIT_IS(name) \
|
||||
int \
|
||||
_part_dbgstat_is_##name (urj_part_t *part, uint16_t dbgstat) \
|
||||
{ \
|
||||
if (dbgstat & EMU_OAB (part)->dbgstat_##name) \
|
||||
return 1; \
|
||||
else \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define _PART_DBGSTAT_CLEAR_BIT(name) \
|
||||
uint16_t \
|
||||
_part_dbgstat_bit_clear_##name (urj_part_t *part, uint16_t dbgstat) \
|
||||
{ \
|
||||
return dbgstat & ~EMU_OAB (part)->dbgstat_##name; \
|
||||
}
|
||||
|
||||
#define _PART_DBGSTAT_SET_BIT(name) \
|
||||
uint16_t \
|
||||
_part_dbgstat_bit_set_##name (urj_part_t *part, uint16_t dbgstat) \
|
||||
{ \
|
||||
return dbgstat | EMU_OAB (part)->dbgstat_##name; \
|
||||
}
|
||||
|
||||
_PART_DBGSTAT_BIT_IS (lpdec1)
|
||||
_PART_DBGSTAT_BIT_IS (in_powrgate)
|
||||
_PART_DBGSTAT_BIT_IS (core_fault)
|
||||
_PART_DBGSTAT_BIT_IS (idle)
|
||||
_PART_DBGSTAT_BIT_IS (in_reset)
|
||||
_PART_DBGSTAT_BIT_IS (lpdec0)
|
||||
_PART_DBGSTAT_BIT_IS (bist_done)
|
||||
_PART_DBGSTAT_BIT_IS (emuack)
|
||||
_PART_DBGSTAT_BIT_IS (emuready)
|
||||
_PART_DBGSTAT_BIT_IS (emudiovf)
|
||||
_PART_DBGSTAT_BIT_IS (emudoovf)
|
||||
_PART_DBGSTAT_BIT_IS (emudif)
|
||||
_PART_DBGSTAT_BIT_IS (emudof)
|
||||
|
||||
_PART_DBGSTAT_CLEAR_BIT (emudiovf)
|
||||
_PART_DBGSTAT_CLEAR_BIT (emudoovf)
|
||||
|
||||
_PART_DBGSTAT_SET_BIT (emudiovf)
|
||||
_PART_DBGSTAT_SET_BIT (emudoovf)
|
||||
|
||||
int
|
||||
_part_dbgctl_dbgstat_in_one_chain (urj_part_t *part)
|
||||
{
|
||||
return EMU_OAB (part)->dbgctl_dbgstat_in_one_chain;
|
||||
}
|
||||
|
||||
int
|
||||
_part_sticky_in_reset (urj_part_t *part)
|
||||
{
|
||||
return EMU_OAB (part)->sticky_in_reset;
|
||||
}
|
||||
|
||||
uint16_t
|
||||
_part_dbgstat_emucause_mask (urj_part_t *part)
|
||||
{
|
||||
return EMU_OAB (part)->dbgstat_emucause_mask;
|
||||
}
|
||||
|
||||
void _bfin_part_init (void) __attribute__((constructor));
|
||||
|
||||
extern void bfin_init (void);
|
||||
|
||||
void
|
||||
_bfin_part_init ()
|
||||
{
|
||||
bfin_init ();
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/* Copyright (C) 2008, 2009, 2010 Analog Devices, Inc.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2, or (at your option) any later
|
||||
* version. See the file COPYING for more details.
|
||||
*
|
||||
* This file 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.
|
||||
*
|
||||
* Non-GPL License is also available. Please contact
|
||||
* <david.babicz@analog.com> for more information.
|
||||
*
|
||||
* Implementation of `Blackfin' target for the GDB proxy server.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _BLACKFIN_PART_H_
|
||||
#define _BLACKFIN_PART_H_
|
||||
|
||||
#include <urjtag/part.h>
|
||||
|
||||
void _part_dbgctl_init (urj_part_t *, uint16_t);
|
||||
uint16_t _part_dbgstat_value (urj_part_t *);
|
||||
uint16_t _part_dbgstat_emucause_mask (urj_part_t *);
|
||||
|
||||
#define DECLARE__PART_DBGCTL_CLEAR_OR_SET_BIT(name) \
|
||||
uint16_t _part_dbgctl_bit_clear_or_set_##name (urj_part_t *, uint16_t, int);
|
||||
|
||||
#define DECLARE__PART_DBGCTL_IS(name) \
|
||||
extern int _part_dbgctl_is_##name (urj_part_t *, uint16_t);
|
||||
|
||||
#define DECLARE__PART_DBGCTL(name) \
|
||||
DECLARE__PART_DBGCTL_CLEAR_OR_SET_BIT(name) \
|
||||
DECLARE__PART_DBGCTL_IS(name)
|
||||
|
||||
DECLARE__PART_DBGCTL (sram_init)
|
||||
DECLARE__PART_DBGCTL (wakeup)
|
||||
DECLARE__PART_DBGCTL (sysrst)
|
||||
DECLARE__PART_DBGCTL (esstep)
|
||||
DECLARE__PART_DBGCTL (emudatsz_32)
|
||||
DECLARE__PART_DBGCTL (emudatsz_40)
|
||||
DECLARE__PART_DBGCTL (emudatsz_48)
|
||||
DECLARE__PART_DBGCTL (emuirlpsz_2)
|
||||
DECLARE__PART_DBGCTL (emuirsz_64)
|
||||
DECLARE__PART_DBGCTL (emuirsz_48)
|
||||
DECLARE__PART_DBGCTL (emuirsz_32)
|
||||
DECLARE__PART_DBGCTL (empen)
|
||||
DECLARE__PART_DBGCTL (emeen)
|
||||
DECLARE__PART_DBGCTL (emfen)
|
||||
DECLARE__PART_DBGCTL (empwr)
|
||||
|
||||
#define DECLARE__PART_DBGSTAT_BIT_IS(name) \
|
||||
int _part_dbgstat_is_##name (urj_part_t *, uint16_t);
|
||||
|
||||
#define DECLARE__PART_DBGSTAT_CLEAR_BIT(name) \
|
||||
uint16_t _part_dbgstat_bit_clear_##name (urj_part_t *, uint16_t);
|
||||
|
||||
#define DECLARE__PART_DBGSTAT_SET_BIT(name) \
|
||||
uint16_t _part_dbgstat_bit_set_##name (urj_part_t *, uint16_t);
|
||||
|
||||
DECLARE__PART_DBGSTAT_BIT_IS (lpdec1)
|
||||
DECLARE__PART_DBGSTAT_BIT_IS (in_powrgate)
|
||||
DECLARE__PART_DBGSTAT_BIT_IS (core_fault)
|
||||
DECLARE__PART_DBGSTAT_BIT_IS (idle)
|
||||
DECLARE__PART_DBGSTAT_BIT_IS (in_reset)
|
||||
DECLARE__PART_DBGSTAT_BIT_IS (lpdec0)
|
||||
DECLARE__PART_DBGSTAT_BIT_IS (bist_done)
|
||||
DECLARE__PART_DBGSTAT_BIT_IS (emuack)
|
||||
DECLARE__PART_DBGSTAT_BIT_IS (emuready)
|
||||
DECLARE__PART_DBGSTAT_BIT_IS (emudiovf)
|
||||
DECLARE__PART_DBGSTAT_BIT_IS (emudoovf)
|
||||
DECLARE__PART_DBGSTAT_BIT_IS (emudif)
|
||||
DECLARE__PART_DBGSTAT_BIT_IS (emudof)
|
||||
|
||||
DECLARE__PART_DBGSTAT_CLEAR_BIT (emudiovf)
|
||||
DECLARE__PART_DBGSTAT_CLEAR_BIT (emudoovf)
|
||||
|
||||
DECLARE__PART_DBGSTAT_SET_BIT (emudiovf)
|
||||
DECLARE__PART_DBGSTAT_SET_BIT (emudoovf)
|
||||
|
||||
int _part_sticky_in_reset (urj_part_t *);
|
||||
int _part_dbgctl_dbgstat_in_one_chain (urj_part_t *);
|
||||
|
||||
|
||||
#endif /* _BLACKFIN_PART_H_ */
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,270 @@
|
||||
/* Copyright (C) 2008, 2009, 2010 Analog Devices, Inc.
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2, or (at your option) any later
|
||||
* version. See the file COPYING for more details.
|
||||
*
|
||||
* This file 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.
|
||||
*
|
||||
* Non-GPL License is also available. Please contact
|
||||
* <david.babicz@analog.com> for more information.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <urjtag/bfin.h>
|
||||
|
||||
|
||||
uint32_t
|
||||
gen_move (enum core_regnum dest, enum core_regnum src)
|
||||
{
|
||||
uint32_t insn;
|
||||
|
||||
insn = 0x3000;
|
||||
insn |= src & 0xf;
|
||||
insn |= (dest & 0xf) << 3;
|
||||
insn |= GROUP (src) << 6;
|
||||
insn |= GROUP (dest) << 9;
|
||||
|
||||
return insn;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
gen_ldstidxi (enum core_regnum reg,
|
||||
enum core_regnum ptr, int32_t offset, int w, int sz)
|
||||
{
|
||||
uint32_t insn;
|
||||
|
||||
insn = 0xe4000000;
|
||||
insn |= (reg & 0xf) << 16;
|
||||
insn |= (ptr & 0xf) << 19;
|
||||
|
||||
switch (sz)
|
||||
{
|
||||
case 0:
|
||||
offset >>= 2;
|
||||
break;
|
||||
case 1:
|
||||
offset >>= 1;
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
if (offset > 32767 || offset < -32768)
|
||||
abort ();
|
||||
insn |= offset & 0xffff;
|
||||
|
||||
insn |= w << 25;
|
||||
insn |= sz << 22;
|
||||
|
||||
return insn;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_load32_offset (enum core_regnum dest, enum core_regnum base, int32_t offset)
|
||||
{
|
||||
return gen_ldstidxi (dest, base, offset, 0, 0);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_store32_offset (enum core_regnum base, int32_t offset, enum core_regnum src)
|
||||
{
|
||||
return gen_ldstidxi (src, base, offset, 1, 0);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_load16z_offset (enum core_regnum dest, enum core_regnum base, int32_t offset)
|
||||
{
|
||||
return gen_ldstidxi (dest, base, offset, 0, 1);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_store16_offset (enum core_regnum base, int32_t offset, enum core_regnum src)
|
||||
{
|
||||
return gen_ldstidxi (src, base, offset, 1, 1);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_load8z_offset (enum core_regnum dest, enum core_regnum base, int32_t offset)
|
||||
{
|
||||
return gen_ldstidxi (dest, base, offset, 0, 2);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_store8_offset (enum core_regnum base, int32_t offset, enum core_regnum src)
|
||||
{
|
||||
return gen_ldstidxi (src, base, offset, 1, 2);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
gen_ldst (enum core_regnum reg,
|
||||
enum core_regnum ptr, int post_dec, int w, int sz)
|
||||
{
|
||||
uint32_t insn;
|
||||
|
||||
insn = 0x9000;
|
||||
insn |= reg & 0xf;
|
||||
insn |= (ptr & 0xf) << 3;
|
||||
insn |= post_dec << 7;
|
||||
insn |= w << 9;
|
||||
insn |= sz << 10;
|
||||
|
||||
return insn;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_load32pi (enum core_regnum dest, enum core_regnum base)
|
||||
{
|
||||
return gen_ldst (dest, base, 0, 0, 0);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_store32pi (enum core_regnum base, enum core_regnum src)
|
||||
{
|
||||
return gen_ldst (src, base, 0, 1, 0);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_load16zpi (enum core_regnum dest, enum core_regnum base)
|
||||
{
|
||||
return gen_ldst (dest, base, 0, 0, 1);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_store16pi (enum core_regnum base, enum core_regnum src)
|
||||
{
|
||||
return gen_ldst (src, base, 0, 1, 1);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_load8zpi (enum core_regnum dest, enum core_regnum base)
|
||||
{
|
||||
return gen_ldst (dest, base, 0, 0, 2);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_store8pi (enum core_regnum base, enum core_regnum src)
|
||||
{
|
||||
return gen_ldst (src, base, 0, 1, 2);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_load32 (enum core_regnum dest, enum core_regnum base)
|
||||
{
|
||||
return gen_ldst (dest, base, 2, 0, 0);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_store32 (enum core_regnum base, enum core_regnum src)
|
||||
{
|
||||
return gen_ldst (src, base, 2, 1, 0);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_load16z (enum core_regnum dest, enum core_regnum base)
|
||||
{
|
||||
return gen_ldst (dest, base, 2, 0, 1);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_store16 (enum core_regnum base, enum core_regnum src)
|
||||
{
|
||||
return gen_ldst (src, base, 2, 1, 1);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_load8z (enum core_regnum dest, enum core_regnum base)
|
||||
{
|
||||
return gen_ldst (dest, base, 2, 0, 2);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_store8 (enum core_regnum base, enum core_regnum src)
|
||||
{
|
||||
return gen_ldst (src, base, 2, 1, 2);
|
||||
}
|
||||
|
||||
/* op
|
||||
0 prefetch
|
||||
1 flushinv
|
||||
2 flush
|
||||
3 iflush */
|
||||
static uint32_t
|
||||
gen_flush_insn (enum core_regnum addr, int op, int post_modify)
|
||||
{
|
||||
uint32_t insn;
|
||||
|
||||
insn = 0x0240;
|
||||
insn |= addr & 0xf;
|
||||
insn |= op << 3;
|
||||
insn |= post_modify << 5;
|
||||
|
||||
return insn;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_iflush (enum core_regnum addr)
|
||||
{
|
||||
return gen_flush_insn (addr, 3, 0);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_iflush_pm (enum core_regnum addr)
|
||||
{
|
||||
return gen_flush_insn (addr, 3, 1);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_flush (enum core_regnum addr)
|
||||
{
|
||||
return gen_flush_insn (addr, 2, 0);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_flush_pm (enum core_regnum addr)
|
||||
{
|
||||
return gen_flush_insn (addr, 2, 1);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_flushinv (enum core_regnum addr)
|
||||
{
|
||||
return gen_flush_insn (addr, 1, 0);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_flushinv_pm (enum core_regnum addr)
|
||||
{
|
||||
return gen_flush_insn (addr, 1, 1);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_prefetch (enum core_regnum addr)
|
||||
{
|
||||
return gen_flush_insn (addr, 0, 0);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_prefetch_pm (enum core_regnum addr)
|
||||
{
|
||||
return gen_flush_insn (addr, 0, 1);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
gen_jump_reg (enum core_regnum addr)
|
||||
{
|
||||
uint32_t insn;
|
||||
|
||||
insn = 0x0050;
|
||||
insn |= addr & 0x7;
|
||||
|
||||
return insn;
|
||||
}
|
@ -0,0 +1,570 @@
|
||||
/* Copyright (C) 2008, 2009, 2010 Analog Devices, Inc.
|
||||
*
|
||||
* 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
|
||||
* 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, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "sysdep.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <urjtag/part.h>
|
||||
#include <urjtag/chain.h>
|
||||
#include <urjtag/cmd.h>
|
||||
#include <urjtag/bfin.h>
|
||||
|
||||
#include "cmd.h"
|
||||
|
||||
/* For "bfin execute", Blackfin assembler assembles instruction(s)
|
||||
into a temporary object file. When this variable is non-zero, there
|
||||
should be only one instruction in the object file. For example,
|
||||
assembler assembles one instruction a time, which is how we do now.
|
||||
|
||||
Blackfin GAS rounds the section size to 4 bytes. Usually we don't
|
||||
want the padding bytes to be executed as a NOP. With this variable
|
||||
set, only the first instruction in the object file will be
|
||||
executed. */
|
||||
|
||||
int bfin_one_insn_a_file = 1;
|
||||
|
||||
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
|
||||
|
||||
static int
|
||||
cmd_bfin_run (urj_chain_t *chain, char *params[])
|
||||
{
|
||||
int num_params;
|
||||
|
||||
num_params = urj_cmd_params (params);
|
||||
|
||||
if (num_params < 2)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_SYNTAX,
|
||||
"#parameters should be >= 2, not %d",
|
||||
num_params);
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
/* These commands don't need cable or parts. */
|
||||
|
||||
if (strcmp (params[1], "set") == 0)
|
||||
{
|
||||
if (num_params != 4)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_BFIN,
|
||||
"'bfin set' requires 2 parameters, not %d",
|
||||
num_params - 2);
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
if (strcmp (params[2], "one-insn-a-file") == 0)
|
||||
{
|
||||
if (strcmp (params[3], "0") == 0)
|
||||
bfin_one_insn_a_file = 0;
|
||||
else if (strcmp (params[3], "1") == 0)
|
||||
bfin_one_insn_a_file = 1;
|
||||
else
|
||||
{
|
||||
urj_error_set (URJ_ERROR_BFIN,
|
||||
"bad value for one-insn-a-file '%s'",
|
||||
params[3]);
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
urj_error_set (URJ_ERROR_BFIN,
|
||||
"unknown set variable '%s'",
|
||||
params[2]);
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
else if (strcmp (params[1], "show") == 0)
|
||||
{
|
||||
int found = 0;
|
||||
|
||||
if (num_params > 3)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_BFIN,
|
||||
"'bfin show' requires 0 or 1 parameter, not %d",
|
||||
num_params - 2);
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
if (num_params == 2 || strcmp (params[2], "one-insn-a-file") == 0)
|
||||
{
|
||||
found = 1;
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL,
|
||||
"one-insn-a-file: %d\n", bfin_one_insn_a_file);
|
||||
}
|
||||
|
||||
if (!found && num_params == 3)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_BFIN,
|
||||
"unknown set variable '%s'",
|
||||
params[2]);
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
|
||||
/* The remaining commands require cable or parts. */
|
||||
|
||||
if (urj_cmd_test_cable (chain) != URJ_STATUS_OK)
|
||||
return URJ_STATUS_FAIL;
|
||||
|
||||
if (!chain->parts)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_ILLEGAL_STATE, "no parts, Run '%s' first",
|
||||
"detect");
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
if (chain->active_part >= chain->parts->len)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_ILLEGAL_STATE, "no active part");
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
assert (chain->active_part >= 0 && chain->active_part < chain->parts->len);
|
||||
|
||||
if (strcmp (params[1], "emulation") == 0)
|
||||
{
|
||||
if (num_params != 3)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_BFIN,
|
||||
"'bfin emulation' requires 1 parameter, not %d",
|
||||
num_params - 2);
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
if (strcmp (params[2], "enable") == 0)
|
||||
{
|
||||
part_emulation_enable (chain, chain->active_part);
|
||||
}
|
||||
else if (strcmp (params[2], "trigger") == 0)
|
||||
{
|
||||
part_emulation_trigger (chain, chain->active_part);
|
||||
}
|
||||
else if (strcmp (params[2], "enter") == 0)
|
||||
{
|
||||
part_emulation_enable (chain, chain->active_part);
|
||||
part_emulation_trigger (chain, chain->active_part);
|
||||
}
|
||||
else if (strcmp (params[2], "return") == 0)
|
||||
{
|
||||
part_emulation_return (chain, chain->active_part);
|
||||
}
|
||||
else if (strcmp (params[2], "disable") == 0)
|
||||
{
|
||||
part_emulation_disable (chain, chain->active_part);
|
||||
}
|
||||
else if (strcmp (params[2], "exit") == 0)
|
||||
{
|
||||
part_emulation_return (chain, chain->active_part);
|
||||
part_emulation_disable (chain, chain->active_part);
|
||||
}
|
||||
else if (strcmp (params[2], "status") == 0)
|
||||
{
|
||||
uint16_t dbgstat, excause;
|
||||
const char *str_excause;
|
||||
urj_part_t *part;
|
||||
|
||||
part_dbgstat_get (chain, chain->active_part);
|
||||
part = chain->parts->parts[chain->active_part];
|
||||
dbgstat = BFIN_PART_DBGSTAT (part);
|
||||
excause = part_dbgstat_emucause (chain, chain->active_part);
|
||||
|
||||
switch (excause)
|
||||
{
|
||||
case 0x0: str_excause = "EMUEXCPT was executed"; break;
|
||||
case 0x1: str_excause = "EMUIN pin was asserted"; break;
|
||||
case 0x2: str_excause = "Watchpoint event occurred"; break;
|
||||
case 0x4: str_excause = "Performance Monitor 0 overflowed"; break;
|
||||
case 0x5: str_excause = "Performance Monitor 1 overflowed"; break;
|
||||
case 0x8: str_excause = "Emulation single step"; break;
|
||||
default: str_excause = "Reserved??"; break;
|
||||
}
|
||||
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, "Core [%d] DBGSTAT = 0x%"PRIx16"\n",
|
||||
chain->active_part, dbgstat);
|
||||
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL,
|
||||
"\tEMUDOF = %u\n"
|
||||
"\tEMUDIF = %u\n"
|
||||
"\tEMUDOOVF = %u\n"
|
||||
"\tEMUDIOVF = %u\n"
|
||||
"\tEMUREADY = %u\n"
|
||||
"\tEMUACK = %u\n"
|
||||
"\tEMUCAUSE = 0x%x (%s)\n"
|
||||
"\tBIST_DONE = %u\n"
|
||||
"\tLPDEC0 = %u\n"
|
||||
"\tIN_RESET = %u\n"
|
||||
"\tIDLE = %u\n"
|
||||
"\tCORE_FAULT = %u\n"
|
||||
"\tLPDEC1 = %u\n",
|
||||
part_dbgstat_is_emudof (chain, chain->active_part),
|
||||
part_dbgstat_is_emudif (chain, chain->active_part),
|
||||
part_dbgstat_is_emudoovf (chain, chain->active_part),
|
||||
part_dbgstat_is_emudiovf (chain, chain->active_part),
|
||||
part_dbgstat_is_emuready (chain, chain->active_part),
|
||||
part_dbgstat_is_emuack (chain, chain->active_part),
|
||||
excause, str_excause,
|
||||
part_dbgstat_is_bist_done (chain, chain->active_part),
|
||||
part_dbgstat_is_lpdec0 (chain, chain->active_part),
|
||||
part_dbgstat_is_in_reset (chain, chain->active_part),
|
||||
part_dbgstat_is_idle (chain, chain->active_part),
|
||||
part_dbgstat_is_core_fault (chain, chain->active_part),
|
||||
part_dbgstat_is_lpdec1 (chain, chain->active_part));
|
||||
}
|
||||
else if (strcmp (params[2], "singlestep") == 0)
|
||||
{
|
||||
part_dbgstat_get (chain, chain->active_part);
|
||||
|
||||
if (!part_dbgstat_is_emuready (chain, chain->active_part))
|
||||
{
|
||||
urj_error_set (URJ_ERROR_BFIN, "Run '%s' first",
|
||||
"bfin emulation enter");
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
/* TODO Allow an argument to specify how many single steps. */
|
||||
|
||||
part_scan_select (chain, chain->active_part, DBGCTL_SCAN);
|
||||
part_dbgctl_bit_set_esstep (chain, chain->active_part);
|
||||
urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE);
|
||||
part_emuir_set (chain, chain->active_part, INSN_RTE, URJ_CHAIN_EXITMODE_IDLE);
|
||||
part_scan_select (chain, chain->active_part, DBGCTL_SCAN);
|
||||
part_dbgctl_bit_clear_esstep (chain, chain->active_part);
|
||||
urj_tap_chain_shift_data_registers_mode (chain, 0, 1, URJ_CHAIN_EXITMODE_UPDATE);
|
||||
}
|
||||
else
|
||||
{
|
||||
urj_error_set (URJ_ERROR_BFIN,
|
||||
"unknown emulation subcommand '%s'", params[2]);
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
else if (strcmp (params[1], "execute") == 0)
|
||||
{
|
||||
int execute_ret = URJ_STATUS_FAIL;
|
||||
|
||||
part_dbgstat_get (chain, chain->active_part);
|
||||
|
||||
if (!part_dbgstat_is_emuready (chain, chain->active_part))
|
||||
{
|
||||
urj_error_set (URJ_ERROR_BFIN, "Run '%s' first",
|
||||
"bfin emulation enter");
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
if (num_params > 2)
|
||||
{
|
||||
int i;
|
||||
struct bfin_insn *insns = NULL;
|
||||
struct bfin_insn **last = &insns;
|
||||
char tmp[8];
|
||||
char *tmpfile = NULL;
|
||||
|
||||
for (i = 2; i < num_params; i++)
|
||||
{
|
||||
if (params[i][0] == '[' && params[i][1] == '0')
|
||||
{
|
||||
uint64_t n;
|
||||
|
||||
if (sscanf (params[i], "[0%[xX]%"PRIx64"]", tmp, &n) != 2)
|
||||
goto execute_cleanup;
|
||||
|
||||
*last = (struct bfin_insn *) malloc (sizeof (struct bfin_insn));
|
||||
if (*last == NULL)
|
||||
goto execute_cleanup;
|
||||
|
||||
(*last)->i = n;
|
||||
(*last)->type = BFIN_INSN_SET_EMUDAT;
|
||||
(*last)->next = NULL;
|
||||
last = &((*last)->next);
|
||||
}
|
||||
else if (params[i][0] == '0')
|
||||
{
|
||||
uint64_t n;
|
||||
|
||||
if (sscanf (params[i], "0%[xX]%"PRIx64, tmp, &n) != 2)
|
||||
goto execute_cleanup;
|
||||
|
||||
*last = (struct bfin_insn *) malloc (sizeof (struct bfin_insn));
|
||||
if (*last == NULL)
|
||||
goto execute_cleanup;
|
||||
|
||||
(*last)->i = n;
|
||||
(*last)->type = BFIN_INSN_NORMAL;
|
||||
(*last)->next = NULL;
|
||||
last = &((*last)->next);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __MINGW32__
|
||||
urj_error_set (URJ_ERROR_BFIN,
|
||||
"Sorry, dynamic code not available in windows");
|
||||
goto execute_cleanup;
|
||||
#else
|
||||
unsigned char raw_insn[4];
|
||||
char *tmp_buf;
|
||||
char *tuples[] = {"uclinux", "linux-uclibc", "elf"};
|
||||
size_t t;
|
||||
FILE *fp;
|
||||
|
||||
/* 1024 should be plenty; MAXINPUTLINE is 100 in parse.c */
|
||||
char insns_string[1024];
|
||||
char *p = insns_string;
|
||||
|
||||
for (; i < num_params; i++)
|
||||
{
|
||||
p += snprintf (p, sizeof (insns_string) - (p - insns_string),
|
||||
"%s ", params[i]);
|
||||
if (params[i][strlen (params[i]) - 1] == '"')
|
||||
break;
|
||||
if (params[i][strlen (params[i]) - 1] == ';')
|
||||
break;
|
||||
}
|
||||
if (i == num_params)
|
||||
{
|
||||
urj_error_set (URJ_ERROR_BFIN,
|
||||
"unbalanced double quotes");
|
||||
goto execute_cleanup;
|
||||
}
|
||||
|
||||
/* p points past the '\0'. p - 1 points to the ending '\0'.
|
||||
p - 2 points to the last double quote. */
|
||||
*(p - 2) = ';';
|
||||
if (insns_string[0] == '"')
|
||||
insns_string[0] = ' ';
|
||||
|
||||
/* HRM states that branches and hardware loop setup results
|
||||
in undefined behavior. Should check opcode instead? */
|
||||
if (strcasestr(insns_string, "jump") ||
|
||||
strcasestr(insns_string, "call") ||
|
||||
strcasestr(insns_string, "lsetup"))
|
||||
urj_warning (_("jump/call/lsetup insns may not work in emulation\n"));
|
||||
|
||||
|
||||
/* get a temporary file to work with -- a little racy */
|
||||
if (!tmpfile)
|
||||
{
|
||||
tmpfile = tmpnam (NULL);
|
||||
if (!tmpfile)
|
||||
goto execute_cleanup;
|
||||
tmpfile = strdup (tmpfile);
|
||||
if (!tmpfile)
|
||||
goto execute_cleanup;
|
||||
}
|
||||
|
||||
/* try to find a toolchain in $PATH */
|
||||
for (t = 0; t < ARRAY_SIZE(tuples); ++t)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* TODO Pass -mcpu= to gas. */
|
||||
asprintf (&tmp_buf,
|
||||
"bfin-%3$s-as --version >/dev/null 2>&1 || exit $?;"
|
||||
"echo '%1$s' | bfin-%3$s-as - -o \"%2$s\""
|
||||
" && bfin-%3$s-objcopy -O binary \"%2$s\"",
|
||||
insns_string, tmpfile, tuples[t]);
|
||||
ret = system (tmp_buf);
|
||||
free (tmp_buf);
|
||||
if (WIFEXITED(ret))
|
||||
{
|
||||
if (WEXITSTATUS(ret) == 0)
|
||||
break;
|
||||
/* 127 -> not found in $PATH */
|
||||
else if (WEXITSTATUS(ret) == 127)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
urj_error_set (URJ_ERROR_BFIN, "GAS failed parsing: %s",
|
||||
insns_string);
|
||||
goto execute_cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (t == ARRAY_SIZE(tuples))
|
||||
{
|
||||
urj_error_set (URJ_ERROR_BFIN,
|
||||
"unable to find Blackfin toolchain in $PATH\n");
|
||||
goto execute_cleanup;
|
||||
}
|
||||
|
||||
/* Read the binary blob from the toolchain */
|
||||
fp = fopen (tmpfile, "rb");
|
||||
if (fp == NULL)
|
||||
goto execute_cleanup;
|
||||
|
||||
while (fread (raw_insn, 1, 2, fp) == 2)
|
||||
{
|
||||
uint16_t iw = raw_insn[0] | (raw_insn[1] << 8);
|
||||
uint64_t n = iw;
|
||||
int is_multiinsn = INSN_IS_MULTI (raw_insn[1]);
|
||||
|
||||
if ((iw & 0xf000) >= 0xc000)
|
||||
{
|
||||
if (fread (raw_insn, 1, 2, fp) != 2)
|
||||
goto execute_cleanup;
|
||||
|
||||
iw = raw_insn[0] | (raw_insn[1] << 8);
|
||||
n = (n << 16) | iw;
|
||||
}
|
||||
|
||||
if (is_multiinsn)
|
||||
{
|
||||
if (fread (raw_insn, 1, 4, fp) != 4)
|
||||
goto execute_cleanup;
|
||||
|
||||
n = (n << 32)
|
||||
| ((uint64_t)raw_insn[0] << 16)
|
||||
| ((uint64_t)raw_insn[1] << 24)
|
||||
| raw_insn[2] | (raw_insn[3] << 8);
|
||||
}
|
||||
|
||||
*last = (struct bfin_insn *) malloc (sizeof (struct bfin_insn));
|
||||
if (*last == NULL)
|
||||
goto execute_cleanup;
|
||||
|
||||
(*last)->i = n;
|
||||
(*last)->type = BFIN_INSN_NORMAL;
|
||||
(*last)->next = NULL;
|
||||
last = &((*last)->next);
|
||||
|
||||
if (bfin_one_insn_a_file)
|
||||
break;
|
||||
}
|
||||
|
||||
fclose (fp);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
part_execute_instructions (chain, chain->active_part, insns);
|
||||
execute_ret = URJ_STATUS_OK;
|
||||
|
||||
execute_cleanup:
|
||||
if (tmpfile)
|
||||
{
|
||||
unlink (tmpfile);
|
||||
free (tmpfile);
|
||||
}
|
||||
while (insns)
|
||||
{
|
||||
struct bfin_insn *tmp = insns->next;
|
||||
free (insns);
|
||||
insns = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (execute_ret == URJ_STATUS_OK)
|
||||
{
|
||||
uint64_t emudat;
|
||||
|
||||
emudat = part_emudat_get (chain, chain->active_part, URJ_CHAIN_EXITMODE_UPDATE);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, "EMUDAT = 0x%"PRIx64"\n", emudat);
|
||||
|
||||
part_dbgstat_get (chain, chain->active_part);
|
||||
if (part_dbgstat_is_core_fault (chain, chain->active_part))
|
||||
urj_warning (_("core fault detected\n"));
|
||||
}
|
||||
|
||||
return execute_ret;
|
||||
}
|
||||
else if (strcmp (params[1], "reset") == 0)
|
||||
{
|
||||
int reset_what = 0;
|
||||
|
||||
if (num_params == 3)
|
||||
{
|
||||
if (!strcmp (params[2], "core"))
|
||||
reset_what |= 0x1;
|
||||
else if (!strcmp (params[2], "system"))
|
||||
reset_what |= 0x2;
|
||||
else
|
||||
{
|
||||
urj_error_set (URJ_ERROR_BFIN, "bad parameter '%s'", params[2]);
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
}
|
||||
else if (num_params == 2)
|
||||
reset_what = 0x1 | 0x2;
|
||||
else
|
||||
{
|
||||
urj_error_set (URJ_ERROR_BFIN,
|
||||
"'bfin emulation' requires 0 or 1 parameter, not %d",
|
||||
num_params - 2);
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL,
|
||||
_("%s: reseting processor ... "), "bfin");
|
||||
fflush (stdout);
|
||||
if (reset_what == 0x3)
|
||||
software_reset (chain);
|
||||
else if (reset_what & 0x1)
|
||||
bfin_core_reset (chain);
|
||||
else if (reset_what & 0x2)
|
||||
chain_system_reset (chain);
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL, _("OK\n"));
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
urj_error_set (URJ_ERROR_BFIN,
|
||||
"unknown command '%s'", params[1]);
|
||||
return URJ_STATUS_FAIL;
|
||||
}
|
||||
|
||||
return URJ_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cmd_bfin_help (void)
|
||||
{
|
||||
urj_log (URJ_LOG_LEVEL_NORMAL,
|
||||
_("Usage: %s execute INSTRUCTIONs\n"
|
||||
"Usage: %s emulation enter|exit|singlestep|status\n"
|
||||
"Usage: %s reset [core|system]\n"
|
||||
"Usage: %s set one-insn-a-file VALUE\n"
|
||||
"Usage: %s show [one-insn-a-file]\n"
|
||||
"Blackfin specific commands\n"
|
||||
"\n"
|
||||
"INSTRUCTIONs are a sequence of Blackfin encoded instructions,\n"
|
||||
"double quoted assembly statements and [EMUDAT_IN]s\n"),
|
||||
"bfin", "bfin", "bfin", "bfin", "bfin" );
|
||||
}
|
||||
|
||||
const urj_cmd_t urj_cmd_bfin = {
|
||||
"bfin",
|
||||
N_("Blackfin specific commands"),
|
||||
cmd_bfin_help,
|
||||
cmd_bfin_run
|
||||
};
|
Loading…
Reference in New Issue