aboutsummaryrefslogtreecommitdiff
path: root/src/target/arc.h
blob: a351802ac6ffe251dfd73147d256bb91b3bdbfd4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
/* SPDX-License-Identifier: GPL-2.0-or-later */

/***************************************************************************
 *   Copyright (C) 2013-2015,2019-2020 Synopsys, Inc.                      *
 *   Frank Dols <frank.dols@synopsys.com>                                  *
 *   Mischa Jonker <mischa.jonker@synopsys.com>                            *
 *   Anton Kolesov <anton.kolesov@synopsys.com>                            *
 *   Evgeniy Didin <didin@synopsys.com>                                    *
 ***************************************************************************/

#ifndef OPENOCD_TARGET_ARC_H
#define OPENOCD_TARGET_ARC_H

#include <helper/time_support.h>
#include <jtag/jtag.h>

#include "algorithm.h"
#include "breakpoints.h"
#include "jtag/interface.h"
#include "register.h"
#include "target.h"
#include "target_request.h"
#include "target_type.h"
#include "helper/bits.h"

#include "arc_jtag.h"
#include "arc_cmd.h"
#include "arc_mem.h"

#define ARC_COMMON_MAGIC	0xB32EB324U  /* just a unique number */

#define AUX_DEBUG_REG                   0x5
#define AUX_PC_REG                      0x6
#define AUX_STATUS32_REG                0xA


#define SET_CORE_FORCE_HALT             BIT(1)
#define SET_CORE_HALT_BIT               BIT(0)      /* STATUS32[0] = H field */
#define SET_CORE_ENABLE_INTERRUPTS      BIT(31)
/* STATUS32[5] or AE bit indicates if the processor is in exception state */
#define SET_CORE_AE_BIT                 BIT(5)
/* Single instruction step bit in Debug register */
#define SET_CORE_SINGLE_INSTR_STEP      BIT(11)

#define AUX_STATUS32_REG_HALT_BIT       BIT(0)
#define AUX_STATUS32_REG_IE_BIT         BIT(31)    /* STATUS32[31] = IE field */

/* ARC register numbers */
enum {
	ARC_R0,
	ARC_R1,
	ARC_R2,
	ARC_R3,
	ARC_R4,
	ARC_R5,
	ARC_R6,
	ARC_R7,
	ARC_R8,
	ARC_R9,
	ARC_R10,
	ARC_R11,
	ARC_R12,
	ARC_R13,
	ARC_R14,
	ARC_R15,
	ARC_R16,
	ARC_R17,
	ARC_R18,
	ARC_R19,
	ARC_R20,
	ARC_R21,
	ARC_R22,
	ARC_R23,
	ARC_R24,
	ARC_R25,
	ARC_GP		= 26,
	ARC_FP		= 27,
	ARC_SP		= 28,
	ARC_ILINK	= 29,
	ARC_R30,
	ARC_BLINK	= 31,
	ARC_LP_COUNT	= 60,

	/* Reserved registers */
	ARC_R61		= 61,
	ARC_R62		= 62,

	ARC_PCL		= 63,
	ARC_PC		= 64,
	ARC_LP_START	= 65,
	ARC_LP_END	= 66,
	ARC_STATUS32	= 67,
};

#define CORE_REG_MAX_NUMBER		(63)

/* Limit reg_type/reg_type_field  name to 20 symbols */
#define REG_TYPE_MAX_NAME_LENGTH	20

/* ARC 32bits opcodes */
#define ARC_SDBBP_32 0x256F003FU  /* BRK */

/* ARC 16bits opcodes */
#define ARC_SDBBP_16 0x7FFF      /* BRK_S */

/* Cache registers */
#define AUX_IC_IVIC_REG			0X10
#define IC_IVIC_INVALIDATE		0XFFFFFFFF

#define AUX_DC_IVDC_REG			0X47
#define DC_IVDC_INVALIDATE		BIT(0)
#define AUX_DC_CTRL_REG			0X48
#define DC_CTRL_IM			BIT(6)

