Index: lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h =================================================================== --- lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h +++ lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.h @@ -73,6 +73,7 @@ bool EmulateBEQZ(uint32_t inst); bool EmulateBNEZ(uint32_t inst); + bool EmulateBCXXZ(uint32_t inst); bool EmulateJIRL(uint32_t inst); bool EmulateB(uint32_t inst); bool EmulateBL(uint32_t inst); @@ -86,6 +87,7 @@ bool EmulateBEQZ64(uint32_t inst); bool EmulateBNEZ64(uint32_t inst); + bool EmulateBCXXZ64(uint32_t inst); bool EmulateJIRL64(uint32_t inst); bool EmulateB64(uint32_t inst); bool EmulateBL64(uint32_t inst); Index: lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp =================================================================== --- lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp +++ lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp @@ -39,6 +39,8 @@ "beqz rj, offs21"}, {0xfc000000, 0x44000000, &EmulateInstructionLoongArch::EmulateBNEZ, "bnez rj, offs21"}, + {0xfc000000, 0x48000000, &EmulateInstructionLoongArch::EmulateBCXXZ, + "bceqz/bcnez cj, offs21"}, {0xfc000000, 0x4c000000, &EmulateInstructionLoongArch::EmulateJIRL, "jirl rd, rj, offs16"}, {0xfc000000, 0x50000000, &EmulateInstructionLoongArch::EmulateB, @@ -199,80 +201,51 @@ } bool EmulateInstructionLoongArch::EmulateBEQZ(uint32_t inst) { - if (IsLoongArch64()) - return EmulateBEQZ64(inst); - else - return false; + return (IsLoongArch64()) ? EmulateBEQZ64(inst) : false; } bool EmulateInstructionLoongArch::EmulateBNEZ(uint32_t inst) { - if (IsLoongArch64()) - return EmulateBNEZ64(inst); - else - return false; + return (IsLoongArch64()) ? EmulateBNEZ64(inst) : false; +} + +bool EmulateInstructionLoongArch::EmulateBCXXZ(uint32_t inst) { + return (IsLoongArch64()) ? EmulateBCXXZ64(inst) : false; } bool EmulateInstructionLoongArch::EmulateJIRL(uint32_t inst) { - if (IsLoongArch64()) - return EmulateJIRL64(inst); - else - return false; + return (IsLoongArch64()) ? EmulateJIRL64(inst) : false; } bool EmulateInstructionLoongArch::EmulateB(uint32_t inst) { - if (IsLoongArch64()) - return EmulateB64(inst); - else - return false; + return (IsLoongArch64()) ? EmulateB64(inst) : false; } bool EmulateInstructionLoongArch::EmulateBL(uint32_t inst) { - if (IsLoongArch64()) - return EmulateBL64(inst); - else - return false; + return (IsLoongArch64()) ? EmulateBL64(inst) : false; } bool EmulateInstructionLoongArch::EmulateBEQ(uint32_t inst) { - if (IsLoongArch64()) - return EmulateBEQ64(inst); - else - return false; + return (IsLoongArch64()) ? EmulateBEQ64(inst) : false; } bool EmulateInstructionLoongArch::EmulateBNE(uint32_t inst) { - if (IsLoongArch64()) - return EmulateJIRL64(inst); - else - return false; + return (IsLoongArch64()) ? EmulateBNE64(inst) : false; } bool EmulateInstructionLoongArch::EmulateBLT(uint32_t inst) { - if (IsLoongArch64()) - return EmulateBLT64(inst); - else - return false; + return (IsLoongArch64()) ? EmulateBLT64(inst) : false; } bool EmulateInstructionLoongArch::EmulateBGE(uint32_t inst) { - if (IsLoongArch64()) - return EmulateBGE64(inst); - else - return false; + return (IsLoongArch64()) ? EmulateBGE64(inst) : false; } bool EmulateInstructionLoongArch::EmulateBLTU(uint32_t inst) { - if (IsLoongArch64()) - return EmulateBLTU64(inst); - else - return false; + return (IsLoongArch64()) ? EmulateBLTU64(inst) : false; } bool EmulateInstructionLoongArch::EmulateBGEU(uint32_t inst) { - if (IsLoongArch64()) - return EmulateBGEU64(inst); - else - return false; + return (IsLoongArch64()) ? EmulateBGEU64(inst) : false; } bool EmulateInstructionLoongArch::EmulateNonJMP(uint32_t inst) { return false; } @@ -281,20 +254,17 @@ // if GR[rj] == 0: // PC = PC + SignExtend({offs21, 2'b0}, GRLEN) bool EmulateInstructionLoongArch::EmulateBEQZ64(uint32_t inst) { - uint64_t next_pc, imm_sign_extend; bool success = false; uint32_t rj = Bits32(inst, 9, 5); - uint64_t rj_val; uint64_t pc = ReadPC(&success); if (!success) return false; uint32_t offs21 = Bits32(inst, 25, 10) + (Bits32(inst, 4, 0) << 16); - rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); + uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); if (!success) return false; if (rj_val == 0) { - imm_sign_extend = llvm::SignExtend64<23>(offs21 << 2); - next_pc = pc + imm_sign_extend; + uint64_t next_pc = pc + llvm::SignExtend64<23>(offs21 << 2); return WritePC(next_pc); } else return WritePC(pc + 4); @@ -304,31 +274,59 @@ // if GR[rj] != 0: // PC = PC + SignExtend({offs21, 2'b0}, GRLEN) bool EmulateInstructionLoongArch::EmulateBNEZ64(uint32_t inst) { - uint64_t next_pc, imm_sign_extend; bool success = false; uint32_t rj = Bits32(inst, 9, 5); - uint64_t rj_val; uint64_t pc = ReadPC(&success); if (!success) return false; uint32_t offs21 = Bits32(inst, 25, 10) + (Bits32(inst, 4, 0) << 16); - rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); + uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); if (!success) return false; if (rj_val != 0) { - imm_sign_extend = llvm::SignExtend64<23>(offs21 << 2); - next_pc = pc + imm_sign_extend; + uint64_t next_pc = pc + llvm::SignExtend64<23>(offs21 << 2); return WritePC(next_pc); } else return WritePC(pc + 4); } +// bceqz cj, offs21 +// if CFR[cj] == 0: +// PC = PC + SignExtend({offs21, 2'b0}, GRLEN) +// bcnez cj, offs21 +// if CFR[cj] != 0: +// PC = PC + SignExtend({offs21, 2'b0}, GRLEN) +bool EmulateInstructionLoongArch::EmulateBCXXZ64(uint32_t inst) { + bool success = false; + bool is_bceqz = inst & (1UL << 8); + uint32_t cj = Bits32(inst, 7, 5) + fpr_first_loongarch + 32; + uint64_t pc = ReadPC(&success); + if (!success) + return false; + uint32_t offs21 = Bits32(inst, 25, 10) + (Bits32(inst, 4, 0) << 16); + uint8_t cj_val = + (uint8_t)ReadRegisterUnsigned(eRegisterKindLLDB, cj, 0, &success); + if (!success) + return false; + if (is_bceqz) { + if (cj_val == 0) { + uint64_t next_pc = pc + llvm::SignExtend64<23>(offs21 << 2); + return WritePC(next_pc); + } else + return WritePC(pc + 4); + } else { + if (cj_val != 0) { + uint64_t next_pc = pc + llvm::SignExtend64<23>(offs21 << 2); + return WritePC(next_pc); + } else + return WritePC(pc + 4); + } +} + // jirl rd, rj, offs16 // GR[rd] = PC + 4 // PC = GR[rj] + SignExtend({offs16, 2'b0}, GRLEN) bool EmulateInstructionLoongArch::EmulateJIRL64(uint32_t inst) { - uint64_t next_pc, imm_sign_extend; - RegisterValue value; uint32_t rj = Bits32(inst, 9, 5); uint32_t rd = Bits32(inst, 4, 0); bool success = false; @@ -338,24 +336,22 @@ EmulateInstruction::Context ctx; if (!WriteRegisterUnsigned(ctx, eRegisterKindLLDB, rd, pc + 4)) return false; - if (!ReadRegister(eRegisterKindLLDB, rj, value)) + uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); + if (!success) return false; - imm_sign_extend = llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); - next_pc = value.GetAsUInt64() + imm_sign_extend; + uint64_t next_pc = rj_val + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); return WritePC(next_pc); } // b offs26 // PC = PC + SignExtend({offs26, 2' b0}, GRLEN) bool EmulateInstructionLoongArch::EmulateB64(uint32_t inst) { - uint64_t next_pc, imm_sign_extend; bool success = false; uint64_t pc = ReadPC(&success); if (!success) return false; uint32_t offs26 = Bits32(inst, 25, 10) + (Bits32(inst, 9, 0) << 16); - imm_sign_extend = llvm::SignExtend64<28>(offs26 << 2); - next_pc = pc + imm_sign_extend; + uint64_t next_pc = pc + llvm::SignExtend64<28>(offs26 << 2); return WritePC(next_pc); } @@ -363,7 +359,6 @@ // GR[1] = PC + 4 // PC = PC + SignExtend({offs26, 2'b0}, GRLEN) bool EmulateInstructionLoongArch::EmulateBL64(uint32_t inst) { - uint64_t next_pc, imm_sign_extend; bool success = false; uint64_t pc = ReadPC(&success); if (!success) @@ -372,8 +367,7 @@ if (!WriteRegisterUnsigned(ctx, eRegisterKindLLDB, gpr_r1_loongarch, pc + 4)) return false; uint32_t offs26 = Bits32(inst, 25, 10) + (Bits32(inst, 9, 0) << 16); - imm_sign_extend = llvm::SignExtend64<28>(offs26 << 2); - next_pc = pc + imm_sign_extend; + uint64_t next_pc = pc + llvm::SignExtend64<28>(offs26 << 2); return WritePC(next_pc); } @@ -381,23 +375,20 @@ // if GR[rj] == GR[rd]: // PC = PC + SignExtend({offs16, 2'b0}, GRLEN) bool EmulateInstructionLoongArch::EmulateBEQ64(uint32_t inst) { - uint64_t next_pc, imm_sign_extend; bool success = false; uint32_t rj = Bits32(inst, 9, 5); uint32_t rd = Bits32(inst, 4, 0); - uint64_t rj_val, rd_val; uint64_t pc = ReadPC(&success); if (!success) return false; - rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); + uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); if (!success) return false; - rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); + uint64_t rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); if (!success) return false; if (rj_val == rd_val) { - imm_sign_extend = llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); - next_pc = pc + imm_sign_extend; + uint64_t next_pc = pc + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); return WritePC(next_pc); } else return WritePC(pc + 4); @@ -407,23 +398,20 @@ // if GR[rj] != GR[rd]: // PC = PC + SignExtend({offs16, 2'b0}, GRLEN) bool EmulateInstructionLoongArch::EmulateBNE64(uint32_t inst) { - uint64_t next_pc, imm_sign_extend; bool success = false; uint32_t rj = Bits32(inst, 9, 5); uint32_t rd = Bits32(inst, 4, 0); - uint64_t rj_val, rd_val; uint64_t pc = ReadPC(&success); if (!success) return false; - rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); + uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); if (!success) return false; - rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); + uint64_t rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); if (!success) return false; if (rj_val != rd_val) { - imm_sign_extend = llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); - next_pc = pc + imm_sign_extend; + uint64_t next_pc = pc + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); return WritePC(next_pc); } else return WritePC(pc + 4); @@ -433,23 +421,22 @@ // if signed(GR[rj]) < signed(GR[rd]): // PC = PC + SignExtend({offs16, 2'b0}, GRLEN) bool EmulateInstructionLoongArch::EmulateBLT64(uint32_t inst) { - uint64_t next_pc, imm_sign_extend; bool success = false; uint32_t rj = Bits32(inst, 9, 5); uint32_t rd = Bits32(inst, 4, 0); - int64_t rj_val, rd_val; uint64_t pc = ReadPC(&success); if (!success) return false; - rj_val = (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); + int64_t rj_val = + (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); if (!success) return false; - rd_val = (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); + int64_t rd_val = + (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); if (!success) return false; if (rj_val < rd_val) { - imm_sign_extend = llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); - next_pc = pc + imm_sign_extend; + uint64_t next_pc = pc + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); return WritePC(next_pc); } else return WritePC(pc + 4); @@ -459,23 +446,22 @@ // if signed(GR[rj]) >= signed(GR[rd]): // PC = PC + SignExtend({offs16, 2'b0}, GRLEN) bool EmulateInstructionLoongArch::EmulateBGE64(uint32_t inst) { - uint64_t next_pc, imm_sign_extend; bool success = false; uint32_t rj = Bits32(inst, 9, 5); uint32_t rd = Bits32(inst, 4, 0); - int64_t rj_val, rd_val; uint64_t pc = ReadPC(&success); if (!success) return false; - rj_val = (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); + int64_t rj_val = + (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); if (!success) return false; - rd_val = (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); + int64_t rd_val = + (int64_t)ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); if (!success) return false; if (rj_val >= rd_val) { - imm_sign_extend = llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); - next_pc = pc + imm_sign_extend; + uint64_t next_pc = pc + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); return WritePC(next_pc); } else return WritePC(pc + 4); @@ -485,23 +471,20 @@ // if unsigned(GR[rj]) < unsigned(GR[rd]): // PC = PC + SignExtend({offs16, 2'b0}, GRLEN) bool EmulateInstructionLoongArch::EmulateBLTU64(uint32_t inst) { - uint64_t next_pc, imm_sign_extend; bool success = false; uint32_t rj = Bits32(inst, 9, 5); uint32_t rd = Bits32(inst, 4, 0); - uint64_t rj_val, rd_val; uint64_t pc = ReadPC(&success); if (!success) return false; - rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); + uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); if (!success) return false; - rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); + uint64_t rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); if (!success) return false; if (rj_val < rd_val) { - imm_sign_extend = llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); - next_pc = pc + imm_sign_extend; + uint64_t next_pc = pc + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); return WritePC(next_pc); } else return WritePC(pc + 4); @@ -511,23 +494,20 @@ // if unsigned(GR[rj]) >= unsigned(GR[rd]): // PC = PC + SignExtend({offs16, 2'b0}, GRLEN) bool EmulateInstructionLoongArch::EmulateBGEU64(uint32_t inst) { - uint64_t next_pc, imm_sign_extend; bool success = false; uint32_t rj = Bits32(inst, 9, 5); uint32_t rd = Bits32(inst, 4, 0); - uint64_t rj_val, rd_val; uint64_t pc = ReadPC(&success); if (!success) return false; - rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); + uint64_t rj_val = ReadRegisterUnsigned(eRegisterKindLLDB, rj, 0, &success); if (!success) return false; - rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); + uint64_t rd_val = ReadRegisterUnsigned(eRegisterKindLLDB, rd, 0, &success); if (!success) return false; if (rj_val >= rd_val) { - imm_sign_extend = llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); - next_pc = pc + imm_sign_extend; + uint64_t next_pc = pc + llvm::SignExtend64<18>(Bits32(inst, 25, 10) << 2); return WritePC(next_pc); } else return WritePC(pc + 4);