Merge commit 'a9080087d82688043ca216d50926228d09631297' into from_upstream

Change-Id: I83a33c1022f8d1a7670ded62f16ec999fc4ef525
This commit is contained in:
Tim Newsome 2023-12-05 14:35:54 -08:00
commit a63b270b38
30 changed files with 1003 additions and 231 deletions

View File

@ -22,10 +22,22 @@
/* Shared table of known SPI flash devices for SPI-based flash drivers. Taken
* from device datasheets and Linux SPI flash drivers. */
const struct flash_device flash_devices[] = {
/* name, read_cmd, qread_cmd, pprog_cmd, erase_cmd, chip_erase_cmd, device_id,
* pagesize, sectorsize, size_in_bytes
* note: device id is usually 3 bytes long, however the unused highest byte counts
* continuation codes for manufacturer id as per JEP106xx */
/* Note: device_id is usually 3 bytes long, however the unused highest byte counts
* continuation codes for manufacturer id as per JEP106xx.
*
* All sizes (page, sector/block and flash) are in bytes.
*
* Guide to select a proper erase command (if both sector and block erase cmds are available):
* Use 4kbit sector erase cmd and set erase size to the size of sector for small devices
* (4Mbit and less, size <= 0x80000) to prevent too raw erase granularity.
* Use 64kbit block erase cmd and set erase size to the size of block for bigger devices
* (8Mbit and more, size >= 0x100000) to keep erase speed reasonable.
* If the device implements also 32kbit block erase, use it for 8Mbit, size == 0x100000.
*/
/* name read qread page erase chip device_id page erase flash
* _cmd _cmd _prog _cmd* _erase size size* size
* _cmd _cmd
*/
FLASH_ID("st m25pe10", 0x03, 0x00, 0x02, 0xd8, 0x00, 0x00118020, 0x100, 0x10000, 0x20000),
FLASH_ID("st m25pe20", 0x03, 0x00, 0x02, 0xd8, 0x00, 0x00128020, 0x100, 0x10000, 0x40000),
FLASH_ID("st m25pe40", 0x03, 0x00, 0x02, 0xd8, 0x00, 0x00138020, 0x100, 0x10000, 0x80000),
@ -174,6 +186,11 @@ const struct flash_device flash_devices[] = {
FLASH_ID("zetta zd25q16", 0x03, 0x00, 0x02, 0xd8, 0xc7, 0x001560ba, 0x100, 0x10000, 0x200000),
/* FRAM, no erase commands, no write page or sectors */
/* name read qread page device_id total
* _cmd _cmd _prog size
* _cmd
*/
FRAM_ID("fu mb85rs16n", 0x03, 0, 0x02, 0x00010104, 0x800),
FRAM_ID("fu mb85rs32v", 0x03, 0, 0x02, 0x00010204, 0x1000), /* exists ? */
FRAM_ID("fu mb85rs64v", 0x03, 0, 0x02, 0x00020304, 0x2000),

View File

@ -2,15 +2,15 @@
/*
* The manufacturer's standard identification code list appears in JEP106.
* Copyright (c) 2022 JEDEC. All rights reserved.
* Copyright (c) 2023 JEDEC. All rights reserved.
*
* JEP106 is regularly updated. For the current manufacturer's standard
* identification code list, please visit the JEDEC website at www.jedec.org .
*/
/* This file is aligned to revision JEP106BG May 2023. */
/* This file is aligned to revision JEP106BH September 2023. */
/* "NXP (Philips)" is reported below, while missing in JEP106BG */
/* "NXP (Philips)" is reported below, while missing since JEP106BG */
[0][0x01 - 1] = "AMD",
[0][0x02 - 1] = "AMI",
@ -1375,7 +1375,7 @@
[10][0x65 - 1] = "Esperanto Technologies",
[10][0x66 - 1] = "JinSheng Electronic (Shenzhen) Co Ltd",
[10][0x67 - 1] = "Shenzhen Shi Bolunshuai Technology",
[10][0x68 - 1] = "Shanghai Rei Zuan Information Tech",
[10][0x68 - 1] = "Shanghai Rui Zuan Information Tech",
[10][0x69 - 1] = "Fraunhofer IIS",
[10][0x6a - 1] = "Kandou Bus SA",
[10][0x6b - 1] = "Acer",
@ -1841,4 +1841,51 @@
[14][0x3f - 1] = "Shenzhen Dingsheng Technology Co Ltd",
[14][0x40 - 1] = "EVAS Intelligence Co Ltd",
[14][0x41 - 1] = "Kaibright Electronic Technologies",
[14][0x42 - 1] = "Fraunhofer IMS",
[14][0x43 - 1] = "Shenzhen Xinrui Renhe Technology",
[14][0x44 - 1] = "Beijing Vcore Technology Co Ltd",
[14][0x45 - 1] = "Silicon Innovation Technologies Co Ltd",
[14][0x46 - 1] = "Shenzhen Zhengxinda Technology Co Ltd",
[14][0x47 - 1] = "Shenzhen Remai Electronics Co Lttd",
[14][0x48 - 1] = "Shenzhen Xinruiyan Electronics Co Ltd",
[14][0x49 - 1] = "CEC Huada Electronic Design Co Ltd",
[14][0x4a - 1] = "Westberry Technology Inc",
[14][0x4b - 1] = "Tongxin Microelectronics Co Ltd",
[14][0x4c - 1] = "UNIM Semiconductor (Shang Hai) Co Ltd",
[14][0x4d - 1] = "Shenzhen Qiaowenxingyu Industrial Co Ltd",
[14][0x4e - 1] = "ICC",
[14][0x4f - 1] = "Enfabrica Corporation",
[14][0x50 - 1] = "Niobium Microsystems Inc",
[14][0x51 - 1] = "Xiaoli AI Electronics (Shenzhen) Co Ltd",
[14][0x52 - 1] = "Silicon Mitus",
[14][0x53 - 1] = "Ajiatek Inc",
[14][0x54 - 1] = "HomeNet",
[14][0x55 - 1] = "Shenzhen Shubang Technology Co Ltd",
[14][0x56 - 1] = "Exacta Technologies Ltd",
[14][0x57 - 1] = "Synology",
[14][0x58 - 1] = "Trium Elektronik Bilgi Islem San Ve Dis",
[14][0x59 - 1] = "Shenzhen Hippstor Technology Co Ltd",
[14][0x5a - 1] = "SSCT",
[14][0x5b - 1] = "Sichuan Heentai Semiconductor Co Ltd",
[14][0x5c - 1] = "Zhejiang University",
[14][0x5d - 1] = "www.shingroup.cn",
[14][0x5e - 1] = "Suzhou Nano Mchip Technology Company",
[14][0x5f - 1] = "Feature Integration Technology Inc",
[14][0x60 - 1] = "d-Matrix",
[14][0x61 - 1] = "Golden Memory",
[14][0x62 - 1] = "Qingdao Thunderobot Technology Co Ltd",
[14][0x63 - 1] = "Shenzhen Tianxiang Chuangxin Technology",
[14][0x64 - 1] = "HYPHY USA",
[14][0x65 - 1] = "Valkyrie",
[14][0x66 - 1] = "Suzhou Hesetc Electronic Technology Co",
[14][0x67 - 1] = "Hainan Zhongyuncun Technology Co Ltd",
[14][0x68 - 1] = "Shenzhen Yousheng Bona Technology Co",
[14][0x69 - 1] = "Shenzhen Xinle Chuang Technology Co",
[14][0x6a - 1] = "DEEPX",
[14][0x6b - 1] = "iStarChip CA LLC",
[14][0x6c - 1] = "Shenzhen Vinreada Technology Co Ltd",
[14][0x6d - 1] = "Novatek Microelectronics Corp",
[14][0x6e - 1] = "Chemgdu EG Technology Co Ltd",
[14][0x6f - 1] = "AGI Technology",
[14][0x70 - 1] = "Syntiant",
/* EOF */

View File

@ -257,7 +257,7 @@ static int angie_usb_open(struct angie *device)
const uint16_t vids[] = {ANGIE_VID, ANGIE_VID, ANGIE_VID, ANGIE_VID, 0};
const uint16_t pids[] = {ANGIE_PID, ANGIE_PID_2, ANGIE_PID_3, ANGIE_PID_4, 0};
int ret = jtag_libusb_open(vids, pids, &usb_device_handle, NULL);
int ret = jtag_libusb_open(vids, pids, NULL, &usb_device_handle, NULL);
if (ret != ERROR_OK)
return ret;

View File

@ -677,7 +677,7 @@ static struct armjtagew *armjtagew_usb_open(void)
const uint16_t pids[] = { USB_PID, 0 };
struct libusb_device_handle *dev;
if (jtag_libusb_open(vids, pids, &dev, NULL) != ERROR_OK)
if (jtag_libusb_open(vids, pids, NULL, &dev, NULL) != ERROR_OK)
return NULL;
struct armjtagew *result = malloc(sizeof(struct armjtagew));

View File

@ -487,7 +487,7 @@ static int esp_usb_jtag_init(void)
bitq_interface->in_rdy = esp_usb_jtag_in_rdy;
bitq_interface->in = esp_usb_jtag_in;
int r = jtag_libusb_open(vids, pids, &priv->usb_device, NULL);
int r = jtag_libusb_open(vids, pids, NULL, &priv->usb_device, NULL);
if (r != ERROR_OK) {
LOG_ERROR("esp_usb_jtag: could not find or open device!");
goto out;

View File

@ -246,7 +246,7 @@ static int ft232r_init(void)
{
uint16_t avids[] = {ft232r_vid, 0};
uint16_t apids[] = {ft232r_pid, 0};
if (jtag_libusb_open(avids, apids, &adapter, NULL)) {
if (jtag_libusb_open(avids, apids, NULL, &adapter, NULL)) {
const char *ft232r_serial_desc = adapter_get_required_serial();
LOG_ERROR("ft232r not found: vid=%04x, pid=%04x, serial=%s\n",
ft232r_vid, ft232r_pid, (!ft232r_serial_desc) ? "[any]" : ft232r_serial_desc);

View File

@ -275,7 +275,7 @@ static int kitprog_usb_open(void)
const uint16_t vids[] = { VID, 0 };
const uint16_t pids[] = { PID, 0 };
if (jtag_libusb_open(vids, pids, &kitprog_handle->usb_handle, NULL) != ERROR_OK) {
if (jtag_libusb_open(vids, pids, NULL, &kitprog_handle->usb_handle, NULL) != ERROR_OK) {
LOG_ERROR("Failed to open or find the device");
return ERROR_FAIL;
}

View File

@ -146,12 +146,13 @@ static bool jtag_libusb_match_serial(struct libusb_device_handle *device,
}
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
struct libusb_device_handle **out,
const char *product, struct libusb_device_handle **out,
adapter_get_alternate_serial_fn adapter_get_alternate_serial)
{
int cnt, idx, err_code;
int retval = ERROR_FAIL;
bool serial_mismatch = false;
bool product_mismatch = false;
struct libusb_device_handle *libusb_handle = NULL;
const char *serial = adapter_get_required_serial();
@ -188,10 +189,18 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
continue;
}
if (product &&
!string_descriptor_equal(libusb_handle, dev_desc.iProduct, product)) {
product_mismatch = true;
libusb_close(libusb_handle);
continue;
}
/* Success. */
*out = libusb_handle;
retval = ERROR_OK;
serial_mismatch = false;
product_mismatch = false;
break;
}
if (cnt >= 0)
@ -200,6 +209,9 @@ int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
if (serial_mismatch)
LOG_INFO("No device matches the serial string");
if (product_mismatch)
LOG_INFO("No device matches the product string");
if (retval != ERROR_OK)
libusb_exit(jtag_libusb_context);

View File

@ -33,7 +33,7 @@ typedef char * (*adapter_get_alternate_serial_fn)(struct libusb_device_handle *d
bool jtag_libusb_match_ids(struct libusb_device_descriptor *dev_desc,
const uint16_t vids[], const uint16_t pids[]);
int jtag_libusb_open(const uint16_t vids[], const uint16_t pids[],
struct libusb_device_handle **out,
const char *product, struct libusb_device_handle **out,
adapter_get_alternate_serial_fn adapter_get_alternate_serial);
void jtag_libusb_close(struct libusb_device_handle *dev);
int jtag_libusb_control_transfer(struct libusb_device_handle *dev,

View File

@ -695,7 +695,7 @@ struct opendous_jtag *opendous_usb_open(void)
struct opendous_jtag *result;
struct libusb_device_handle *devh;
if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, &devh, NULL) != ERROR_OK)
if (jtag_libusb_open(opendous_probe->VID, opendous_probe->PID, NULL, &devh, NULL) != ERROR_OK)
return NULL;
jtag_libusb_set_configuration(devh, 0);

View File

@ -438,7 +438,7 @@ static int openjtag_init_cy7c65215(void)
int ret;
usbh = NULL;
ret = jtag_libusb_open(cy7c65215_vids, cy7c65215_pids, &usbh, NULL);
ret = jtag_libusb_open(cy7c65215_vids, cy7c65215_pids, NULL, &usbh, NULL);
if (ret != ERROR_OK) {
LOG_ERROR("unable to open cy7c65215 device");
goto err;

View File

@ -363,7 +363,7 @@ static int osbdm_flush(struct osbdm *osbdm, struct queue *queue)
static int osbdm_open(struct osbdm *osbdm)
{
(void)memset(osbdm, 0, sizeof(*osbdm));
if (jtag_libusb_open(osbdm_vid, osbdm_pid, &osbdm->devh, NULL) != ERROR_OK)
if (jtag_libusb_open(osbdm_vid, osbdm_pid, NULL, &osbdm->devh, NULL) != ERROR_OK)
return ERROR_FAIL;
if (libusb_claim_interface(osbdm->devh, 0) != ERROR_OK)

View File

@ -1448,7 +1448,7 @@ static int rlink_init(void)
const uint16_t vids[] = { USB_IDVENDOR, 0 };
const uint16_t pids[] = { USB_IDPRODUCT, 0 };
if (jtag_libusb_open(vids, pids, &hdev, NULL) != ERROR_OK)
if (jtag_libusb_open(vids, pids, NULL, &hdev, NULL) != ERROR_OK)
return ERROR_FAIL;
struct libusb_device_descriptor descriptor;

View File

@ -3406,7 +3406,7 @@ static int stlink_usb_usb_open(void *handle, struct hl_interface_param_s *param)
in order to become operational.
*/
do {
if (jtag_libusb_open(param->vid, param->pid,
if (jtag_libusb_open(param->vid, param->pid, NULL,
&h->usb_backend_priv.fd, stlink_usb_get_alternate_serial) != ERROR_OK) {
LOG_ERROR("open failed");
return ERROR_FAIL;

View File

@ -675,7 +675,7 @@ static int icdi_usb_open(struct hl_interface_param_s *param, void **fd)
/* TI (Stellaris) ICDI provides its serial number in the USB descriptor;
no need to provide a callback here. */
jtag_libusb_open(param->vid, param->pid, &h->usb_dev, NULL);
jtag_libusb_open(param->vid, param->pid, NULL, &h->usb_dev, NULL);
if (!h->usb_dev) {
LOG_ERROR("open failed");

View File

@ -202,7 +202,7 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
bool renumeration = false;
int ret;
if (jtag_libusb_open(vids, pids, &temp, NULL) == ERROR_OK) {
if (jtag_libusb_open(vids, pids, NULL, &temp, NULL) == ERROR_OK) {
LOG_INFO("Altera USB-Blaster II (uninitialized) found");
LOG_INFO("Loading firmware...");
ret = load_usb_blaster_firmware(temp, low);
@ -216,13 +216,13 @@ static int ublast2_libusb_init(struct ublast_lowlevel *low)
const uint16_t pids_renum[] = { low->ublast_pid, 0 };
if (renumeration == false) {
if (jtag_libusb_open(vids_renum, pids_renum, &low->libusb_dev, NULL) != ERROR_OK) {
if (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev, NULL) != ERROR_OK) {
LOG_ERROR("Altera USB-Blaster II not found");
return ERROR_FAIL;
}
} else {
int retry = 10;
while (jtag_libusb_open(vids_renum, pids_renum, &low->libusb_dev, NULL) != ERROR_OK && retry--) {
while (jtag_libusb_open(vids_renum, pids_renum, NULL, &low->libusb_dev, NULL) != ERROR_OK && retry--) {
usleep(1000000);
LOG_INFO("Waiting for reenumerate...");
}

View File

@ -341,7 +341,7 @@ struct usbprog_jtag *usbprog_jtag_open(void)
const uint16_t pids[] = { PID, 0 };
struct libusb_device_handle *dev;
if (jtag_libusb_open(vids, pids, &dev, NULL) != ERROR_OK)
if (jtag_libusb_open(vids, pids, NULL, &dev, NULL) != ERROR_OK)
return NULL;
struct usbprog_jtag *tmp = malloc(sizeof(struct usbprog_jtag));

View File

@ -83,6 +83,7 @@ static void os_free(struct target *target)
return;
free(target->rtos->symbols);
rtos_free_threadlist(target->rtos);
free(target->rtos);
target->rtos = NULL;
}

View File

@ -95,6 +95,8 @@ struct gdb_connection {
char *thread_list;
/* flag to mask the output from gdb_log_callback() */
enum gdb_output_flag output_flag;
/* Unique index for this GDB connection. */
unsigned int unique_index;
};
#if 0
@ -392,6 +394,7 @@ static void gdb_log_incoming_packet(struct connection *connection, char *packet)
return;
struct target *target = get_target_from_connection(connection);
struct gdb_connection *gdb_connection = connection->priv;
/* Avoid dumping non-printable characters to the terminal */
const unsigned packet_len = strlen(packet);
@ -406,14 +409,15 @@ static void gdb_log_incoming_packet(struct connection *connection, char *packet)
if (packet_prefix_printable) {
const unsigned int prefix_len = colon - packet + 1; /* + 1 to include the ':' */
const unsigned int payload_len = packet_len - prefix_len;
LOG_TARGET_DEBUG(target, "received packet: %.*s<binary-data-%u-bytes>", prefix_len,
packet, payload_len);
LOG_TARGET_DEBUG(target, "{%d} received packet: %.*s<binary-data-%u-bytes>",
gdb_connection->unique_index, prefix_len, packet, payload_len);
} else {
LOG_TARGET_DEBUG(target, "received packet: <binary-data-%u-bytes>", packet_len);
LOG_TARGET_DEBUG(target, "{%d} received packet: <binary-data-%u-bytes>",
gdb_connection->unique_index, packet_len);
}
} else {
/* All chars printable, dump the packet as is */
LOG_TARGET_DEBUG(target, "received packet: %s", packet);
LOG_TARGET_DEBUG(target, "{%d} received packet: %s", gdb_connection->unique_index, packet);
}
}
@ -424,13 +428,14 @@ static void gdb_log_outgoing_packet(struct connection *connection, char *packet_
return;
struct target *target = get_target_from_connection(connection);
struct gdb_connection *gdb_connection = connection->priv;
if (find_nonprint_char(packet_buf, packet_len))
LOG_TARGET_DEBUG(target, "sending packet: $<binary-data-%u-bytes>#%2.2x",
packet_len, checksum);
LOG_TARGET_DEBUG(target, "{%d} sending packet: $<binary-data-%u-bytes>#%2.2x",
gdb_connection->unique_index, packet_len, checksum);
else
LOG_TARGET_DEBUG(target, "sending packet: $%.*s#%2.2x", packet_len, packet_buf,
checksum);
LOG_TARGET_DEBUG(target, "{%d} sending packet: $%.*s#%2.2x",
gdb_connection->unique_index, packet_len, packet_buf, checksum);
}
static int gdb_put_packet_inner(struct connection *connection,
@ -1017,6 +1022,7 @@ static int gdb_new_connection(struct connection *connection)
struct target *target;
int retval;
int initial_ack;
static unsigned int next_unique_id = 1;
target = get_target_from_connection(connection);
connection->priv = gdb_connection;
@ -1039,6 +1045,7 @@ static int gdb_new_connection(struct connection *connection)
gdb_connection->target_desc.tdesc_length = 0;
gdb_connection->thread_list = NULL;
gdb_connection->output_flag = GDB_OUTPUT_NO;
gdb_connection->unique_index = next_unique_id++;
/* send ACK to GDB for debug request */
gdb_write(connection, "+", 1);
@ -1097,20 +1104,19 @@ static int gdb_new_connection(struct connection *connection)
}
}
gdb_actual_connections++;
log_printf_lf(all_targets->next ? LOG_LVL_INFO : LOG_LVL_DEBUG,
__FILE__, __LINE__, __func__,
"New GDB Connection: %d, Target %s, state: %s",
gdb_actual_connections,
gdb_connection->unique_index,
target_name(target),
target_state_name(target));
if (!target_was_examined(target)) {
LOG_ERROR("Target %s not examined yet, refuse gdb connection %d!",
target_name(target), gdb_actual_connections);
gdb_actual_connections--;
target_name(target), gdb_connection->unique_index);
return ERROR_TARGET_NOT_EXAMINED;
}
gdb_actual_connections++;
if (target->state != TARGET_HALTED)
LOG_WARNING("GDB connection %d on target %s not halted",
@ -1141,7 +1147,8 @@ static int gdb_connection_closed(struct connection *connection)
log_remove_callback(gdb_log_callback, connection);
gdb_actual_connections--;
LOG_DEBUG("GDB Close, Target: %s, state: %s, gdb_actual_connections=%d",
LOG_DEBUG("{%d} GDB Close, Target: %s, state: %s, gdb_actual_connections=%d",
gdb_connection->unique_index,
target_name(target),
target_state_name(target),
gdb_actual_connections);

View File

@ -468,7 +468,7 @@ static int watchpoint_remove_all_internal(struct target *target)
return retval;
}
int breakpoint_watchpoint_remove_all(struct target *target, enum breakpoint_watchpoint bp_wp)
static int breakpoint_watchpoint_remove_all(struct target *target, enum breakpoint_watchpoint bp_wp)
{
assert(bp_wp == BREAKPOINT || bp_wp == WATCHPOINT);
int retval = ERROR_OK;

View File

@ -968,12 +968,13 @@ int image_open(struct image *image, const char *url, const char *type_string)
retval = fileio_open(&image_binary->fileio, url, FILEIO_READ, FILEIO_BINARY);
if (retval != ERROR_OK)
return retval;
goto free_mem_on_error;
size_t filesize;
retval = fileio_size(image_binary->fileio, &filesize);
if (retval != ERROR_OK) {
fileio_close(image_binary->fileio);
return retval;
goto free_mem_on_error;
}
image->num_sections = 1;
@ -988,14 +989,14 @@ int image_open(struct image *image, const char *url, const char *type_string)
retval = fileio_open(&image_ihex->fileio, url, FILEIO_READ, FILEIO_TEXT);
if (retval != ERROR_OK)
return retval;
goto free_mem_on_error;
retval = image_ihex_buffer_complete(image);
if (retval != ERROR_OK) {
LOG_ERROR(
"failed buffering IHEX image, check server output for additional information");
fileio_close(image_ihex->fileio);
return retval;
goto free_mem_on_error;
}
} else if (image->type == IMAGE_ELF) {
struct image_elf *image_elf;
@ -1004,12 +1005,12 @@ int image_open(struct image *image, const char *url, const char *type_string)
retval = fileio_open(&image_elf->fileio, url, FILEIO_READ, FILEIO_BINARY);
if (retval != ERROR_OK)
return retval;
goto free_mem_on_error;
retval = image_elf_read_headers(image);
if (retval != ERROR_OK) {
fileio_close(image_elf->fileio);
return retval;
goto free_mem_on_error;
}
} else if (image->type == IMAGE_MEMORY) {
struct target *target = get_target(url);
@ -1039,14 +1040,14 @@ int image_open(struct image *image, const char *url, const char *type_string)
retval = fileio_open(&image_mot->fileio, url, FILEIO_READ, FILEIO_TEXT);
if (retval != ERROR_OK)
return retval;
goto free_mem_on_error;
retval = image_mot_buffer_complete(image);
if (retval != ERROR_OK) {
LOG_ERROR(
"failed buffering S19 image, check server output for additional information");
fileio_close(image_mot->fileio);
return retval;
goto free_mem_on_error;
}
} else if (image->type == IMAGE_BUILDER) {
image->num_sections = 0;
@ -1067,6 +1068,11 @@ int image_open(struct image *image, const char *url, const char *type_string)
}
return retval;
free_mem_on_error:
free(image->type_private);
image->type_private = NULL;
return retval;
};
int image_read_section(struct image *image,

View File

@ -27,7 +27,7 @@ static const char *mips_isa_strings[] = {
"MIPS32", "MIPS16", "", "MICRO MIPS32",
};
#define MIPS32_GDB_DUMMY_FP_REG 1
#define MIPS32_GDB_FP_REG 1
/*
* GDB registers
@ -39,7 +39,7 @@ static const struct {
enum reg_type type;
const char *group;
const char *feature;
int flag;
int size;
} mips32_regs[] = {
{ 0, "r0", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 1, "r1", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
@ -73,88 +73,93 @@ static const struct {
{ 29, "r29", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 30, "r30", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 31, "r31", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 32, "status", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 },
{ 33, "lo", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 34, "hi", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 35, "badvaddr", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 },
{ 36, "cause", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cp0", 0 },
{ 37, "pc", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 32, "lo", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 33, "hi", REG_TYPE_INT, NULL, "org.gnu.gdb.mips.cpu", 0 },
{ 38, "f0", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 39, "f1", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 40, "f2", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 41, "f3", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 42, "f4", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 43, "f5", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 44, "f6", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 45, "f7", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 46, "f8", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 47, "f9", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 48, "f10", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 49, "f11", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 50, "f12", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 51, "f13", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 52, "f14", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 53, "f15", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 54, "f16", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 55, "f17", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 56, "f18", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 57, "f19", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 58, "f20", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 59, "f21", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 60, "f22", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 61, "f23", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 62, "f24", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 63, "f25", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 64, "f26", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 65, "f27", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 66, "f28", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 67, "f29", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 68, "f30", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 69, "f31", REG_TYPE_IEEE_SINGLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 70, "fcsr", REG_TYPE_INT, "float",
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ 71, "fir", REG_TYPE_INT, "float",
"org.gnu.gdb.mips.fpu", MIPS32_GDB_DUMMY_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 0, "f0", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 1, "f1", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 2, "f2", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 3, "f3", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 4, "f4", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 5, "f5", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 6, "f6", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 7, "f7", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 8, "f8", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 9, "f9", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 10, "f10", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 11, "f11", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 12, "f12", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 13, "f13", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 14, "f14", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 15, "f15", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 16, "f16", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 17, "f17", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 18, "f18", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 19, "f19", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 20, "f20", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 21, "f21", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 22, "f22", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 23, "f23", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 24, "f24", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 25, "f25", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 26, "f26", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 27, "f27", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 28, "f28", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 29, "f29", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 30, "f30", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FP_INDEX + 31, "f31", REG_TYPE_IEEE_DOUBLE, NULL,
"org.gnu.gdb.mips.fpu", MIPS32_GDB_FP_REG },
{ MIPS32_REGLIST_FPC_INDEX + 0, "fcsr", REG_TYPE_INT, "float",
"org.gnu.gdb.mips.fpu", 0 },
{ MIPS32_REGLIST_FPC_INDEX + 1, "fir", REG_TYPE_INT, "float",
"org.gnu.gdb.mips.fpu", 0 },
{ MIPS32_REGLIST_C0_STATUS_INDEX, "status", REG_TYPE_INT, NULL,
"org.gnu.gdb.mips.cp0", 0 },
{ MIPS32_REGLIST_C0_BADVADDR_INDEX, "badvaddr", REG_TYPE_INT, NULL,
"org.gnu.gdb.mips.cp0", 0 },
{ MIPS32_REGLIST_C0_CAUSE_INDEX, "cause", REG_TYPE_INT, NULL,
"org.gnu.gdb.mips.cp0", 0 },
{ MIPS32_REGLIST_C0_PC_INDEX, "pc", REG_TYPE_INT, NULL,
"org.gnu.gdb.mips.cpu", 0 },
{ MIPS32_REGLIST_C0_GUESTCTL1_INDEX, "guestCtl1", REG_TYPE_INT, NULL,
"org.gnu.gdb.mips.cp0", 0 },
};
#define MIPS32_NUM_REGS ARRAY_SIZE(mips32_regs)
static uint8_t mips32_gdb_dummy_fp_value[] = {0, 0, 0, 0};
static int mips32_get_core_reg(struct reg *reg)
{
int retval;
@ -174,12 +179,21 @@ static int mips32_set_core_reg(struct reg *reg, uint8_t *buf)
{
struct mips32_core_reg *mips32_reg = reg->arch_info;
struct target *target = mips32_reg->target;
uint32_t value = buf_get_u32(buf, 0, 32);
uint64_t value;
if (reg->size == 64)
value = buf_get_u64(buf, 0, 64);
else
value = buf_get_u32(buf, 0, 32);
if (target->state != TARGET_HALTED)
return ERROR_TARGET_NOT_HALTED;
buf_set_u32(reg->value, 0, 32, value);
if (reg->size == 64)
buf_set_u64(reg->value, 0, 64, value);
else
buf_set_u32(reg->value, 0, 32, value);
reg->dirty = true;
reg->valid = true;
@ -188,7 +202,8 @@ static int mips32_set_core_reg(struct reg *reg, uint8_t *buf)
static int mips32_read_core_reg(struct target *target, unsigned int num)
{
uint32_t reg_value;
unsigned int cnum;
uint64_t reg_value = 0;
/* get pointers to arch-specific information */
struct mips32_common *mips32 = target_to_mips32(target);
@ -196,17 +211,40 @@ static int mips32_read_core_reg(struct target *target, unsigned int num)
if (num >= MIPS32_NUM_REGS)
return ERROR_COMMAND_SYNTAX_ERROR;
reg_value = mips32->core_regs[num];
buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
if (num >= MIPS32_REGLIST_C0_INDEX) {
/* CP0 */
cnum = num - MIPS32_REGLIST_C0_INDEX;
reg_value = mips32->core_regs.cp0[cnum];
buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
} else if (num >= MIPS32_REGLIST_FPC_INDEX) {
/* FPCR */
cnum = num - MIPS32_REGLIST_FPC_INDEX;
reg_value = mips32->core_regs.fpcr[cnum];
buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
} else if (num >= MIPS32_REGLIST_FP_INDEX) {
/* FPR */
cnum = num - MIPS32_REGLIST_FP_INDEX;
reg_value = mips32->core_regs.fpr[cnum];
buf_set_u64(mips32->core_cache->reg_list[num].value, 0, 64, reg_value);
} else {
/* GPR */
cnum = num - MIPS32_REGLIST_GP_INDEX;
reg_value = mips32->core_regs.gpr[cnum];
buf_set_u32(mips32->core_cache->reg_list[num].value, 0, 32, reg_value);
}
mips32->core_cache->reg_list[num].valid = true;
mips32->core_cache->reg_list[num].dirty = false;
LOG_DEBUG("read core reg %i value 0x%" PRIx64 "", num, reg_value);
return ERROR_OK;
}
static int mips32_write_core_reg(struct target *target, unsigned int num)
{
uint32_t reg_value;
unsigned int cnum;
uint64_t reg_value;
/* get pointers to arch-specific information */
struct mips32_common *mips32 = target_to_mips32(target);
@ -214,9 +252,29 @@ static int mips32_write_core_reg(struct target *target, unsigned int num)
if (num >= MIPS32_NUM_REGS)
return ERROR_COMMAND_SYNTAX_ERROR;
reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
mips32->core_regs[num] = reg_value;
LOG_DEBUG("write core reg %i value 0x%" PRIx32 "", num, reg_value);
if (num >= MIPS32_REGLIST_C0_INDEX) {
/* CP0 */
cnum = num - MIPS32_REGLIST_C0_INDEX;
reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
mips32->core_regs.cp0[cnum] = (uint32_t)reg_value;
} else if (num >= MIPS32_REGLIST_FPC_INDEX) {
/* FPCR */
cnum = num - MIPS32_REGLIST_FPC_INDEX;
reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
mips32->core_regs.fpcr[cnum] = (uint32_t)reg_value;
} else if (num >= MIPS32_REGLIST_FP_INDEX) {
/* FPR */
cnum = num - MIPS32_REGLIST_FP_INDEX;
reg_value = buf_get_u64(mips32->core_cache->reg_list[num].value, 0, 64);
mips32->core_regs.fpr[cnum] = reg_value;
} else {
/* GPR */
cnum = num - MIPS32_REGLIST_GP_INDEX;
reg_value = buf_get_u32(mips32->core_cache->reg_list[num].value, 0, 32);
mips32->core_regs.gpr[cnum] = (uint32_t)reg_value;
}
LOG_DEBUG("write core reg %i value 0x%" PRIx64 "", num, reg_value);
mips32->core_cache->reg_list[num].valid = true;
mips32->core_cache->reg_list[num].dirty = false;
@ -246,10 +304,13 @@ int mips32_save_context(struct target *target)
/* get pointers to arch-specific information */
struct mips32_common *mips32 = target_to_mips32(target);
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
/* read core registers */
mips32_pracc_read_regs(ejtag_info, mips32->core_regs);
int retval = mips32_pracc_read_regs(mips32);
if (retval != ERROR_OK) {
LOG_ERROR("Could not read core registers from target");
return retval;
}
for (i = 0; i < MIPS32_NUM_REGS; i++) {
if (!mips32->core_cache->reg_list[i].valid)
@ -265,7 +326,6 @@ int mips32_restore_context(struct target *target)
/* get pointers to arch-specific information */
struct mips32_common *mips32 = target_to_mips32(target);
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
for (i = 0; i < MIPS32_NUM_REGS; i++) {
if (mips32->core_cache->reg_list[i].dirty)
@ -273,7 +333,7 @@ int mips32_restore_context(struct target *target)
}
/* write core regs */
mips32_pracc_write_regs(ejtag_info, mips32->core_regs);
mips32_pracc_write_regs(mips32);
return ERROR_OK;
}
@ -285,7 +345,7 @@ int mips32_arch_state(struct target *target)
LOG_USER("target halted in %s mode due to %s, pc: 0x%8.8" PRIx32 "",
mips_isa_strings[mips32->isa_mode],
debug_reason_name(target),
buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32));
buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32));
return ERROR_OK;
}
@ -322,25 +382,19 @@ struct reg_cache *mips32_build_reg_cache(struct target *target)
arch_info[i].mips32_common = mips32;
reg_list[i].name = mips32_regs[i].name;
reg_list[i].size = 32;
reg_list[i].size = mips32_regs[i].size ? 64 : 32;
if (mips32_regs[i].flag == MIPS32_GDB_DUMMY_FP_REG) {
reg_list[i].value = mips32_gdb_dummy_fp_value;
reg_list[i].valid = true;
reg_list[i].arch_info = NULL;
register_init_dummy(&reg_list[i]);
} else {
reg_list[i].value = calloc(1, 4);
reg_list[i].valid = false;
reg_list[i].type = &mips32_reg_type;
reg_list[i].arch_info = &arch_info[i];
reg_list[i].value = mips32_regs[i].size ? calloc(1, 8) : calloc(1, 4);
reg_list[i].valid = false;
reg_list[i].type = &mips32_reg_type;
reg_list[i].arch_info = &arch_info[i];
reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
if (reg_list[i].reg_data_type)
reg_list[i].reg_data_type->type = mips32_regs[i].type;
else
LOG_ERROR("unable to allocate reg type list");
reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
if (reg_list[i].reg_data_type)
reg_list[i].reg_data_type->type = mips32_regs[i].type;
else
LOG_ERROR("unable to allocate reg type list");
}
reg_list[i].dirty = false;
@ -407,7 +461,7 @@ static int mips32_run_and_wait(struct target *target, target_addr_t entry_point,
return ERROR_TARGET_TIMEOUT;
}
pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32);
if (exit_point && (pc != exit_point)) {
LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 " ", pc);
return ERROR_TARGET_TIMEOUT;
@ -751,15 +805,82 @@ int mips32_cpu_probe(struct target *target)
return ERROR_OK;
}
/* reads dsp implementation info from CP0 Config3 register {DSPP, DSPREV}*/
void mips32_read_config_dsp(struct mips32_common *mips32, struct mips_ejtag *ejtag_info)
{
uint32_t dsp_present = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPP_MASK) >> MIPS32_CONFIG3_DSPP_SHIFT);
if (dsp_present) {
mips32->dsp_imp = ((ejtag_info->config[3] & MIPS32_CONFIG3_DSPREV_MASK) >> MIPS32_CONFIG3_DSPREV_SHIFT) + 1;
LOG_USER("DSP implemented: %s, rev %d", "yes", mips32->dsp_imp);
} else {
LOG_USER("DSP implemented: %s", "no");
}
}
/* read fpu implementation info from CP0 Config1 register {CU1, FP}*/
int mips32_read_config_fpu(struct mips32_common *mips32, struct mips_ejtag *ejtag_info)
{
int retval;
uint32_t fp_imp = (ejtag_info->config[1] & MIPS32_CONFIG1_FP_MASK) >> MIPS32_CONFIG1_FP_SHIFT;
char buf[60] = {0};
if (!fp_imp) {
LOG_USER("FPU implemented: %s", "no");
mips32->fp_imp = MIPS32_FP_IMP_NONE;
return ERROR_OK;
}
uint32_t status_value;
bool status_fr, status_cu1;
retval = mips32_cp0_read(ejtag_info, &status_value, MIPS32_C0_STATUS, 0);
if (retval != ERROR_OK) {
LOG_ERROR("Failed to read cp0 status register");
return retval;
}
status_fr = (status_value >> MIPS32_CP0_STATUS_FR_SHIFT) & 0x1;
status_cu1 = (status_value >> MIPS32_CP0_STATUS_CU1_SHIFT) & 0x1;
if (status_cu1) {
/* TODO: read fpu(cp1) config register for current operating mode.
* Now its set to 32 bits by default. */
snprintf(buf, sizeof(buf), "yes");
fp_imp = MIPS32_FP_IMP_32;
} else {
snprintf(buf, sizeof(buf), "yes, disabled");
fp_imp = MIPS32_FP_IMP_UNKNOWN;
}
mips32->fpu_in_64bit = status_fr;
mips32->fpu_enabled = status_cu1;
LOG_USER("FPU implemented: %s", buf);
mips32->fp_imp = fp_imp;
return ERROR_OK;
}
/* Checks if current target implements Common Device Memory Map and therefore Fast Debug Channel (MD00090) */
void mips32_read_config_fdc(struct mips32_common *mips32, struct mips_ejtag *ejtag_info, uint32_t dcr)
{
if (((ejtag_info->config[3] & MIPS32_CONFIG3_CDMM_MASK) != 0) && ((dcr & EJTAG_DCR_FDC) != 0)) {
mips32->fdc = 1;
mips32->semihosting = 1;
} else {
mips32->fdc = 0;
mips32->semihosting = 0;
}
}
/* read config to config3 cp0 registers and log isa implementation */
int mips32_read_config_regs(struct target *target)
{
struct mips32_common *mips32 = target_to_mips32(target);
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
char buf[60] = {0};
int retval;
if (ejtag_info->config_regs == 0)
for (int i = 0; i != 4; i++) {
int retval = mips32_cp0_read(ejtag_info, &ejtag_info->config[i], 16, i);
retval = mips32_cp0_read(ejtag_info, &ejtag_info->config[i], 16, i);
if (retval != ERROR_OK) {
LOG_ERROR("isa info not available, failed to read cp0 config register: %" PRId32, i);
ejtag_info->config_regs = 0;
@ -774,27 +895,56 @@ int mips32_read_config_regs(struct target *target)
LOG_DEBUG("read %"PRIu32" config registers", ejtag_info->config_regs);
mips32->isa_rel = (ejtag_info->config[0] & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT;
snprintf(buf, sizeof(buf), ", release %s(AR=%d)",
mips32->isa_rel == MIPS32_RELEASE_1 ? "1"
: mips32->isa_rel == MIPS32_RELEASE_2 ? "2"
: mips32->isa_rel == MIPS32_RELEASE_6 ? "6"
: "unknown", mips32->isa_rel);
if (ejtag_info->impcode & EJTAG_IMP_MIPS16) {
mips32->isa_imp = MIPS32_MIPS16;
LOG_USER("MIPS32 with MIPS16 support implemented");
LOG_USER("ISA implemented: %s%s", "MIPS32, MIPS16", buf);
} else if (ejtag_info->config_regs >= 4) { /* config3 implemented */
unsigned isa_imp = (ejtag_info->config[3] & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT;
if (isa_imp == 1) {
mips32->isa_imp = MMIPS32_ONLY;
LOG_USER("MICRO MIPS32 only implemented");
LOG_USER("ISA implemented: %s%s", "microMIPS32", buf);
} else if (isa_imp != 0) {
mips32->isa_imp = MIPS32_MMIPS32;
LOG_USER("MIPS32 and MICRO MIPS32 implemented");
LOG_USER("ISA implemented: %s%s", "MIPS32, microMIPS32", buf);
}
} else if (mips32->isa_imp == MIPS32_ONLY) {
/* initial default value */
LOG_USER("ISA implemented: %s%s", "MIPS32", buf);
}
if (mips32->isa_imp == MIPS32_ONLY) /* initial default value */
LOG_USER("MIPS32 only implemented");
/* Retrieve DSP info */
mips32_read_config_dsp(mips32, ejtag_info);
/* Retrieve if Float Point CoProcessor Implemented */
retval = mips32_read_config_fpu(mips32, ejtag_info);
if (retval != ERROR_OK) {
LOG_ERROR("fpu info is not available, error while reading cp0 status");
mips32->fp_imp = MIPS32_FP_IMP_NONE;
return retval;
}
uint32_t dcr;
retval = target_read_u32(target, EJTAG_DCR, &dcr);
if (retval != ERROR_OK) {
LOG_ERROR("failed to read EJTAG_DCR register");
return retval;
}
/* Determine if FDC and CDMM are implemented for this core */
mips32_read_config_fdc(mips32, ejtag_info, dcr);
return ERROR_OK;
}
int mips32_checksum_memory(struct target *target, target_addr_t address,
uint32_t count, uint32_t *checksum)
{

View File

@ -46,9 +46,21 @@
#define MIPS32_CONFIG0_AR_SHIFT 10
#define MIPS32_CONFIG0_AR_MASK (0x7 << MIPS32_CONFIG0_AR_SHIFT)
#define MIPS32_CONFIG1_FP_SHIFT 0
#define MIPS32_CONFIG1_FP_MASK BIT(MIPS32_CONFIG1_FP_SHIFT)
#define MIPS32_CONFIG1_DL_SHIFT 10
#define MIPS32_CONFIG1_DL_MASK (0x7 << MIPS32_CONFIG1_DL_SHIFT)
#define MIPS32_CONFIG3_CDMM_SHIFT 3
#define MIPS32_CONFIG3_CDMM_MASK BIT(MIPS32_CONFIG3_CDMM_SHIFT)
#define MIPS32_CONFIG3_DSPP_SHIFT 10
#define MIPS32_CONFIG3_DSPP_MASK BIT(MIPS32_CONFIG3_DSPP_SHIFT)
#define MIPS32_CONFIG3_DSPREV_SHIFT 11
#define MIPS32_CONFIG3_DSPREV_MASK BIT(MIPS32_CONFIG3_DSPREV_SHIFT)
#define MIPS32_CONFIG3_ISA_SHIFT 14
#define MIPS32_CONFIG3_ISA_MASK (3 << MIPS32_CONFIG3_ISA_SHIFT)
@ -57,6 +69,141 @@
#define MIPS32_SCAN_DELAY_LEGACY_MODE 2000000
#define MIPS32_NUM_DSPREGS 9
/* Bit Mask indicating CP0 register supported by this core */
#define MIPS_CP0_MK4 0x0001
#define MIPS_CP0_MAPTIV_UC 0x0002
#define MIPS_CP0_MAPTIV_UP 0x0004
#define MIPS_CP0_IAPTIV 0x0008
/* CP0 Status register fields */
#define MIPS32_CP0_STATUS_FR_SHIFT 26
#define MIPS32_CP0_STATUS_CU1_SHIFT 29
/* CP1 FIR register fields */
#define MIPS32_CP1_FIR_F64_SHIFT 22
static const struct {
unsigned int reg;
unsigned int sel;
const char *name;
const unsigned int core;
} mips32_cp0_regs[] = {
{0, 0, "index", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
{0, 1, "mvpcontrol", MIPS_CP0_IAPTIV},
{0, 2, "mvpconf0", MIPS_CP0_IAPTIV},
{0, 3, "mvpconf1", MIPS_CP0_IAPTIV},
{1, 0, "random", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
{1, 1, "vpecontrol", MIPS_CP0_IAPTIV},
{1, 2, "vpeconf0", MIPS_CP0_IAPTIV},
{1, 3, "vpeconf1", MIPS_CP0_IAPTIV},
{1, 4, "yqmask", MIPS_CP0_IAPTIV},
{1, 5, "vpeschedule", MIPS_CP0_IAPTIV},
{1, 6, "vpeschefback", MIPS_CP0_IAPTIV},
{1, 7, "vpeopt", MIPS_CP0_IAPTIV},
{2, 0, "entrylo0", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
{2, 1, "tcstatus", MIPS_CP0_IAPTIV},
{2, 2, "tcbind", MIPS_CP0_IAPTIV},
{2, 3, "tcrestart", MIPS_CP0_IAPTIV},
{2, 4, "tchalt", MIPS_CP0_IAPTIV},
{2, 5, "tccontext", MIPS_CP0_IAPTIV},
{2, 6, "tcschedule", MIPS_CP0_IAPTIV},
{2, 7, "tcschefback", MIPS_CP0_IAPTIV},
{3, 0, "entrylo1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
{3, 7, "tcopt", MIPS_CP0_IAPTIV},
{4, 0, "context", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
{4, 2, "userlocal", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{5, 0, "pagemask", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
{5, 1, "pagegrain", MIPS_CP0_MAPTIV_UP},
{5, 2, "segctl0", MIPS_CP0_IAPTIV},
{5, 3, "segctl1", MIPS_CP0_IAPTIV},
{5, 4, "segctl2", MIPS_CP0_IAPTIV},
{6, 0, "wired", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
{6, 1, "srsconf0", MIPS_CP0_IAPTIV},
{6, 2, "srsconf1", MIPS_CP0_IAPTIV},
{6, 3, "srsconf2", MIPS_CP0_IAPTIV},
{6, 4, "srsconf3", MIPS_CP0_IAPTIV},
{6, 5, "srsconf4", MIPS_CP0_IAPTIV},
{7, 0, "hwrena", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{8, 0, "badvaddr", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{8, 1, "badinstr", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP},
{8, 2, "badinstrp", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP},
{9, 0, "count", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{10, 0, "entryhi", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP},
{10, 4, "guestctl1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MK4},
{10, 5, "guestctl2", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MK4},
{10, 6, "guestctl3", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MK4},
{11, 0, "compare", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{11, 4, "guestctl0ext", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MK4},
{12, 0, "status", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{12, 1, "intctl", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{12, 2, "srsctl", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{12, 3, "srsmap", MIPS_CP0_IAPTIV},
{12, 3, "srsmap1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP},
{12, 4, "view_ipl", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{12, 5, "srsmap2", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP},
{12, 6, "guestctl0", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MK4},
{12, 7, "gtoffset", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MK4},
{13, 0, "cause", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{13, 5, "nestedexc", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{14, 0, "epc", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{14, 2, "nestedepc", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{15, 0, "prid", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{15, 1, "ebase", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{15, 2, "cdmmbase", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{15, 3, "cmgcrbase", MIPS_CP0_IAPTIV},
{16, 0, "config", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{16, 1, "config1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{16, 2, "config2", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{16, 3, "config3", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{16, 4, "config4", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{16, 5, "config5", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{16, 7, "config7", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{17, 0, "lladdr", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{18, 0, "watchlo0", MIPS_CP0_IAPTIV},
{18, 1, "watchlo1", MIPS_CP0_IAPTIV},
{18, 2, "watchlo2", MIPS_CP0_IAPTIV},
{18, 3, "watchlo3", MIPS_CP0_IAPTIV},
{19, 0, "watchhi0", MIPS_CP0_IAPTIV},
{19, 1, "watchhi1", MIPS_CP0_IAPTIV},
{19, 2, "watchhi2", MIPS_CP0_IAPTIV},
{19, 3, "watchhi3", MIPS_CP0_IAPTIV},
{23, 0, "debug", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{23, 1, "tracecontrol", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{23, 2, "tracecontrol2", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{23, 3, "usertracedata1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{23, 4, "tracebpc", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{23, 4, "traceibpc", MIPS_CP0_IAPTIV},
{23, 5, "tracedbpc", MIPS_CP0_IAPTIV},
{24, 0, "depc", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{24, 2, "tracecontrol3", MIPS_CP0_IAPTIV},
{24, 3, "usertracedata2", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{25, 0, "perfctl0", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{25, 1, "perfcnt0", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{25, 2, "perfctl1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{25, 3, "perfcnt1", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{26, 0, "errctl", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{27, 0, "cacheerr", MIPS_CP0_IAPTIV},
{28, 0, "itaglo", MIPS_CP0_IAPTIV},
{28, 0, "taglo", MIPS_CP0_IAPTIV},
{28, 1, "idatalo", MIPS_CP0_IAPTIV},
{28, 1, "datalo", MIPS_CP0_IAPTIV},
{28, 2, "dtaglo", MIPS_CP0_IAPTIV},
{28, 3, "ddatalo", MIPS_CP0_IAPTIV},
{28, 4, "l23taglo", MIPS_CP0_IAPTIV},
{28, 5, "l23datalo", MIPS_CP0_IAPTIV},
{29, 1, "idatahi", MIPS_CP0_IAPTIV},
{29, 2, "dtaghi", MIPS_CP0_IAPTIV},
{29, 5, "l23datahi", MIPS_CP0_IAPTIV},
{30, 0, "errorepc", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{31, 0, "desave", MIPS_CP0_IAPTIV | MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP | MIPS_CP0_MK4},
{31, 2, "kscratch1", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP},
{31, 3, "kscratch2", MIPS_CP0_MAPTIV_UC | MIPS_CP0_MAPTIV_UP},
};
#define MIPS32NUMCP0REGS ((int)ARRAY_SIZE(mips32_cp0_regs))
/* Insert extra NOPs after the DRET instruction on exit from debug. */
#define EJTAG_QUIRK_PAD_DRET BIT(0)
@ -67,6 +214,30 @@ enum {
MIPS32NUMCOREREGS
};
/* offsets into mips32 core register cache */
#define MIPS32_REG_GP_COUNT 34
#define MIPS32_REG_FP_COUNT 32
#define MIPS32_REG_FPC_COUNT 2
#define MIPS32_REG_C0_COUNT 5
#define MIPS32_REGLIST_GP_INDEX 0
#define MIPS32_REGLIST_FP_INDEX (MIPS32_REGLIST_GP_INDEX + MIPS32_REG_GP_COUNT)
#define MIPS32_REGLIST_FPC_INDEX (MIPS32_REGLIST_FP_INDEX + MIPS32_REG_FP_COUNT)
#define MIPS32_REGLIST_C0_INDEX (MIPS32_REGLIST_FPC_INDEX + MIPS32_REG_FPC_COUNT)
#define MIPS32_REGLIST_C0_STATUS_INDEX (MIPS32_REGLIST_C0_INDEX + 0)
#define MIPS32_REGLIST_C0_BADVADDR_INDEX (MIPS32_REGLIST_C0_INDEX + 1)
#define MIPS32_REGLIST_C0_CAUSE_INDEX (MIPS32_REGLIST_C0_INDEX + 2)
#define MIPS32_REGLIST_C0_PC_INDEX (MIPS32_REGLIST_C0_INDEX + 3)
#define MIPS32_REGLIST_C0_GUESTCTL1_INDEX (MIPS32_REGLIST_C0_INDEX + 4)
#define MIPS32_REG_C0_STATUS_INDEX 0
#define MIPS32_REG_C0_BADVADDR_INDEX 1
#define MIPS32_REG_C0_CAUSE_INDEX 2
#define MIPS32_REG_C0_PC_INDEX 3
#define MIPS32_REG_C0_GUESTCTL1_INDEX 4
enum mips32_isa_mode {
MIPS32_ISA_MIPS32 = 0,
MIPS32_ISA_MIPS16E = 1,
@ -80,21 +251,67 @@ enum mips32_isa_imp {
MIPS32_MMIPS32 = 3,
};
/* Release 2~5 does not have much change regarding to the ISA under User mode,
* therefore no new Architecture Revision(AR) level is assigned to them.
* Release 6 changed some instruction's encoding/mnemonic, removed instructions that
* has lost its purposes/none are using, and added some new instructions as well.
*/
enum mips32_isa_rel {
MIPS32_RELEASE_1 = 0,
MIPS32_RELEASE_2 = 1,
MIPS32_RELEASE_6 = 2,
MIPS32_RELEASE_UNKNOWN,
};
enum mips32_fp_imp {
MIPS32_FP_IMP_NONE = 0,
MIPS32_FP_IMP_32 = 1,
MIPS32_FP_IMP_64 = 2,
MIPS32_FP_IMP_UNKNOWN = 3,
};
enum mips32_dsp_imp {
MIPS32_DSP_IMP_NONE = 0,
MIPS32_DSP_IMP_REV1 = 1,
MIPS32_DSP_IMP_REV2 = 2,
};
struct mips32_comparator {
int used;
uint32_t bp_value;
uint32_t reg_address;
};
struct mips32_core_regs {
uint32_t gpr[MIPS32_REG_GP_COUNT];
uint64_t fpr[MIPS32_REG_FP_COUNT];
uint32_t fpcr[MIPS32_REG_FPC_COUNT];
uint32_t cp0[MIPS32_REG_C0_COUNT];
};
struct mips32_common {
unsigned int common_magic;
void *arch_info;
struct reg_cache *core_cache;
struct mips_ejtag ejtag_info;
uint32_t core_regs[MIPS32NUMCOREREGS];
struct mips32_core_regs core_regs;
enum mips32_isa_mode isa_mode;
enum mips32_isa_imp isa_imp;
enum mips32_isa_rel isa_rel;
enum mips32_fp_imp fp_imp;
enum mips32_dsp_imp dsp_imp;
int fdc;
int semihosting;
uint32_t cp0_mask;
/* FPU enabled (cp0.status.cu1) */
bool fpu_enabled;
/* FPU mode (cp0.status.fr) */
bool fpu_in_64bit;
/* processor identification register */
uint32_t prid;
@ -394,6 +611,173 @@ struct mips32_algorithm {
#define MIPS16_SDBBP(isa) (isa ? MMIPS16_SDBBP : MIPS16_ISA_SDBBP)
/*
* MIPS32 Config1 Register (CP0 Register 16, Select 1)
*/
#define MIPS32_CFG1_M 0x80000000 /* Config2 implemented */
#define MIPS32_CFG1_MMUSMASK 0x7e000000 /* mmu size - 1 */
#define MIPS32_CFG1_MMUSSHIFT 25
#define MIPS32_CFG1_ISMASK 0x01c00000 /* icache lines 64<<n */
#define MIPS32_CFG1_ISSHIFT 22
#define MIPS32_CFG1_ILMASK 0x00380000 /* icache line size 2<<n */
#define MIPS32_CFG1_ILSHIFT 19
#define MIPS32_CFG1_IAMASK 0x00070000 /* icache ways - 1 */
#define MIPS32_CFG1_IASHIFT 16
#define MIPS32_CFG1_DSMASK 0x0000e000 /* dcache lines 64<<n */
#define MIPS32_CFG1_DSSHIFT 13
#define MIPS32_CFG1_DLMASK 0x00001c00 /* dcache line size 2<<n */
#define MIPS32_CFG1_DLSHIFT 10
#define MIPS32_CFG1_DAMASK 0x00000380 /* dcache ways - 1 */
#define MIPS32_CFG1_DASHIFT 7
#define MIPS32_CFG1_C2 0x00000040 /* Coprocessor 2 present */
#define MIPS32_CFG1_MD 0x00000020 /* MDMX implemented */
#define MIPS32_CFG1_PC 0x00000010 /* performance counters implemented */
#define MIPS32_CFG1_WR 0x00000008 /* watch registers implemented */
#define MIPS32_CFG1_CA 0x00000004 /* compression (mips16) implemented */
#define MIPS32_CFG1_EP 0x00000002 /* ejtag implemented */
#define MIPS32_CFG1_FP 0x00000001 /* fpu implemented */
/*
* MIPS32 Coprocessor 0 register numbers
*/
#define MIPS32_C0_INDEX 0
#define MIPS32_C0_INX 0
#define MIPS32_C0_RANDOM 1
#define MIPS32_C0_RAND 1
#define MIPS32_C0_ENTRYLO0 2
#define MIPS32_C0_TLBLO0 2
#define MIPS32_C0_ENTRYLO1 3
#define MIPS32_C0_TLBLO1 3
#define MIPS32_C0_CONTEXT 4
#define MIPS32_C0_CTXT 4
#define MIPS32_C0_PAGEMASK 5
#define MIPS32_C0_PAGEGRAIN (5, 1)
#define MIPS32_C0_WIRED 6
#define MIPS32_C0_HWRENA 7
#define MIPS32_C0_BADVADDR 8
#define MIPS32_C0_VADDR 8
#define MIPS32_C0_COUNT 9
#define MIPS32_C0_ENTRYHI 10
#define MIPS32_C0_TLBHI 10
#define MIPS32_C0_GUESTCTL1 10
#define MIPS32_C0_COMPARE 11
#define MIPS32_C0_STATUS 12
#define MIPS32_C0_SR 12
#define MIPS32_C0_INTCTL (12, 1)
#define MIPS32_C0_SRSCTL (12, 2)
#define MIPS32_C0_SRSMAP (12, 3)
#define MIPS32_C0_CAUSE 13
#define MIPS32_C0_CR 13
#define MIPS32_C0_EPC 14
#define MIPS32_C0_PRID 15
#define MIPS32_C0_EBASE (15, 1)
#define MIPS32_C0_CONFIG 16
#define MIPS32_C0_CONFIG0 (16, 0)
#define MIPS32_C0_CONFIG1 (16, 1)
#define MIPS32_C0_CONFIG2 (16, 2)
#define MIPS32_C0_CONFIG3 (16, 3)
#define MIPS32_C0_LLADDR 17
#define MIPS32_C0_WATCHLO 18
#define MIPS32_C0_WATCHHI 19
#define MIPS32_C0_DEBUG 23
#define MIPS32_C0_DEPC 24
#define MIPS32_C0_PERFCNT 25
#define MIPS32_C0_ERRCTL 26
#define MIPS32_C0_CACHEERR 27
#define MIPS32_C0_TAGLO 28
#define MIPS32_C0_ITAGLO 28
#define MIPS32_C0_DTAGLO (28, 2)
#define MIPS32_C0_TAGLO2 (28, 4)
#define MIPS32_C0_DATALO (28, 1)
#define MIPS32_C0_IDATALO (28, 1)
#define MIPS32_C0_DDATALO (28, 3)
#define MIPS32_C0_DATALO2 (28, 5)
#define MIPS32_C0_TAGHI 29
#define MIPS32_C0_ITAGHI 29
#define MIPS32_C0_DATAHI (29, 1)
#define MIPS32_C0_ERRPC 30
#define MIPS32_C0_DESAVE 31
/*
* MIPS32 MMU types
*/
#define MIPS32_MMU_TLB 1
#define MIPS32_MMU_BAT 2
#define MIPS32_MMU_FIXED 3
#define MIPS32_MMU_DUAL_VTLB_FTLB 4
enum mips32_cpu_vendor {
MIPS32_CPU_VENDOR_MTI,
MIPS32_CPU_VENDOR_ALCHEMY,
MIPS32_CPU_VENDOR_BROADCOM,
MIPS32_CPU_VENDOR_ALTERA,
MIPS32_CPU_VENDOR_LEXRA,
};
enum mips32_isa_supported {
MIPS16,
MIPS32,
MIPS64,
MICROMIPS_ONLY,
MIPS32_AT_RESET_AND_MICROMIPS,
MICROMIPS_AT_RESET_AND_MIPS32,
};
struct mips32_cpu_features {
/* Type of CPU (4Kc, 24Kf, etc.) */
uint32_t cpu_core;
/* Internal representation of cpu type */
uint32_t cpu_type;
/* Processor vendor */
enum mips32_cpu_vendor vendor;
/* Supported ISA and boot config */
enum mips32_isa_supported isa;
/* PRID */
uint32_t prid;
/* Processor implemented the MultiThreading ASE */
bool mtase;
/* Processor implemented the DSP ASE */
bool dspase;
/* Processor implemented the SmartMIPS ASE */
bool smase;
/* Processor implemented the MIPS16[e] ASE */
bool m16ase;
/* Processor implemented the microMIPS ASE */
bool micromipsase;
/* Processor implemented the Virtualization ASE */
uint32_t vzase;
uint32_t vz_guest_id_width;
/* ebase.cpuid number */
uint32_t cpuid;
uint32_t inst_cache_size;
uint32_t data_cache_size;
uint32_t mmu_type;
uint32_t tlb_entries;
uint32_t num_shadow_regs;
/* Processor implemented the MSA module */
bool msa;
/* Processor implemented mfhc0 and mthc0 instructions */
bool mvh;
bool guest_ctl1_present;
bool cdmm;
};
extern const struct command_registration mips32_command_handlers[];
int mips32_arch_state(struct target *target);

View File

@ -823,9 +823,13 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int siz
return retval;
}
int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
int mips32_pracc_write_regs(struct mips32_common *mips32)
{
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
uint32_t *gprs = mips32->core_regs.gpr;
uint32_t *c0rs = mips32->core_regs.cp0;
pracc_queue_init(&ctx);
uint32_t cp0_write_code[] = {
@ -837,66 +841,178 @@ int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
MIPS32_MTC0(ctx.isa, 1, 24, 0), /* move $1 to depc (pc) */
};
uint32_t cp0_write_data[] = {
/* lo */
gprs[32],
/* hi */
gprs[33],
/* status */
c0rs[0],
/* badvaddr */
c0rs[1],
/* cause */
c0rs[2],
/* depc (pc) */
c0rs[3],
};
for (size_t i = 0; i < ARRAY_SIZE(cp0_write_code); i++) {
/* load CP0 value in $1 */
pracc_add_li32(&ctx, 1, cp0_write_data[i], 0);
/* write value from $1 to CP0 register */
pracc_add(&ctx, 0, cp0_write_code[i]);
}
/* load registers 2 to 31 with li32, optimize */
for (int i = 2; i < 32; i++)
pracc_add_li32(&ctx, i, regs[i], 1);
pracc_add_li32(&ctx, i, gprs[i], 1);
for (int i = 0; i != 6; i++) {
pracc_add_li32(&ctx, 1, regs[i + 32], 0); /* load CPO value in $1 */
pracc_add(&ctx, 0, cp0_write_code[i]); /* write value from $1 to CPO register */
}
pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0)); /* load $15 in DeSave */
pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 1, UPPER16((regs[1])))); /* load upper half word in $1 */
pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 1, 1, LOWER16((regs[1])))); /* load lower half word in $1 */
/* load $15 in DeSave */
pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0));
/* load upper half word in $1 */
pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 1, UPPER16((gprs[1]))));
/* jump to start */
pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));
/* load lower half word in $1 */
pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 1, 1, LOWER16((gprs[1]))));
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1);
ejtag_info->reg8 = regs[8];
ejtag_info->reg9 = regs[9];
ejtag_info->reg8 = gprs[8];
ejtag_info->reg9 = gprs[9];
pracc_queue_free(&ctx);
return ctx.retval;
}
int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs)
/* Saves content in `$1` to `DeSave(cp0.31.0)` and loads `MIPS32_PRACC_BASE_ADDR` into `$1` */
static void mips32_pracc_store_regs_set_base_addr(struct pracc_queue_info *ctx)
{
struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
pracc_queue_init(&ctx);
/* move $1 to COP0 DeSave */
pracc_add(ctx, 0, MIPS32_MTC0(ctx->isa, 1, 31, 0));
/* $1 = MIP32_PRACC_BASE_ADDR */
pracc_add(ctx, 0, MIPS32_LUI(ctx->isa, 1, PRACC_UPPER_BASE_ADDR));
}
uint32_t cp0_read_code[] = {
MIPS32_MFC0(ctx.isa, 8, 12, 0), /* move status to $8 */
MIPS32_MFLO(ctx.isa, 8), /* move lo to $8 */
MIPS32_MFHI(ctx.isa, 8), /* move hi to $8 */
MIPS32_MFC0(ctx.isa, 8, 8, 0), /* move badvaddr to $8 */
MIPS32_MFC0(ctx.isa, 8, 13, 0), /* move cause to $8 */
MIPS32_MFC0(ctx.isa, 8, 24, 0), /* move depc (pc) to $8 */
/* This function assumes the address for saving is stored in `$1`.
* And that action is performed in `mips32_pracc_set_save_base_addr`.
*/
static void mips32_pracc_store_regs_gpr(struct pracc_queue_info *ctx, unsigned int offset_gpr)
{
for (int i = 2; i != 32; i++)
pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + offset_gpr + (i * 4),
MIPS32_SW(ctx->isa, i, PRACC_OUT_OFFSET + offset_gpr + (i * 4), 1));
}
static void mips32_pracc_store_regs_lohi(struct pracc_queue_info *ctx)
{
uint32_t lohi_read_code[] = {
MIPS32_MFLO(ctx->isa, 8), /* move lo to $8 */
MIPS32_MFHI(ctx->isa, 8), /* move hi to $8 */
};
pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 1, 31, 0)); /* move $1 to COP0 DeSave */
pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 1, PRACC_UPPER_BASE_ADDR)); /* $1 = MIP32_PRACC_BASE_ADDR */
for (int i = 2; i != 32; i++) /* store GPR's 2 to 31 */
pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i * 4),
MIPS32_SW(ctx.isa, i, PRACC_OUT_OFFSET + (i * 4), 1));
for (int i = 0; i != 6; i++) {
pracc_add(&ctx, 0, cp0_read_code[i]); /* load COP0 needed registers to $8 */
pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i + 32) * 4, /* store $8 at PARAM OUT */
MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + (i + 32) * 4, 1));
/* store lo & hi */
for (int i = 0; i < 2; i++) {
/* load COP0 needed registers to $8 */
pracc_add(ctx, 0, lohi_read_code[i]);
/* store $8 at PARAM OUT */
pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + (i + 32) * 4,
MIPS32_SW(ctx->isa, 8, PRACC_OUT_OFFSET + (i + 32) * 4, 1));
}
pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 8, 31, 0)); /* move DeSave to $8, reg1 value */
pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + 4, /* store reg1 value from $8 to param out */
MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + 4, 1));
}
pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 1, 31, 0)); /* move COP0 DeSave to $1, restore reg1 */
pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */
pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0)); /* load $15 in DeSave */
/* Saves CP0 registers [status, badvaddr, cause, depc] */
static void mips32_pracc_store_regs_cp0_context(struct pracc_queue_info *ctx, unsigned int offset_cp0)
{
uint32_t cp0_read_code[] = {
MIPS32_MFC0(ctx->isa, 8, 12, 0), /* move status to $8 */
MIPS32_MFC0(ctx->isa, 8, 8, 0), /* move badvaddr to $8 */
MIPS32_MFC0(ctx->isa, 8, 13, 0), /* move cause to $8 */
MIPS32_MFC0(ctx->isa, 8, 24, 0), /* move depc (pc) to $8 */
};
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, regs, 1);
/* store cp0 */
for (size_t i = 0; i < ARRAY_SIZE(cp0_read_code); i++) {
size_t offset = offset_cp0 + (i * 4);
/* load COP0 needed registers to $8 */
pracc_add(ctx, 0, cp0_read_code[i]);
/* store $8 at PARAM OUT */
pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + offset,
MIPS32_SW(ctx->isa, 8, PRACC_OUT_OFFSET + offset, 1));
}
}
/* Loads original content of $1 into $8,
* then store it to the batch data access address.
* Finally it restores $1 from DeSave.
*/
static void mips32_pracc_store_regs_restore(struct pracc_queue_info *ctx)
{
/* move DeSave to $8, reg1 value */
pracc_add(ctx, 0, MIPS32_MFC0(ctx->isa, 8, 31, 0));
/* store reg1 value from $8 to param out */
pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + 4,
MIPS32_SW(ctx->isa, 8, PRACC_OUT_OFFSET + 4, 1));
/* move COP0 DeSave to $1, restore reg1 */
pracc_add(ctx, 0, MIPS32_MFC0(ctx->isa, 1, 31, 0));
}
/* This function performs following actions:
* Saves `$1` to `DeSave`,
* then load `PRACC_UPPER_BASE_ADDR` for saving the register data structure into `$1`,
* Saves `$2` ~ `$31` to `PRACC_UPPER_BASE_ADDR + offset_gpr`
* Saves HI and LO,
* Saves necessary cp0 registers.
*/
static void mips32_pracc_store_regs(struct pracc_queue_info *ctx,
unsigned int offset_gpr, unsigned int offset_cp0)
{
mips32_pracc_store_regs_set_base_addr(ctx);
mips32_pracc_store_regs_gpr(ctx, offset_gpr);
mips32_pracc_store_regs_lohi(ctx);
mips32_pracc_store_regs_cp0_context(ctx, offset_cp0);
mips32_pracc_store_regs_restore(ctx);
}
int mips32_pracc_read_regs(struct mips32_common *mips32)
{
struct mips_ejtag *ejtag_info = &mips32->ejtag_info;
struct pracc_queue_info ctx = {.ejtag_info = ejtag_info};
struct mips32_core_regs *core_regs = &mips32->core_regs;
unsigned int offset_gpr = ((uint8_t *)&core_regs->gpr[0]) - (uint8_t *)core_regs;
unsigned int offset_cp0 = ((uint8_t *)&core_regs->cp0[0]) - (uint8_t *)core_regs;
/*
* This procedure has to be in 2 distinctive steps, because we can
* only know whether FP is enabled after reading CP0.
*
* Step 1: Read everything except CP1 stuff
* Step 2: Read CP1 stuff if FP is implemented
*/
pracc_queue_init(&ctx);
mips32_pracc_store_regs(&ctx, offset_gpr, offset_cp0);
/* jump to start */
pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa)));
/* load $15 in DeSave */
pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0));
ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, (uint32_t *)&mips32->core_regs, 1);
ejtag_info->reg8 = regs[8]; /* reg8 is saved but not restored, next called function should restore it */
ejtag_info->reg9 = regs[9];
pracc_queue_free(&ctx);
/* reg8 is saved but not restored, next called function should restore it */
ejtag_info->reg8 = mips32->core_regs.gpr[8];
ejtag_info->reg9 = mips32->core_regs.gpr[9];
/* we only care if FP is actually impl'd and if cp1 is enabled */
/* since we already read cp0 in the prev step */
/* now we know what's in cp0.status */
/* TODO: Read FPRs */
return ctx.retval;
}

View File

@ -36,6 +36,8 @@
#define PRACC_BLOCK 128 /* 1 Kbyte */
struct mips32_common;
struct pa_list {
uint32_t instr;
uint32_t addr;
@ -64,8 +66,8 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info,
int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source,
int write_t, uint32_t addr, int count, uint32_t *buf);
int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs);
int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs);
int mips32_pracc_read_regs(struct mips32_common *mips32);
int mips32_pracc_write_regs(struct mips32_common *mips32);
/**
* \b mips32_cp0_read

View File

@ -123,11 +123,12 @@
/* Debug Control Register DCR */
#define EJTAG_DCR 0xFF300000
#define EJTAG_DCR_ENM (1 << 29)
#define EJTAG_DCR_DB (1 << 17)
#define EJTAG_DCR_IB (1 << 16)
#define EJTAG_DCR_INTE (1 << 4)
#define EJTAG_DCR_MP (1 << 2)
#define EJTAG_DCR_ENM BIT(29)
#define EJTAG_DCR_FDC BIT(18)
#define EJTAG_DCR_DB BIT(17)
#define EJTAG_DCR_IB BIT(16)
#define EJTAG_DCR_INTE BIT(4)
#define EJTAG_DCR_MP BIT(2)
/* breakpoint support */
/* EJTAG_V20_* was tested on Broadcom BCM7401

View File

@ -108,11 +108,11 @@ static int mips_m4k_debug_entry(struct target *target)
mips32->isa_mode = MIPS32_ISA_MIPS32;
/* other than mips32 only and isa bit set ? */
if (mips32->isa_imp && buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1))
if (mips32->isa_imp && buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 1))
mips32->isa_mode = mips32->isa_imp == 2 ? MIPS32_ISA_MIPS16E : MIPS32_ISA_MMIPS32;
LOG_DEBUG("entered debug state at PC 0x%" PRIx32 ", target->state: %s",
buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32),
buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32),
target_state_name(target));
return ERROR_OK;
@ -443,18 +443,18 @@ static int mips_m4k_internal_restore(struct target *target, int current,
/* current = 1: continue on current pc, otherwise continue at <address> */
if (!current) {
mips_m4k_isa_filter(mips32->isa_imp, &address);
buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
mips32->core_cache->reg_list[MIPS32_PC].dirty = true;
mips32->core_cache->reg_list[MIPS32_PC].valid = true;
buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32, address);
mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].dirty = true;
mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].valid = true;
}
if ((mips32->isa_imp > 1) && debug_execution) /* if more than one isa supported */
buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1, mips32->isa_mode);
buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 1, mips32->isa_mode);
if (!current)
resume_pc = address;
else
resume_pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32);
resume_pc = buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32);
mips32_restore_context(target);
@ -537,15 +537,15 @@ static int mips_m4k_step(struct target *target, int current,
/* current = 1: continue on current pc, otherwise continue at <address> */
if (!current) {
mips_m4k_isa_filter(mips32->isa_imp, &address);
buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address);
mips32->core_cache->reg_list[MIPS32_PC].dirty = true;
mips32->core_cache->reg_list[MIPS32_PC].valid = true;
buf_set_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32, address);
mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].dirty = true;
mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].valid = true;
}
/* the front-end may request us not to handle breakpoints */
if (handle_breakpoints) {
breakpoint = breakpoint_find(target,
buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32));
buf_get_u32(mips32->core_cache->reg_list[MIPS32_REGLIST_C0_PC_INDEX].value, 0, 32));
if (breakpoint)
mips_m4k_unset_breakpoint(target, breakpoint);
}

