1//===---EmulateInstructionLoongArch.cpp------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include <cstdlib>
10#include <optional>
11
12#include "EmulateInstructionLoongArch.h"
13#include "Plugins/Process/Utility/InstructionUtils.h"
14#include "Plugins/Process/Utility/RegisterInfoPOSIX_loongarch64.h"
15#include "Plugins/Process/Utility/lldb-loongarch-register-enums.h"
16#include "lldb/Core/Address.h"
17#include "lldb/Core/PluginManager.h"
18#include "lldb/Interpreter/OptionValueArray.h"
19#include "lldb/Interpreter/OptionValueDictionary.h"
20#include "lldb/Symbol/UnwindPlan.h"
21#include "lldb/Utility/ArchSpec.h"
22#include "lldb/Utility/LLDBLog.h"
23#include "lldb/Utility/RegisterValue.h"
24#include "lldb/Utility/Stream.h"
25#include "llvm/ADT/STLExtras.h"
26#include "llvm/Support/MathExtras.h"
27
28using namespace lldb;
29using namespace lldb_private;
30
31LLDB_PLUGIN_DEFINE_ADV(EmulateInstructionLoongArch, InstructionLoongArch)
32
33namespace lldb_private {
34
35EmulateInstructionLoongArch::Opcode *
36EmulateInstructionLoongArch::GetOpcodeForInstruction(uint32_t inst) {
37 // TODO: Add the mask for other instruction.
38 static EmulateInstructionLoongArch::Opcode g_opcodes[] = {
39 {.mask: 0xfc000000, .value: 0x40000000, .callback: &EmulateInstructionLoongArch::EmulateBEQZ,
40 .name: "beqz rj, offs21"},
41 {.mask: 0xfc000000, .value: 0x44000000, .callback: &EmulateInstructionLoongArch::EmulateBNEZ,
42 .name: "bnez rj, offs21"},
43 {.mask: 0xfc000300, .value: 0x48000000, .callback: &EmulateInstructionLoongArch::EmulateBCEQZ,
44 .name: "bceqz cj, offs21"},
45 {.mask: 0xfc000300, .value: 0x48000100, .callback: &EmulateInstructionLoongArch::EmulateBCNEZ,
46 .name: "bcnez cj, offs21"},
47 {.mask: 0xfc000000, .value: 0x4c000000, .callback: &EmulateInstructionLoongArch::EmulateJIRL,
48 .name: "jirl rd, rj, offs16"},
49 {.mask: 0xfc000000, .value: 0x50000000, .callback: &EmulateInstructionLoongArch::EmulateB,
50 .name: " b offs26"},
51 {.mask: 0xfc000000, .value: 0x54000000, .callback: &EmulateInstructionLoongArch::EmulateBL,
52 .name: "bl offs26"},
53 {.mask: 0xfc000000, .value: 0x58000000, .callback: &EmulateInstructionLoongArch::EmulateBEQ,
54 .name: "beq rj, rd, offs16"},
55 {.mask: 0xfc000000, .value: 0x5c000000, .callback: &EmulateInstructionLoongArch::EmulateBNE,
56 .name: "bne rj, rd, offs16"},
57 {.mask: 0xfc000000, .value: 0x60000000, .callback: &EmulateInstructionLoongArch::EmulateBLT,
58 .name: "blt rj, rd, offs16"},
59 {.mask: 0xfc000000, .value: 0x64000000, .callback: &EmulateInstructionLoongArch::EmulateBGE,
60 .name: "bge rj, rd, offs16"},
61 {.mask: 0xfc000000, .value: 0x68000000, .callback: &EmulateInstructionLoongArch::EmulateBLTU,
62 .name: "bltu rj, rd, offs16"},
63 {.mask: 0xfc000000, .value: 0x6c000000, .callback: &EmulateInstructionLoongArch::EmulateBGEU,
64 .name: "bgeu rj, rd, offs16"},
65 {.mask: 0x00000000, .value: 0x00000000, .callback: &EmulateInstructionLoongArch::EmulateNonJMP,
66 .name: "NonJMP"}};
67 static const size_t num_loongarch_opcodes = std::size(g_opcodes);
68
69 for (size_t i = 0; i < num_loongarch_opcodes; ++i)
70 if ((g_opcodes[i].mask & inst) == g_opcodes[i].value)
71 return &g_opcodes[i];
72 return nullptr;
73}
74
75bool EmulateInstructionLoongArch::TestExecute(uint32_t inst) {
76 Opcode *opcode_data = GetOpcodeForInstruction(inst);
77 if (!opcode_data)
78 return false;
79 // Call the Emulate... function.
80 if (!(this->*opcode_data->callback)(inst))
81 return false;
82 return true;
83}
84
85bool EmulateInstructionLoongArch::EvaluateInstruction(uint32_t options) {
86 uint32_t inst_size = m_opcode.GetByteSize();
87 uint32_t inst = m_opcode.GetOpcode32();
88 bool increase_pc = options & eEmulateInstructionOptionAutoAdvancePC;
89 bool success = false;
90
91 Opcode *opcode_data = GetOpcodeForInstruction(inst);
92 if (!opcode_data)
93 return false;
94
95 lldb::addr_t old_pc = 0;
96 if (increase_pc) {
97 old_pc = ReadPC(success: &success);
98 if (!success)
99 return false;
100 }
101
102 // Call the Emulate... function.
103 if (!(this->*opcode_data->callback)(inst))
104 return false;
105
106 if (increase_pc) {
107 lldb::addr_t new_pc = ReadPC(success: &success);
108 if (!success)
109 return false;
110
111 if (new_pc == old_pc && !WritePC(pc: old_pc + inst_size))
112 return false;
113 }
114 return true;
115}
116
117bool EmulateInstructionLoongArch::ReadInstruction() {
118 bool success = false;
119 m_addr = ReadPC(success: &success);
120 if (!success) {
121 m_addr = LLDB_INVALID_ADDRESS;
122 return false;
123 }
124
125 Context ctx;
126 ctx.type = eContextReadOpcode;
127 ctx.SetNoArgs();
128 uint32_t inst = (uint32_t)ReadMemoryUnsigned(context: ctx, addr: m_addr, byte_size: 4, fail_value: 0, success_ptr: &success);
129 m_opcode.SetOpcode32(inst, order: GetByteOrder());
130
131 return true;
132}
133
134lldb::addr_t EmulateInstructionLoongArch::ReadPC(bool *success) {
135 return ReadRegisterUnsigned(reg_kind: eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC,
136 LLDB_INVALID_ADDRESS, success_ptr: success);
137}
138
139bool EmulateInstructionLoongArch::WritePC(lldb::addr_t pc) {
140 EmulateInstruction::Context ctx;
141 ctx.type = eContextAdvancePC;
142 ctx.SetNoArgs();
143 return WriteRegisterUnsigned(context: ctx, reg_kind: eRegisterKindGeneric,
144 LLDB_REGNUM_GENERIC_PC, reg_value: pc);
145}
146
147std::optional<RegisterInfo>
148EmulateInstructionLoongArch::GetRegisterInfo(lldb::RegisterKind reg_kind,
149 uint32_t reg_index) {
150 if (reg_kind == eRegisterKindGeneric) {
151 switch (reg_index) {
152 case LLDB_REGNUM_GENERIC_PC:
153 reg_kind = eRegisterKindLLDB;
154 reg_index = gpr_pc_loongarch;
155 break;
156 case LLDB_REGNUM_GENERIC_SP:
157 reg_kind = eRegisterKindLLDB;
158 reg_index = gpr_sp_loongarch;
159 break;
160 case LLDB_REGNUM_GENERIC_FP:
161 reg_kind = eRegisterKindLLDB;
162 reg_index = gpr_fp_loongarch;
163 break;
164 case LLDB_REGNUM_GENERIC_RA:
165 reg_kind = eRegisterKindLLDB;
166 reg_index = gpr_ra_loongarch;
167 break;
168 // We may handle LLDB_REGNUM_GENERIC_ARGx when more instructions are
169 // supported.
170 default:
171 llvm_unreachable("unsupported register");
172 }
173 }
174
175 const RegisterInfo *array =
176 RegisterInfoPOSIX_loongarch64::GetRegisterInfoPtr(target_arch: m_arch);
177 const uint32_t length =
178 RegisterInfoPOSIX_loongarch64::GetRegisterInfoCount(target_arch: m_arch);
179
180 if (reg_index >= length || reg_kind != eRegisterKindLLDB)
181 return {};
182 return array[reg_index];
183}
184
185bool EmulateInstructionLoongArch::SetTargetTriple(const ArchSpec &arch) {
186 return SupportsThisArch(arch);
187}
188
189bool EmulateInstructionLoongArch::TestEmulation(
190 Stream &out_stream, ArchSpec &arch, OptionValueDictionary *test_data) {
191 return false;
192}
193
194void EmulateInstructionLoongArch::Initialize() {
195 PluginManager::RegisterPlugin(name: GetPluginNameStatic(),
196 description: GetPluginDescriptionStatic(), create_callback: CreateInstance);
197}
198
199void EmulateInstructionLoongArch::Terminate() {
200 PluginManager::UnregisterPlugin(create_callback: CreateInstance);
201}
202
203lldb_private::EmulateInstruction *
204EmulateInstructionLoongArch::CreateInstance(const ArchSpec &arch,
205 InstructionType inst_type) {
206 if (EmulateInstructionLoongArch::SupportsThisInstructionType(inst_type) &&
207 SupportsThisArch(arch))
208 return new EmulateInstructionLoongArch(arch);
209 return nullptr;
210}
211
212bool EmulateInstructionLoongArch::SupportsThisArch(const ArchSpec &arch) {
213 return arch.GetTriple().isLoongArch();
214}
215
216bool EmulateInstructionLoongArch::EmulateBEQZ(uint32_t inst) {
217 return IsLoongArch64() ? EmulateBEQZ64(inst) : false;
218}
219
220bool EmulateInstructionLoongArch::EmulateBNEZ(uint32_t inst) {
221 return IsLoongArch64() ? EmulateBNEZ64(inst) : false;
222}
223
224bool EmulateInstructionLoongArch::EmulateBCEQZ(uint32_t inst) {
225 return IsLoongArch64() ? EmulateBCEQZ64(inst) : false;
226}
227
228bool EmulateInstructionLoongArch::EmulateBCNEZ(uint32_t inst) {
229 return IsLoongArch64() ? EmulateBCNEZ64(inst) : false;
230}
231
232bool EmulateInstructionLoongArch::EmulateJIRL(uint32_t inst) {
233 return IsLoongArch64() ? EmulateJIRL64(inst) : false;
234}
235
236bool EmulateInstructionLoongArch::EmulateB(uint32_t inst) {
237 return IsLoongArch64() ? EmulateB64(inst) : false;
238}
239
240bool EmulateInstructionLoongArch::EmulateBL(uint32_t inst) {
241 return IsLoongArch64() ? EmulateBL64(inst) : false;
242}
243
244bool EmulateInstructionLoongArch::EmulateBEQ(uint32_t inst) {
245 return IsLoongArch64() ? EmulateBEQ64(inst) : false;
246}
247
248bool EmulateInstructionLoongArch::EmulateBNE(uint32_t inst) {
249 return IsLoongArch64() ? EmulateBNE64(inst) : false;
250}
251
252bool EmulateInstructionLoongArch::EmulateBLT(uint32_t inst) {
253 return IsLoongArch64() ? EmulateBLT64(inst) : false;
254}
255
256bool EmulateInstructionLoongArch::EmulateBGE(uint32_t inst) {
257 return IsLoongArch64() ? EmulateBGE64(inst) : false;
258}
259
260bool EmulateInstructionLoongArch::EmulateBLTU(uint32_t inst) {
261 return IsLoongArch64() ? EmulateBLTU64(inst) : false;
262}
263
264bool EmulateInstructionLoongArch::EmulateBGEU(uint32_t inst) {
265 return IsLoongArch64() ? EmulateBGEU64(inst) : false;
266}
267
268bool EmulateInstructionLoongArch::EmulateNonJMP(uint32_t inst) { return false; }
269
270// beqz rj, offs21
271// if GR[rj] == 0:
272// PC = PC + SignExtend({offs21, 2'b0}, GRLEN)
273bool EmulateInstructionLoongArch::EmulateBEQZ64(uint32_t inst) {
274 bool success = false;
275 uint32_t rj = Bits32(bits: inst, msbit: 9, lsbit: 5);
276 uint64_t pc = ReadPC(success: &success);
277 if (!success)
278 return false;
279 uint32_t offs21 = Bits32(bits: inst, msbit: 25, lsbit: 10) + (Bits32(bits: inst, msbit: 4, lsbit: 0) << 16);
280 uint64_t rj_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rj, fail_value: 0, success_ptr: &success);
281 if (!success)
282 return false;
283 if (rj_val == 0) {
284 uint64_t next_pc = pc + llvm::SignExtend64<23>(x: offs21 << 2);
285 return WritePC(pc: next_pc);
286 } else
287 return WritePC(pc: pc + 4);
288}
289
290// bnez rj, offs21
291// if GR[rj] != 0:
292// PC = PC + SignExtend({offs21, 2'b0}, GRLEN)
293bool EmulateInstructionLoongArch::EmulateBNEZ64(uint32_t inst) {
294 bool success = false;
295 uint32_t rj = Bits32(bits: inst, msbit: 9, lsbit: 5);
296 uint64_t pc = ReadPC(success: &success);
297 if (!success)
298 return false;
299 uint32_t offs21 = Bits32(bits: inst, msbit: 25, lsbit: 10) + (Bits32(bits: inst, msbit: 4, lsbit: 0) << 16);
300 uint64_t rj_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rj, fail_value: 0, success_ptr: &success);
301 if (!success)
302 return false;
303 if (rj_val != 0) {
304 uint64_t next_pc = pc + llvm::SignExtend64<23>(x: offs21 << 2);
305 return WritePC(pc: next_pc);
306 } else
307 return WritePC(pc: pc + 4);
308}
309
310// bceqz cj, offs21
311// if CFR[cj] == 0:
312// PC = PC + SignExtend({offs21, 2'b0}, GRLEN)
313bool EmulateInstructionLoongArch::EmulateBCEQZ64(uint32_t inst) {
314 bool success = false;
315 uint32_t cj = Bits32(bits: inst, msbit: 7, lsbit: 5) + fpr_fcc0_loongarch;
316 uint64_t pc = ReadPC(success: &success);
317 if (!success)
318 return false;
319 uint32_t offs21 = Bits32(bits: inst, msbit: 25, lsbit: 10) + (Bits32(bits: inst, msbit: 4, lsbit: 0) << 16);
320 uint8_t cj_val =
321 (uint8_t)ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: cj, fail_value: 0, success_ptr: &success);
322 if (!success)
323 return false;
324 if (cj_val == 0) {
325 uint64_t next_pc = pc + llvm::SignExtend64<23>(x: offs21 << 2);
326 return WritePC(pc: next_pc);
327 } else
328 return WritePC(pc: pc + 4);
329 return false;
330}
331
332// bcnez cj, offs21
333// if CFR[cj] != 0:
334// PC = PC + SignExtend({offs21, 2'b0}, GRLEN)
335bool EmulateInstructionLoongArch::EmulateBCNEZ64(uint32_t inst) {
336 bool success = false;
337 uint32_t cj = Bits32(bits: inst, msbit: 7, lsbit: 5) + fpr_fcc0_loongarch;
338 uint64_t pc = ReadPC(success: &success);
339 if (!success)
340 return false;
341 uint32_t offs21 = Bits32(bits: inst, msbit: 25, lsbit: 10) + (Bits32(bits: inst, msbit: 4, lsbit: 0) << 16);
342 uint8_t cj_val =
343 (uint8_t)ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: cj, fail_value: 0, success_ptr: &success);
344 if (!success)
345 return false;
346 if (cj_val != 0) {
347 uint64_t next_pc = pc + llvm::SignExtend64<23>(x: offs21 << 2);
348 return WritePC(pc: next_pc);
349 } else
350 return WritePC(pc: pc + 4);
351 return false;
352}
353
354// jirl rd, rj, offs16
355// GR[rd] = PC + 4
356// PC = GR[rj] + SignExtend({offs16, 2'b0}, GRLEN)
357bool EmulateInstructionLoongArch::EmulateJIRL64(uint32_t inst) {
358 uint32_t rj = Bits32(bits: inst, msbit: 9, lsbit: 5);
359 uint32_t rd = Bits32(bits: inst, msbit: 4, lsbit: 0);
360 bool success = false;
361 uint64_t pc = ReadPC(success: &success);
362 if (!success)
363 return false;
364 EmulateInstruction::Context ctx;
365 if (!WriteRegisterUnsigned(context: ctx, reg_kind: eRegisterKindLLDB, reg_num: rd, reg_value: pc + 4))
366 return false;
367 uint64_t rj_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rj, fail_value: 0, success_ptr: &success);
368 if (!success)
369 return false;
370 uint64_t next_pc = rj_val + llvm::SignExtend64<18>(x: Bits32(bits: inst, msbit: 25, lsbit: 10) << 2);
371 return WritePC(pc: next_pc);
372}
373
374// b offs26
375// PC = PC + SignExtend({offs26, 2' b0}, GRLEN)
376bool EmulateInstructionLoongArch::EmulateB64(uint32_t inst) {
377 bool success = false;
378 uint64_t pc = ReadPC(success: &success);
379 if (!success)
380 return false;
381 uint32_t offs26 = Bits32(bits: inst, msbit: 25, lsbit: 10) + (Bits32(bits: inst, msbit: 9, lsbit: 0) << 16);
382 uint64_t next_pc = pc + llvm::SignExtend64<28>(x: offs26 << 2);
383 return WritePC(pc: next_pc);
384}
385
386// bl offs26
387// GR[1] = PC + 4
388// PC = PC + SignExtend({offs26, 2'b0}, GRLEN)
389bool EmulateInstructionLoongArch::EmulateBL64(uint32_t inst) {
390 bool success = false;
391 uint64_t pc = ReadPC(success: &success);
392 if (!success)
393 return false;
394 EmulateInstruction::Context ctx;
395 if (!WriteRegisterUnsigned(context: ctx, reg_kind: eRegisterKindLLDB, reg_num: gpr_r1_loongarch, reg_value: pc + 4))
396 return false;
397 uint32_t offs26 = Bits32(bits: inst, msbit: 25, lsbit: 10) + (Bits32(bits: inst, msbit: 9, lsbit: 0) << 16);
398 uint64_t next_pc = pc + llvm::SignExtend64<28>(x: offs26 << 2);
399 return WritePC(pc: next_pc);
400}
401
402// beq rj, rd, offs16
403// if GR[rj] == GR[rd]:
404// PC = PC + SignExtend({offs16, 2'b0}, GRLEN)
405bool EmulateInstructionLoongArch::EmulateBEQ64(uint32_t inst) {
406 bool success = false;
407 uint32_t rj = Bits32(bits: inst, msbit: 9, lsbit: 5);
408 uint32_t rd = Bits32(bits: inst, msbit: 4, lsbit: 0);
409 uint64_t pc = ReadPC(success: &success);
410 if (!success)
411 return false;
412 uint64_t rj_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rj, fail_value: 0, success_ptr: &success);
413 if (!success)
414 return false;
415 uint64_t rd_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rd, fail_value: 0, success_ptr: &success);
416 if (!success)
417 return false;
418 if (rj_val == rd_val) {
419 uint64_t next_pc = pc + llvm::SignExtend64<18>(x: Bits32(bits: inst, msbit: 25, lsbit: 10) << 2);
420 return WritePC(pc: next_pc);
421 } else
422 return WritePC(pc: pc + 4);
423}
424
425// bne rj, rd, offs16
426// if GR[rj] != GR[rd]:
427// PC = PC + SignExtend({offs16, 2'b0}, GRLEN)
428bool EmulateInstructionLoongArch::EmulateBNE64(uint32_t inst) {
429 bool success = false;
430 uint32_t rj = Bits32(bits: inst, msbit: 9, lsbit: 5);
431 uint32_t rd = Bits32(bits: inst, msbit: 4, lsbit: 0);
432 uint64_t pc = ReadPC(success: &success);
433 if (!success)
434 return false;
435 uint64_t rj_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rj, fail_value: 0, success_ptr: &success);
436 if (!success)
437 return false;
438 uint64_t rd_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rd, fail_value: 0, success_ptr: &success);
439 if (!success)
440 return false;
441 if (rj_val != rd_val) {
442 uint64_t next_pc = pc + llvm::SignExtend64<18>(x: Bits32(bits: inst, msbit: 25, lsbit: 10) << 2);
443 return WritePC(pc: next_pc);
444 } else
445 return WritePC(pc: pc + 4);
446}
447
448// blt rj, rd, offs16
449// if signed(GR[rj]) < signed(GR[rd]):
450// PC = PC + SignExtend({offs16, 2'b0}, GRLEN)
451bool EmulateInstructionLoongArch::EmulateBLT64(uint32_t inst) {
452 bool success = false;
453 uint32_t rj = Bits32(bits: inst, msbit: 9, lsbit: 5);
454 uint32_t rd = Bits32(bits: inst, msbit: 4, lsbit: 0);
455 uint64_t pc = ReadPC(success: &success);
456 if (!success)
457 return false;
458 int64_t rj_val =
459 (int64_t)ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rj, fail_value: 0, success_ptr: &success);
460 if (!success)
461 return false;
462 int64_t rd_val =
463 (int64_t)ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rd, fail_value: 0, success_ptr: &success);
464 if (!success)
465 return false;
466 if (rj_val < rd_val) {
467 uint64_t next_pc = pc + llvm::SignExtend64<18>(x: Bits32(bits: inst, msbit: 25, lsbit: 10) << 2);
468 return WritePC(pc: next_pc);
469 } else
470 return WritePC(pc: pc + 4);
471}
472
473// bge rj, rd, offs16
474// if signed(GR[rj]) >= signed(GR[rd]):
475// PC = PC + SignExtend({offs16, 2'b0}, GRLEN)
476bool EmulateInstructionLoongArch::EmulateBGE64(uint32_t inst) {
477 bool success = false;
478 uint32_t rj = Bits32(bits: inst, msbit: 9, lsbit: 5);
479 uint32_t rd = Bits32(bits: inst, msbit: 4, lsbit: 0);
480 uint64_t pc = ReadPC(success: &success);
481 if (!success)
482 return false;
483 int64_t rj_val =
484 (int64_t)ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rj, fail_value: 0, success_ptr: &success);
485 if (!success)
486 return false;
487 int64_t rd_val =
488 (int64_t)ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rd, fail_value: 0, success_ptr: &success);
489 if (!success)
490 return false;
491 if (rj_val >= rd_val) {
492 uint64_t next_pc = pc + llvm::SignExtend64<18>(x: Bits32(bits: inst, msbit: 25, lsbit: 10) << 2);
493 return WritePC(pc: next_pc);
494 } else
495 return WritePC(pc: pc + 4);
496}
497
498// bltu rj, rd, offs16
499// if unsigned(GR[rj]) < unsigned(GR[rd]):
500// PC = PC + SignExtend({offs16, 2'b0}, GRLEN)
501bool EmulateInstructionLoongArch::EmulateBLTU64(uint32_t inst) {
502 bool success = false;
503 uint32_t rj = Bits32(bits: inst, msbit: 9, lsbit: 5);
504 uint32_t rd = Bits32(bits: inst, msbit: 4, lsbit: 0);
505 uint64_t pc = ReadPC(success: &success);
506 if (!success)
507 return false;
508 uint64_t rj_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rj, fail_value: 0, success_ptr: &success);
509 if (!success)
510 return false;
511 uint64_t rd_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rd, fail_value: 0, success_ptr: &success);
512 if (!success)
513 return false;
514 if (rj_val < rd_val) {
515 uint64_t next_pc = pc + llvm::SignExtend64<18>(x: Bits32(bits: inst, msbit: 25, lsbit: 10) << 2);
516 return WritePC(pc: next_pc);
517 } else
518 return WritePC(pc: pc + 4);
519}
520
521// bgeu rj, rd, offs16
522// if unsigned(GR[rj]) >= unsigned(GR[rd]):
523// PC = PC + SignExtend({offs16, 2'b0}, GRLEN)
524bool EmulateInstructionLoongArch::EmulateBGEU64(uint32_t inst) {
525 bool success = false;
526 uint32_t rj = Bits32(bits: inst, msbit: 9, lsbit: 5);
527 uint32_t rd = Bits32(bits: inst, msbit: 4, lsbit: 0);
528 uint64_t pc = ReadPC(success: &success);
529 if (!success)
530 return false;
531 uint64_t rj_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rj, fail_value: 0, success_ptr: &success);
532 if (!success)
533 return false;
534 uint64_t rd_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rd, fail_value: 0, success_ptr: &success);
535 if (!success)
536 return false;
537 if (rj_val >= rd_val) {
538 uint64_t next_pc = pc + llvm::SignExtend64<18>(x: Bits32(bits: inst, msbit: 25, lsbit: 10) << 2);
539 return WritePC(pc: next_pc);
540 } else
541 return WritePC(pc: pc + 4);
542}
543
544} // namespace lldb_private
545

source code of lldb/source/Plugins/Instruction/LoongArch/EmulateInstructionLoongArch.cpp