/*
* Copyright(c) 2013 Intel Corporation.
*
* Adrian Burns (adrian.burns@intel.com)
* Thomas Faust (thomas.faust@intel.com)
* Ivan De Cesaris (ivan.de.cesaris@intel.com)
* Julien Carreno (julien.carreno@intel.com)
* Jeffrey Maxwell (jeffrey.r.maxwell@intel.com)
*
* 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., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
*
* Contact Information:
* Intel Corporation
*/
/*
* @file
* This implements the probemode operations for Lakemont 1 (LMT1).
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <helper/log.h>
#include "target.h"
#include "target_type.h"
#include "lakemont.h"
#include "register.h"
#include "breakpoints.h"
#include "x86_32_common.h"
static int irscan(struct target *t, uint8_t *out,
uint8_t *in, uint8_t ir_len);
static int drscan(struct target *t, uint8_t *out, uint8_t *in, uint8_t len);
static int save_context(struct target *target);
static int restore_context(struct target *target);
static uint32_t get_tapstatus(struct target *t);
static int enter_probemode(struct target *t);
static int exit_probemode(struct target *t);
static int halt_prep(struct target *t);
static int do_halt(struct target *t);
static int do_resume(struct target *t);
static int read_all_core_hw_regs(struct target *t);
static int write_all_core_hw_regs(struct target *t);
static int read_hw_reg(struct target *t,
int reg, uint32_t *regval, uint8_t cache);
static int write_hw_reg(struct target *t,
int reg, uint32_t regval, uint8_t cache);
static struct reg_cache *lakemont_build_reg_cache
(struct target *target);
static int submit_reg_pir(struct target *t, int num);
static int submit_instruction_pir(struct target *t, int num);
static int submit_pir(struct target *t, uint64_t op);
static int lakemont_get_core_reg(struct reg *reg);
static int lakemont_set_core_reg(struct reg *reg, uint8_t *buf);
static struct scan_blk scan;
/* registers and opcodes for register access, pm_idx is used to identify the
* registers that are modified for lakemont probemode specific operations
*/
static const struct {
uint8_t id;
const char *name;
uint64_t op;
uint8_t pm_idx;
unsigned bits;
enum reg_type type;
const char *group;
const char *feature;
} regs[] = {
/* general purpose registers */
{ EAX, "eax", 0x000000D01D660000, 0, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ ECX, "ecx", 0x000000501D660000, 1, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ EDX, "edx", 0x000000901D660000, 2, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ EBX, "ebx", 0x000000101D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" },
{ ESP, "esp", 0x000000E01D660000, NOT_PMREG, 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.i386.core" },
{ EBP, "ebp", 0x000000601D660000, NOT_PMREG, 32, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.i386.core" },
{ ESI, "esi", 0x000000A01D660000, NOT_PMREG, 32, REG_TYPE_INT32, "general", "org.gnu.gdb.i386.core" <