View File

@ -3053,6 +3053,10 @@ COMMAND_HANDLER(handle_reg_command)
LOG_DEBUG("-");
struct target *target = get_current_target(CMD_CTX);
if (!target_was_examined(target)) {
LOG_ERROR("Target not examined yet");
return ERROR_TARGET_NOT_EXAMINED;
}
struct reg *reg = NULL;
/* list all available registers for the current target */
@ -3136,9 +3140,9 @@ COMMAND_HANDLER(handle_reg_command)
if ((CMD_ARGC == 1) || ((CMD_ARGC == 2) && !((CMD_ARGV[1][0] >= '0')
&& (CMD_ARGV[1][0] <= '9')))) {
if ((CMD_ARGC == 2) && (strcmp(CMD_ARGV[1], "force") == 0))
reg->valid = 0;
reg->valid = false;
if (reg->valid == 0) {
if (!reg->valid) {
int retval = reg->type->get(reg);
if (retval != ERROR_OK) {
LOG_ERROR("Could not read register '%s'", reg->name);
@ -4071,13 +4075,14 @@ COMMAND_HANDLER(handle_wp_command)
struct watchpoint *watchpoint = target->watchpoints;
while (watchpoint) {
char wp_type = (watchpoint->rw == WPT_READ ? 'r' : (watchpoint->rw == WPT_WRITE ? 'w' : 'a'));
command_print(CMD, "address: " TARGET_ADDR_FMT
", len: 0x%8.8" PRIx32
", r/w/a: %i, value: 0x%8.8" PRIx64
", r/w/a: %c, value: 0x%8.8" PRIx64
", mask: 0x%8.8" PRIx64,
watchpoint->address,
watchpoint->length,
(int)watchpoint->rw,
wp_type,
watchpoint->value,
watchpoint->mask);
watchpoint = watchpoint->next;
@ -5146,7 +5151,7 @@ static int target_jim_get_reg(Jim_Interp *interp, int argc,
return JIM_ERR;
}
if (force) {
if (force || !reg->valid) {
int retval = reg->type->get(reg);
if (retval != ERROR_OK) {

View File

@ -0,0 +1,23 @@
# SPDX-License-Identifier: GPL-2.0-or-later
#
# configuration file for Advantech IMX8QM DMSSE20
#
# only JTAG supported
transport select jtag
# set a safe JTAG clock speed, can be overridden
adapter speed 1000
# default JTAG configuration has only SRST and no TRST
reset_config srst_only srst_push_pull
# delay after SRST goes inactive
adapter srst delay 70
# board has an i.MX8QM with 4 Cortex-A53 cores and 2 Cortex-A72
set CHIPNAME imx8qm
set CHIPCORES 6
# source SoC configuration
source [find tcl/target/imx8qm.cfg]

View File

@ -77,6 +77,7 @@ bNumInterfaces
idProduct
idVendor
iInterface
iManufacturer
iProduct
iSerialNumber
wMaxPacketSize