/* L2 cache registers */
#define SLC_AUX_CACHE_CTRL		0x903
#define L2_CTRL_IM			BIT(6)
#define L2_CTRL_BS			BIT(8)		/* Busy flag */
#define SLC_AUX_CACHE_FLUSH		0x904
#define L2_FLUSH_FL			BIT(0)
#define SLC_AUX_CACHE_INV		0x905
#define L2_INV_IV			BIT(0)

 /* Action Point */
#define AP_AC_AT_INST_ADDR		0x0
#define AP_AC_AT_MEMORY_ADDR	0x2
#define AP_AC_AT_AUXREG_ADDR	0x4

#define AP_AC_TT_DISABLE		0x00
#define AP_AC_TT_WRITE			0x10
#define AP_AC_TT_READ			0x20
#define AP_AC_TT_READWRITE		0x30

struct arc_reg_bitfield {
	struct reg_data_type_bitfield bitfield;
	char name[REG_TYPE_MAX_NAME_LENGTH];
};
/* Register data type */
struct arc_reg_data_type {
	struct list_head list;
	struct reg_data_type data_type;
	struct reg_data_type_flags data_type_flags;
	struct reg_data_type_struct data_type_struct;
	char data_type_id[REG_TYPE_MAX_NAME_LENGTH];
	struct arc_reg_bitfield *bitfields;
	union {
		struct reg_data_type_struct_field *reg_type_struct_field;
		struct reg_data_type_flags_field *reg_type_flags_field;
	};
};

/* Standard GDB register types */
static const struct reg_data_type standard_gdb_types[] = {
	{ .type = REG_TYPE_INT,         .id = "int" },
	{ .type = REG_TYPE_INT8,        .id = "int8" },
	{ .type = REG_TYPE_INT16,       .id = "int16" },
	{ .type = REG_TYPE_INT32,       .id = "int32" },
	{ .type = REG_TYPE_INT64,       .id = "int64" },
	{ .type = REG_TYPE_INT128,      .id = "int128" },
	{ .type = REG_TYPE_UINT8,       .id = "uint8" },
	{ .type = REG_TYPE_UINT16,      .id = "uint16" },
	{ .type = REG_TYPE_UINT32,      .id = "uint32" },
	{ .type = REG_TYPE_UINT64,      .id = "uint64" },
	{ .type = REG_TYPE_UINT128,     .id = "uint128" },
	{ .type = REG_TYPE_CODE_PTR,    .id = "code_ptr" },
	{ .type = REG_TYPE_DATA_PTR,    .id = "data_ptr" },
	{ .type = REG_TYPE_FLOAT,       .id = "float" },
	{ .type = REG_TYPE_IEEE_SINGLE, .id = "ieee_single" },
	{ .type = REG_TYPE_IEEE_DOUBLE, .id = "ieee_double" },
};

enum arc_actionpointype {
	ARC_AP_BREAKPOINT,
	ARC_AP_WATCHPOINT,
};

/* Actionpoint related fields  */
struct arc_actionpoint {
	int used;
	uint32_t bp_value;
	uint32_t reg_address;
	enum arc_actionpointype type;
};

struct arc_common {
	unsigned int common_magic;

	struct arc_jtag jtag_info;

	struct reg_cache *core_and_aux_cache;
	struct reg_cache *bcr_cache;

	/* Cache control */
	bool has_dcache;
	bool has_icache;
	bool has_l2cache;
	/* If true, then D$ has been already flushed since core has been
	 * halted. */
	bool dcache_flushed;
	/* If true, then L2 has been already flushed since core has been
	 * halted. */
	bool l2cache_flushed;
	/* If true, then caches have been already flushed since core has been
	 * halted. */
	bool icache_invalidated;
	bool dcache_invalidated;
	bool l2cache_invalidated;

	/* Indicate if cache was built (for deinit function) */
	bool core_aux_cache_built;
	bool bcr_cache_built;
	/* Closely Coupled memory(CCM) regions for performance-critical
	 * code (optional). */
	uint32_t iccm0_start;
	uint32_t iccm0_end;
	uint32_t iccm1_start;
	uint32_t iccm1_end;
	uint32_t dccm_start;
	uint32_t dccm_end;

