Add target_data_bits().
authorTim Newsome <tim@sifive.com>
Thu, 13 May 2021 23:38:51 +0000 (16:38 -0700)
committerAntonio Borneo <borneo.antonio@gmail.com>
Fri, 4 Jun 2021 16:45:58 +0000 (17:45 +0100)
This is used to compute memory block read alignment, and specifically
allows 64-bit targets to ensure that memory block reads are only
requested on 64-bit boundaries.

Signed-off-by: Tim Newsome <tim@sifive.com>
Change-Id: Idb1a27b9fc02c46245556bb0f3d6d94b368c4817
Reviewed-on: http://openocd.zylin.com/6249
Reviewed-by: Marc Schink <dev@zapb.de>
Tested-by: jenkins
Reviewed-by: Jan Matyas <matyas@codasip.com>
Reviewed-by: Xiang W <wxjstz@126.com>
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
src/target/riscv/riscv.c
src/target/target.c
src/target/target.h
src/target/target_type.h

index fa07fe8213418197b882c8e9f236ff480dfce9a0..50535e2668393cf191514d6b91df2500caada29e 100644 (file)
@@ -2813,6 +2813,14 @@ static unsigned riscv_xlen_nonconst(struct target *target)
        return riscv_xlen(target);
 }
 
+static unsigned int riscv_data_bits(struct target *target)
+{
+       RISCV_INFO(r);
+       if (r->data_bits)
+               return r->data_bits(target);
+       return riscv_xlen(target);
+}
+
 struct target_type riscv_target = {
        .name = "riscv",
 
@@ -2857,6 +2865,7 @@ struct target_type riscv_target = {
        .commands = riscv_command_handlers,
 
        .address_bits = riscv_xlen_nonconst,
+       .data_bits = riscv_data_bits
 };
 
 /*** RISC-V Interface ***/
index 39a07ad6ce00dc8df1a20ebfa722cd0124751a2b..63f68ebabe8efd88d098e77cbed487b25d1a4b15 100644 (file)
@@ -1506,6 +1506,13 @@ unsigned target_address_bits(struct target *target)
        return 32;
 }
 
+unsigned int target_data_bits(struct target *target)
+{
+       if (target->type->data_bits)
+               return target->type->data_bits(target);
+       return 32;
+}
+
 static int target_profiling(struct target *target, uint32_t *samples,
                        uint32_t max_num_samples, uint32_t *num_samples, uint32_t seconds)
 {
@@ -2402,10 +2409,13 @@ static int target_write_buffer_default(struct target *target,
        target_addr_t address, uint32_t count, const uint8_t *buffer)
 {
        uint32_t size;
+       unsigned int data_bytes = target_data_bits(target) / 8;
 
-       /* Align up to maximum bytes. The loop condition makes sure the next pass
+       /* Align up to maximum bytes. The loop condition makes sure the next pass
         * will have something to do with the size we leave to it. */
-       for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) {
+       for (size = 1;
+                       size < data_bytes && count >= size * 2 + (address & size);
+                       size *= 2) {
                if (address & size) {
                        int retval = target_write_memory(target, address, size, 1, buffer);
                        if (retval != ERROR_OK)
@@ -2463,10 +2473,13 @@ int target_read_buffer(struct target *target, target_addr_t address, uint32_t si
 static int target_read_buffer_default(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer)
 {
        uint32_t size;
+       unsigned int data_bytes = target_data_bits(target) / 8;
 
-       /* Align up to maximum bytes. The loop condition makes sure the next pass
+       /* Align up to maximum bytes. The loop condition makes sure the next pass
         * will have something to do with the size we leave to it. */
-       for (size = 1; size < 4 && count >= size * 2 + (address & size); size *= 2) {
+       for (size = 1;
+                       size < data_bytes && count >= size * 2 + (address & size);
+                       size *= 2) {
                if (address & size) {
                        int retval = target_read_memory(target, address, size, 1, buffer);
                        if (retval != ERROR_OK)
index d86c63eb06632c9d6908db4dd8670e950e2ced3c..18a9516f52867a9518c5a33504bd2a698c643a0e 100644 (file)
@@ -684,6 +684,13 @@ target_addr_t target_address_max(struct target *target);
  */
 unsigned target_address_bits(struct target *target);
 
+/**
+ * Return the number of data bits this target supports.
+ *
+ * This routine is a wrapper for target->type->data_bits.
+ */
+unsigned int target_data_bits(struct target *target);
+
 /** Return the *name* of this targets current state */
 const char *target_state_name(struct target *target);
 
index cc51c0401659405d2307f79766673126f22f7101..cf30cf8cc69e88b72f6f30fda4baa6a5afd9b884 100644 (file)
@@ -295,6 +295,11 @@ struct target_type {
         * typically be 32 for 32-bit targets, and 64 for 64-bit targets. If not
         * implemented, it's assumed to be 32. */
        unsigned (*address_bits)(struct target *target);
+
+       /* Return the number of system bus data bits this target supports. This
+        * will typically be 32 for 32-bit targets, and 64 for 64-bit targets. If
+        * not implemented, it's assumed to be 32. */
+       unsigned int (*data_bits)(struct target *target);
 };
 
 #endif /* OPENOCD_TARGET_TARGET_TYPE_H */