From: openocd-gerrit <ope...@us...> - 2024-03-16 14:47:43
|
This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "Main OpenOCD repository". The branch, master has been updated via 01a797af143398c6f3aa1eb6f8949deff4ccf044 (commit) from a88db9b1211ea71b5795b91d11d94fb0f37cc905 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 01a797af143398c6f3aa1eb6f8949deff4ccf044 Author: Walter Ji <wal...@os...> Date: Fri Nov 17 16:46:55 2023 +0800 target/mips32: add fpu access support Add access to fpr and cp1 registers. GDB can now check the FPRs with `info reg f` and change them. Checkpatch-ignore: MACRO_ARG_REUSE Change-Id: I63896ab6f6737054d8108db105a13a58e1446fbc Signed-off-by: Walter Ji <wal...@os...> Reviewed-on: https://review.openocd.org/c/openocd/+/7866 Tested-by: jenkins Reviewed-by: Oleksij Rempel <li...@re...> Reviewed-by: Antonio Borneo <bor...@gm...> diff --git a/src/target/mips32.c b/src/target/mips32.c index ec2bfb7d0..6bbf71bd8 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -262,6 +262,61 @@ static int mips32_set_core_reg(struct reg *reg, uint8_t *buf) return ERROR_OK; } +/** + * mips32_set_all_fpr_width - Set the width of all floating-point registers + * @param[in] mips32: MIPS32 common structure + * @param[in] fp64: Flag indicating whether to set the width to 64 bits (double precision) + * + * @brief Sets the width of all floating-point registers based on the specified flag. + */ +static void mips32_set_all_fpr_width(struct mips32_common *mips32, bool fp64) +{ + struct reg_cache *cache = mips32->core_cache; + struct reg *reg_list = cache->reg_list; + int i; + + for (i = MIPS32_REGLIST_FP_INDEX; i < (MIPS32_REGLIST_FP_INDEX + MIPS32_REG_FP_COUNT); i++) { + reg_list[i].size = fp64 ? 64 : 32; + reg_list[i].reg_data_type->type = fp64 ? REG_TYPE_IEEE_DOUBLE : REG_TYPE_IEEE_SINGLE; + } +} + +/** + * mips32_detect_fpr_mode_change - Detect changes in floating-point register mode + * @param[in] mips32: MIPS32 common structure + * @param[in] cp0_status: Value of the CP0 status register + * + * @brief Detects changes in the floating-point register mode based on the CP0 status register. + * If changes are detected, it updates the internal state + * and logs a warning message indicating the mode change. + */ +static void mips32_detect_fpr_mode_change(struct mips32_common *mips32, uint32_t cp0_status) +{ + if (!mips32->fp_imp) + return; + + /* CP0.Status.FR indicates the working mode of floating-point register. + * When FP = 0, fpr can contain any 32bit data type, + * 64bit data types are stored in even-odd register pairs. + * When FP = 1, fpr can contain any data types.*/ + bool fpu_in_64bit = ((cp0_status & BIT(MIPS32_CP0_STATUS_FR_SHIFT)) != 0); + + /* CP0.Status.CU1 indicated whether CoProcessor1(which is FPU) is present. */ + bool fp_enabled = ((cp0_status & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0); + + if (mips32->fpu_in_64bit != fpu_in_64bit) { + mips32->fpu_in_64bit = fpu_in_64bit; + mips32_set_all_fpr_width(mips32, fpu_in_64bit); + LOG_WARNING("** FP mode changed to %sbit, you must reconnect GDB **", fpu_in_64bit ? "64" : "32"); + } + + if (mips32->fpu_enabled != fp_enabled) { + mips32->fpu_enabled = fp_enabled; + const char *s = fp_enabled ? "enabled" : "disabled"; + LOG_WARNING("** FP is %s, register update %s **", s, s); + } +} + static int mips32_read_core_reg(struct target *target, unsigned int num) { unsigned int cnum; @@ -278,6 +333,8 @@ static int mips32_read_core_reg(struct target *target, unsigned int num) 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); + if (cnum == MIPS32_REG_C0_STATUS_INDEX) + mips32_detect_fpr_mode_change(mips32, reg_value); } else if (num >= MIPS32_REGLIST_FPC_INDEX) { /* FPCR */ cnum = num - MIPS32_REGLIST_FPC_INDEX; @@ -319,6 +376,8 @@ static int mips32_write_core_reg(struct target *target, unsigned int num) 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; + if (cnum == MIPS32_REG_C0_STATUS_INDEX) + mips32_detect_fpr_mode_change(mips32, reg_value); } else if (num >= MIPS32_REGLIST_FPC_INDEX) { /* FPCR */ cnum = num - MIPS32_REGLIST_FPC_INDEX; @@ -987,8 +1046,8 @@ static int mips32_read_config_fpu(struct mips32_common *mips32, struct mips_ejta mips32->fp_imp = MIPS32_FP_IMP_NONE; return ERROR_OK; } - uint32_t status_value; - bool status_fr, status_cu1; + uint32_t fir_value, status_value; + bool fpu_in_64bit, fp_enabled; retval = mips32_cp0_read(ejtag_info, &status_value, MIPS32_C0_STATUS, 0); if (retval != ERROR_OK) { @@ -996,20 +1055,34 @@ static int mips32_read_config_fpu(struct mips32_common *mips32, struct mips_ejta 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; + fpu_in_64bit = (status_value & BIT(MIPS32_CP0_STATUS_FR_SHIFT)) != 0; + fp_enabled = (status_value & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0; + if (fp_enabled) { + retval = mips32_cp1_control_read(ejtag_info, &fir_value, 0); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to read cp1 FIR register"); + return retval; + } + + if ((fir_value >> MIPS32_CP1_FIR_F64_SHIFT) & 0x1) + fp_imp++; } else { + /* This is the only condition that writes to buf */ snprintf(buf, sizeof(buf), "yes, disabled"); fp_imp = MIPS32_FP_IMP_UNKNOWN; } - mips32->fpu_in_64bit = status_fr; - mips32->fpu_enabled = status_cu1; + mips32->fpu_in_64bit = fpu_in_64bit; + mips32->fpu_enabled = fp_enabled; + + mips32_set_all_fpr_width(mips32, fpu_in_64bit); + + /* If fpu is not disabled, print out more information */ + if (!buf[0]) + snprintf(buf, sizeof(buf), "yes, %sbit (%s, working in %sbit)", + fp_imp == MIPS32_FP_IMP_64 ? "64" : "32", + fp_enabled ? "enabled" : "disabled", + fpu_in_64bit ? "64" : "32"); LOG_USER("FPU implemented: %s", buf); mips32->fp_imp = fp_imp; diff --git a/src/target/mips32.h b/src/target/mips32.h index d512e4970..a557f3117 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -459,10 +459,13 @@ struct mips32_algorithm { #define MIPS32_OP_AND 0x24u #define MIPS32_OP_CACHE 0x2Fu #define MIPS32_OP_COP0 0x10u +#define MIPS32_OP_COP1 0x11u #define MIPS32_OP_J 0x02u #define MIPS32_OP_JR 0x08u #define MIPS32_OP_LUI 0x0Fu #define MIPS32_OP_LW 0x23u +#define MIPS32_OP_LWC1 0x31u +#define MIPS32_OP_LDC1 0x35u #define MIPS32_OP_LB 0x20u #define MIPS32_OP_LBU 0x24u #define MIPS32_OP_LHU 0x25u @@ -470,6 +473,7 @@ struct mips32_algorithm { #define MIPS32_OP_MTHI 0x11u #define MIPS32_OP_MFLO 0x12u #define MIPS32_OP_MTLO 0x13u +#define MIPS32_OP_MUL 0x02u #define MIPS32_OP_RDHWR 0x3Bu #define MIPS32_OP_SB 0x28u #define MIPS32_OP_SH 0x29u @@ -485,6 +489,8 @@ struct mips32_algorithm { #define MIPS32_OP_SLLV 0x04u #define MIPS32_OP_SLTI 0x0Au #define MIPS32_OP_MOVN 0x0Bu +#define MIPS32_OP_SWC1 0x39u +#define MIPS32_OP_SDC1 0x3Du #define MIPS32_OP_REGIMM 0x01u #define MIPS32_OP_SDBBP 0x3Fu @@ -517,6 +523,7 @@ struct mips32_algorithm { #define MIPS32_ISA_BGTZ(reg, off) MIPS32_I_INST(MIPS32_OP_BGTZ, reg, 0, off) #define MIPS32_ISA_BNE(src, tar, off) MIPS32_I_INST(MIPS32_OP_BNE, src, tar, off) #define MIPS32_ISA_CACHE(op, off, base) MIPS32_I_INST(MIPS32_OP_CACHE, base, op, off) +#define MIPS32_ISA_CFC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_CF, gpr, cpr, 0, 0) #define MIPS32_ISA_J(tar) MIPS32_J_INST(MIPS32_OP_J, (0x0FFFFFFFu & (tar)) >> 2) #define MIPS32_ISA_JR(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_JR) #define MIPS32_ISA_JRHB(reg) MIPS32_R_INST(0, reg, 0, 0, 0x10, MIPS32_OP_JR) @@ -526,9 +533,15 @@ struct mips32_algorithm { #define MIPS32_ISA_LHU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LHU, base, reg, off) #define MIPS32_ISA_LUI(reg, val) MIPS32_I_INST(MIPS32_OP_LUI, 0, reg, val) #define MIPS32_ISA_LW(reg, off, base) MIPS32_I_INST(MIPS32_OP_LW, base, reg, off) +#define MIPS32_ISA_LWC1(reg, off, base) MIPS32_I_INST(MIPS32_OP_LWC1, base, reg, off) +#define MIPS32_ISA_LDC1(reg, off, base) MIPS32_I_INST(MIPS32_OP_LDC1, base, reg, off) #define MIPS32_ISA_MFC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP_MF, gpr, cpr, 0, sel) #define MIPS32_ISA_MTC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP_MT, gpr, cpr, 0, sel) +#define MIPS32_ISA_MFC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_MF, gpr, cpr, 0, 0) +#define MIPS32_ISA_MFHC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_MFH, gpr, cpr, 0, 0) +#define MIPS32_ISA_MTC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_MT, gpr, cpr, 0, 0) +#define MIPS32_ISA_MTHC1(gpr, cpr) MIPS32_R_INST(MIPS32_OP_COP1, MIPS32_COP_MTH, gpr, cpr, 0, 0) #define MIPS32_ISA_MFLO(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFLO) #define MIPS32_ISA_MFHI(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFHI) #define MIPS32_ISA_MTLO(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTLO) @@ -542,6 +555,8 @@ struct mips32_algorithm { #define MIPS32_ISA_SB(reg, off, base) MIPS32_I_INST(MIPS32_OP_SB, base, reg, off) #define MIPS32_ISA_SH(reg, off, base) MIPS32_I_INST(MIPS32_OP_SH, base, reg, off) #define MIPS32_ISA_SW(reg, off, base) MIPS32_I_INST(MIPS32_OP_SW, base, reg, off) +#define MIPS32_ISA_SWC1(reg, off, base) MIPS32_I_INST(MIPS32_OP_SWC1, base, reg, off) +#define MIPS32_ISA_SDC1(reg, off, base) MIPS32_I_INST(MIPS32_OP_SDC1, base, reg, off) #define MIPS32_ISA_SLL(dst, src, sa) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, dst, sa, MIPS32_OP_SLL) #define MIPS32_ISA_SLLV(dst, src, sa) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, dst, sa, MIPS32_OP_SLLV) @@ -588,6 +603,7 @@ struct mips32_algorithm { #define MMIPS32_OP_BGTZ 0x06u #define MMIPS32_OP_BNE 0x2Du #define MMIPS32_OP_CACHE 0x06u +#define MMIPS32_OP_CFC1 0x40u #define MMIPS32_OP_J 0x35u #define MMIPS32_OP_JALR 0x03Cu #define MMIPS32_OP_JALRHB 0x07Cu @@ -596,8 +612,14 @@ struct mips32_algorithm { #define MMIPS32_OP_LHU 0x0Du #define MMIPS32_OP_LUI 0x0Du #define MMIPS32_OP_LW 0x3Fu +#define MMIPS32_OP_LWC1 0x27u +#define MMIPS32_OP_LDC1 0x2Fu #define MMIPS32_OP_MFC0 0x03u +#define MMIPS32_OP_MFC1 0x80u +#define MMIPS32_OP_MFHC1 0xC0u #define MMIPS32_OP_MTC0 0x0Bu +#define MMIPS32_OP_MTC1 0xA0u +#define MMIPS32_OP_MTHC1 0xE0u #define MMIPS32_OP_MFLO 0x075u #define MMIPS32_OP_MFHI 0x035u #define MMIPS32_OP_MTLO 0x0F5u @@ -608,6 +630,8 @@ struct mips32_algorithm { #define MMIPS32_OP_SB 0x06u #define MMIPS32_OP_SH 0x0Eu #define MMIPS32_OP_SW 0x3Eu +#define MMIPS32_OP_SWC1 0x26u +#define MMIPS32_OP_SDC1 0x2Eu #define MMIPS32_OP_SLTU 0x390u #define MMIPS32_OP_SLL 0x000u #define MMIPS32_OP_SLTI 0x24u @@ -627,6 +651,7 @@ struct mips32_algorithm { #define MMIPS32_BGTZ(reg, off) MIPS32_I_INST(MMIPS32_POOL32I, MMIPS32_OP_BGTZ, reg, off) #define MMIPS32_BNE(src, tar, off) MIPS32_I_INST(MMIPS32_OP_BNE, tar, src, off) #define MMIPS32_CACHE(op, off, base) MIPS32_R_INST(MMIPS32_POOL32B, op, base, MMIPS32_OP_CACHE << 1, 0, off) +#define MMIPS32_CFC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_CFC1, MMIPS32_POOL32FXF) #define MMIPS32_J(tar) MIPS32_J_INST(MMIPS32_OP_J, ((0x07FFFFFFu & ((tar) >> 1)))) #define MMIPS32_JR(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_JALR, MMIPS32_POOL32AXF) @@ -636,13 +661,19 @@ struct mips32_algorithm { #define MMIPS32_LHU(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LHU, reg, base, off) #define MMIPS32_LUI(reg, val) MIPS32_I_INST(MMIPS32_POOL32I, MMIPS32_OP_LUI, reg, val) #define MMIPS32_LW(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LW, reg, base, off) +#define MMIPS32_LWC1(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LWC1, reg, base, off) +#define MMIPS32_LDC1(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LDC1, reg, base, off) #define MMIPS32_MFC0(gpr, cpr, sel) MIPS32_R_INST(MMIPS32_POOL32A, gpr, cpr, sel,\ MMIPS32_OP_MFC0, MMIPS32_POOL32AXF) +#define MMIPS32_MFC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_MFC1, MMIPS32_POOL32FXF) +#define MMIPS32_MFHC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_MFHC1, MMIPS32_POOL32FXF) #define MMIPS32_MFLO(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MFLO, MMIPS32_POOL32AXF) #define MMIPS32_MFHI(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MFHI, MMIPS32_POOL32AXF) #define MMIPS32_MTC0(gpr, cpr, sel) MIPS32_R_INST(MMIPS32_POOL32A, gpr, cpr, sel,\ MMIPS32_OP_MTC0, MMIPS32_POOL32AXF) +#define MMIPS32_MTC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_MTC1, MMIPS32_POOL32FXF) +#define MMIPS32_MTHC1(gpr, cpr) MIPS32_R_INST(MMIPS32_POOL32F, gpr, cpr, 0, MMIPS32_OP_MTHC1, MMIPS32_POOL32FXF) #define MMIPS32_MTLO(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MTLO, MMIPS32_POOL32AXF) #define MMIPS32_MTHI(reg) MIPS32_R_INST(MMIPS32_POOL32A, 0, reg, 0, MMIPS32_OP_MTHI, MMIPS32_POOL32AXF) @@ -653,6 +684,8 @@ struct mips32_algorithm { #define MMIPS32_SB(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SB, reg, base, off) #define MMIPS32_SH(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SH, reg, base, off) #define MMIPS32_SW(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SW, reg, base, off) +#define MMIPS32_SWC1(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SWC1, reg, base, off) +#define MMIPS32_SDC1(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SDC1, reg, base, off) #define MMIPS32_SRL(reg, src, off) MIPS32_R_INST(MMIPS32_POOL32A, reg, src, off, 0, MMIPS32_OP_SRL) #define MMIPS32_SLTU(dst, src, tar) MIPS32_R_INST(MMIPS32_POOL32A, tar, src, dst, 0, MMIPS32_OP_SLTU) @@ -686,6 +719,7 @@ struct mips32_algorithm { #define MIPS32_BGTZ(isa, reg, off) (isa ? MMIPS32_BGTZ(reg, off) : MIPS32_ISA_BGTZ(reg, off)) #define MIPS32_BNE(isa, src, tar, off) (isa ? MMIPS32_BNE(src, tar, off) : MIPS32_ISA_BNE(src, tar, off)) #define MIPS32_CACHE(isa, op, off, base) (isa ? MMIPS32_CACHE(op, off, base) : MIPS32_ISA_CACHE(op, off, base)) +#define MIPS32_CFC1(isa, gpr, cpr) (isa ? MMIPS32_CFC1(gpr, cpr) : MIPS32_ISA_CFC1(gpr, cpr)) #define MIPS32_J(isa, tar) (isa ? MMIPS32_J(tar) : MIPS32_ISA_J(tar)) #define MIPS32_JR(isa, reg) (isa ? MMIPS32_JR(reg) : MIPS32_ISA_JR(reg)) @@ -694,10 +728,15 @@ struct mips32_algorithm { #define MIPS32_LBU(isa, reg, off, base) (isa ? MMIPS32_LBU(reg, off, base) : MIPS32_ISA_LBU(reg, off, base)) #define MIPS32_LHU(isa, reg, off, base) (isa ? MMIPS32_LHU(reg, off, base) : MIPS32_ISA_LHU(reg, off, base)) #define MIPS32_LW(isa, reg, off, base) (isa ? MMIPS32_LW(reg, off, base) : MIPS32_ISA_LW(reg, off, base)) +#define MIPS32_LWC1(isa, reg, off, base) (isa ? MMIPS32_LWC1(reg, off, base) : MIPS32_ISA_LWC1(reg, off, base)) #define MIPS32_LUI(isa, reg, val) (isa ? MMIPS32_LUI(reg, val) : MIPS32_ISA_LUI(reg, val)) #define MIPS32_MFC0(isa, gpr, cpr, sel) (isa ? MMIPS32_MFC0(gpr, cpr, sel) : MIPS32_ISA_MFC0(gpr, cpr, sel)) #define MIPS32_MTC0(isa, gpr, cpr, sel) (isa ? MMIPS32_MTC0(gpr, cpr, sel) : MIPS32_ISA_MTC0(gpr, cpr, sel)) +#define MIPS32_MFC1(isa, gpr, cpr) (isa ? MMIPS32_MFC1(gpr, cpr) : MIPS32_ISA_MFC1(gpr, cpr)) +#define MIPS32_MFHC1(isa, gpr, cpr) (isa ? MMIPS32_MFHC1(gpr, cpr) : MIPS32_ISA_MFHC1(gpr, cpr)) +#define MIPS32_MTC1(isa, gpr, cpr) (isa ? MMIPS32_MTC1(gpr, cpr) : MIPS32_ISA_MTC1(gpr, cpr)) +#define MIPS32_MTHC1(isa, gpr, cpr) (isa ? MMIPS32_MTHC1(gpr, cpr) : MIPS32_ISA_MTHC1(gpr, cpr)) #define MIPS32_MFLO(isa, reg) (isa ? MMIPS32_MFLO(reg) : MIPS32_ISA_MFLO(reg)) #define MIPS32_MFHI(isa, reg) (isa ? MMIPS32_MFHI(reg) : MIPS32_ISA_MFHI(reg)) #define MIPS32_MTLO(isa, reg) (isa ? MMIPS32_MTLO(reg) : MIPS32_ISA_MTLO(reg)) @@ -710,6 +749,8 @@ struct mips32_algorithm { #define MIPS32_SB(isa, reg, off, base) (isa ? MMIPS32_SB(reg, off, base) : MIPS32_ISA_SB(reg, off, base)) #define MIPS32_SH(isa, reg, off, base) (isa ? MMIPS32_SH(reg, off, base) : MIPS32_ISA_SH(reg, off, base)) #define MIPS32_SW(isa, reg, off, base) (isa ? MMIPS32_SW(reg, off, base) : MIPS32_ISA_SW(reg, off, base)) +#define MIPS32_SWC1(isa, reg, off, base) (isa ? MMIPS32_SWC1(reg, off, base) : MIPS32_ISA_SWC1(reg, off, base)) +#define MIPS32_SDC1(isa, reg, off, base) (isa ? MMIPS32_SDC1(reg, off, base) : MIPS32_ISA_SDC1(reg, off, base)) #define MIPS32_SLL(isa, dst, src, sa) (isa ? MMIPS32_SLL(dst, src, sa) : MIPS32_ISA_SLL(dst, src, sa)) #define MIPS32_EHB(isa) (isa ? MMIPS32_SLL(0, 0, 3) : MIPS32_ISA_SLL(0, 0, 3)) diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index 22edf6a41..aaf3875fb 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -588,6 +588,26 @@ int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_r return ctx.retval; } +int mips32_cp1_control_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp1_c_reg) +{ + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; + pracc_queue_init(&ctx); + + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ + pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa)); + pracc_add(&ctx, 0, MIPS32_CFC1(ctx.isa, 8, cp1_c_reg)); /* move cp1c reg to $8 */ + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */ + 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, 8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ + + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val, 1); + pracc_queue_free(&ctx); + return ctx.retval; +} + /** * \b mips32_pracc_sync_cache * @@ -856,6 +876,9 @@ int mips32_pracc_write_regs(struct mips32_common *mips32) struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; uint32_t *gprs = mips32->core_regs.gpr; uint32_t *c0rs = mips32->core_regs.cp0; + bool fpu_in_64bit = ((c0rs[0] & BIT(MIPS32_CP0_STATUS_FR_SHIFT)) != 0); + bool fp_enabled = ((c0rs[0] & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0); + uint32_t rel = (ejtag_info->config[0] & MIPS32_CONFIG0_AR_MASK) >> MIPS32_CONFIG0_AR_SHIFT; pracc_queue_init(&ctx); @@ -895,6 +918,31 @@ int mips32_pracc_write_regs(struct mips32_common *mips32) if (mips32_cpu_support_hazard_barrier(ejtag_info)) pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa)); + + /* store FPRs */ + if (mips32->fp_imp && fp_enabled) { + uint64_t *fprs = mips32->core_regs.fpr; + if (fpu_in_64bit) { + for (int i = 0; i != MIPS32_REG_FP_COUNT; i++) { + uint32_t fp_lo = fprs[i] & 0xffffffff; + uint32_t fp_hi = (fprs[i] >> 32) & 0xffffffff; + pracc_add_li32(&ctx, 2, fp_lo, 0); + pracc_add_li32(&ctx, 3, fp_hi, 0); + pracc_add(&ctx, 0, MIPS32_MTC1(ctx.isa, 2, i)); + pracc_add(&ctx, 0, MIPS32_MTHC1(ctx.isa, 3, i)); + } + } else { + for (int i = 0; i != MIPS32_REG_FP_COUNT; i++) { + uint32_t fp_lo = fprs[i] & 0xffffffff; + pracc_add_li32(&ctx, 2, fp_lo, 0); + pracc_add(&ctx, 0, MIPS32_MTC1(ctx.isa, 2, i)); + } + } + + if (rel > MIPS32_RELEASE_1) + pracc_add(&ctx, 0, MIPS32_EHB(ctx.isa)); + } + /* load registers 2 to 31 with li32, optimize */ for (int i = 2; i < 32; i++) pracc_add_li32(&ctx, i, gprs[i], 1); @@ -1014,6 +1062,9 @@ int mips32_pracc_read_regs(struct mips32_common *mips32) 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; + unsigned int offset_fpr = ((uint8_t *)&core_regs->fpr[0]) - (uint8_t *)core_regs; + unsigned int offset_fpcr = ((uint8_t *)&core_regs->fpcr[0]) - (uint8_t *)core_regs; + bool fp_enabled; /* * This procedure has to be in 2 distinctive steps, because we can @@ -1040,11 +1091,64 @@ int mips32_pracc_read_regs(struct mips32_common *mips32) ejtag_info->reg8 = mips32->core_regs.gpr[8]; ejtag_info->reg9 = mips32->core_regs.gpr[9]; + if (ctx.retval != ERROR_OK) + return ctx.retval; + /* 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 */ + fp_enabled = (mips32->core_regs.cp0[0] & BIT(MIPS32_CP0_STATUS_CU1_SHIFT)) != 0; + if (mips32->fp_imp && fp_enabled) { + pracc_queue_init(&ctx); + mips32_pracc_store_regs_set_base_addr(&ctx); + + /* FCSR */ + pracc_add(&ctx, 0, MIPS32_CFC1(ctx.isa, 8, 31)); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset_fpcr, + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset_fpcr, 1)); + + /* FIR */ + pracc_add(&ctx, 0, MIPS32_CFC1(ctx.isa, 8, 0)); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset_fpcr + 4, + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset_fpcr + 4, 1)); + + /* f0 to f31 */ + if (mips32->fpu_in_64bit) { + for (int i = 0; i != 32; i++) { + size_t offset = offset_fpr + (i * 8); + /* current pracc implementation (or EJTAG itself) only supports 32b access */ + /* so there is no way to use SDC1 */ + + /* lower half */ + pracc_add(&ctx, 0, MIPS32_MFC1(ctx.isa, 8, i)); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset, + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset, 1)); + + /* upper half */ + pracc_add(&ctx, 0, MIPS32_MFHC1(ctx.isa, 8, i)); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset + 4, + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + offset + 4, 1)); + } + } else { + for (int i = 0; i != 32; i++) { + size_t offset = offset_fpr + (i * 8); + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + offset, + MIPS32_SWC1(ctx.isa, i, PRACC_OUT_OFFSET + offset, 1)); + } + } + + mips32_pracc_store_regs_restore(&ctx); + + /* 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); + + pracc_queue_free(&ctx); + } return ctx.retval; } diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h index 78d087213..f78f89153 100644 --- a/src/target/mips32_pracc.h +++ b/src/target/mips32_pracc.h @@ -103,6 +103,21 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info, int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel); +/** + * mips32_cp1_control_read + * + * @brief Simulates cfc1 ASM instruction (Move Control Word From Floating Point), + * i.e. implements copro C1 Control Register read. + * + * @param[in] ejtag_info + * @param[in] val Storage to hold read value + * @param[in] cp1_c_reg Number of copro C1 control register we want to read + * + * @return ERROR_OK on Success, ERROR_FAIL otherwise + */ +int mips32_cp1_control_read(struct mips_ejtag *ejtag_info, + uint32_t *val, uint32_t cp1_c_reg); + static inline void pracc_swap16_array(struct mips_ejtag *ejtag_info, uint32_t *buf, int count) { if (ejtag_info->isa && ejtag_info->endianness) ----------------------------------------------------------------------- Summary of changes: src/target/mips32.c | 95 ++++++++++++++++++++++++++++++++++++----- src/target/mips32.h | 41 ++++++++++++++++++ src/target/mips32_pracc.c | 106 +++++++++++++++++++++++++++++++++++++++++++++- src/target/mips32_pracc.h | 15 +++++++ 4 files changed, 245 insertions(+), 12 deletions(-) hooks/post-receive -- Main OpenOCD repository |