	int irq_state;

	/* Register descriptions */
	struct list_head reg_data_types;
	struct list_head core_reg_descriptions;
	struct list_head aux_reg_descriptions;
	struct list_head bcr_reg_descriptions;
	unsigned long num_regs;
	unsigned long num_core_regs;
	unsigned long num_aux_regs;
	unsigned long num_bcr_regs;
	unsigned long last_general_reg;

	/* PC register location in register cache. */
	unsigned long pc_index_in_cache;
	/* DEBUG register location in register cache. */
	unsigned long debug_index_in_cache;

	/* Actionpoints */
	unsigned int actionpoints_num;
	unsigned int actionpoints_num_avail;
	struct arc_actionpoint *actionpoints_list;
};

/* Borrowed from nds32.h */
#define CHECK_RETVAL(action)			\
	do {					\
		int __retval = (action);	\
		if (__retval != ERROR_OK) {	\
			LOG_DEBUG("error while calling \"%s\"",	\
				# action);     \
			return __retval;	\
		}				\
	} while (0)

static inline struct arc_common *target_to_arc(struct target *target)
{
	return target->arch_info;
}

/* ----- Inlined functions ------------------------------------------------- */

/**
 * Convert data in host endianness to the middle endian. This is required to
 * write 4-byte instructions.
 */
static inline void arc_h_u32_to_me(uint8_t *buf, int val)
{
	buf[1] = (uint8_t) (val >> 24);
	buf[0] = (uint8_t) (val >> 16);
	buf[3] = (uint8_t) (val >> 8);
	buf[2] = (uint8_t) (val >> 0);
}

/**
 * Convert data in middle endian to host endian. This is required to read 32-bit
 * instruction from little endian ARCs.
 */
static inline uint32_t arc_me_to_h_u32(const uint8_t *buf)
{
	return (uint32_t)(buf[2] | buf[3] << 8 | buf[0] << 16 | buf[1] << 24);
}


/* ARC Register description */
struct arc_reg_desc {

	struct target *target;

	/* Register name */
	char *name;

	/* Actual place of storing reg_value */
	uint8_t reg_value[4];

	/* Actual place of storing register feature */
	struct reg_feature feature;

	/* GDB XML feature */
	char *gdb_xml_feature;

	/* Is this a register in g/G-packet? */
	bool is_general;

	/* Architectural number: core reg num or AUX reg num */
	uint32_t arch_num;

	/* Core or AUX register? */
	bool is_core;

	/* Build configuration register? */
	bool is_bcr;

	/* Data type */
	struct reg_data_type *data_type;

	struct list_head list;
};

/* Error codes */
#define ERROR_ARC_REGISTER_NOT_FOUND       (-700)
#define ERROR_ARC_REGISTER_FIELD_NOT_FOUND (-701)
#define ERROR_ARC_REGISTER_IS_NOT_STRUCT   (-702)
#define ERROR_ARC_FIELD_IS_NOT_BITFIELD    (-703)
#define ERROR_ARC_REGTYPE_NOT_FOUND        (-704)

void free_reg_desc(struct arc_reg_desc *r);


void arc_reg_data_type_add(struct target *target,
		struct arc_reg_data_type *data_type);

int arc_reg_add(struct target *target, struct arc_reg_desc *arc_reg,
		const char * const type_name, const size_t type_name_len);

struct reg *arc_reg_get_by_name(struct reg_cache *first,
					const char *name, bool search_all);

int arc_reg_get_field(struct target *target, const char *reg_name,
		const char *field_name, uint32_t *value_ptr);

int arc_cache_flush(struct target *target);
int arc_cache_invalidate(struct target *target);

int arc_add_auxreg_actionpoint(struct target *target,
	uint32_t auxreg_addr, uint32_t transaction);
int arc_remove_auxreg_actionpoint(struct target *target, uint32_t auxreg_addr);
int arc_set_actionpoints_num(struct target *target, uint32_t ap_num);

#endif /* OPENOCD_TARGET_ARC_H */