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
90 Opcode *opcode_data = GetOpcodeForInstruction(inst);
91 if (!opcode_data)
92 return false;
93
94 lldb::addr_t old_pc = 0;
95 if (increase_pc) {
96 auto addr = ReadPC();
97 if (!addr)
98 return false;
99 old_pc = *addr;
100 }
101
102 // Call the Emulate... function.
103 if (!(this->*opcode_data->callback)(inst))
104 return false;
105
106 if (increase_pc) {
107 auto addr = ReadPC();
108 if (!addr)
109 return false;
110 lldb::addr_t new_pc = *addr;
111
112 if (new_pc == old_pc && !WritePC(addr: old_pc + inst_size))
113 return false;
114 }
115 return true;
116}
117
118bool EmulateInstructionLoongArch::ReadInstruction() {
119 auto addr = ReadPC();
120 if (!addr) {
121 m_addr = LLDB_INVALID_ADDRESS;
122 return false;
123 }
124 m_addr = *addr;
125
126 bool success = false;
127 Context ctx;
128 ctx.type = eContextReadOpcode;
129 ctx.SetNoArgs();
130 uint32_t inst = (uint32_t)ReadMemoryUnsigned(context: ctx, addr: m_addr, byte_size: 4, fail_value: 0, success_ptr: &success);
131 m_opcode.SetOpcode32(inst, order: GetByteOrder());
132
133 return true;
134}
135
136std::optional<RegisterInfo>
137EmulateInstructionLoongArch::GetRegisterInfo(lldb::RegisterKind reg_kind,
138 uint32_t reg_index) {
139 if (reg_kind == eRegisterKindGeneric) {
140 switch (reg_index) {
141 case LLDB_REGNUM_GENERIC_PC:
142 reg_kind = eRegisterKindLLDB;
143 reg_index = gpr_pc_loongarch;
144 break;
145 case LLDB_REGNUM_GENERIC_SP:
146 reg_kind = eRegisterKindLLDB;
147 reg_index = gpr_sp_loongarch;
148 break;
149 case LLDB_REGNUM_GENERIC_FP:
150 reg_kind = eRegisterKindLLDB;
151 reg_index = gpr_fp_loongarch;
152 break;
153 case LLDB_REGNUM_GENERIC_RA:
154 reg_kind = eRegisterKindLLDB;
155 reg_index = gpr_ra_loongarch;
156 break;
157 // We may handle LLDB_REGNUM_GENERIC_ARGx when more instructions are
158 // supported.
159 default:
160 llvm_unreachable("unsupported register");
161 }
162 }
163
164 const RegisterInfo *array =
165 RegisterInfoPOSIX_loongarch64::GetRegisterInfoPtr(target_arch: m_arch);
166 const uint32_t length =
167 RegisterInfoPOSIX_loongarch64::GetRegisterInfoCount(target_arch: m_arch);
168
169 if (reg_index >= length || reg_kind != eRegisterKindLLDB)
170 return {};
171 return array[reg_index];
172}
173
174bool EmulateInstructionLoongArch::SetTargetTriple(const ArchSpec &arch) {
175 return SupportsThisArch(arch);
176}
177
178bool EmulateInstructionLoongArch::TestEmulation(
179 Stream &out_stream, ArchSpec &arch, OptionValueDictionary *test_data) {
180 return false;
181}
182
183void EmulateInstructionLoongArch::Initialize() {
184 PluginManager::RegisterPlugin(name: GetPluginNameStatic(),
185 description: GetPluginDescriptionStatic(), create_callback: CreateInstance);
186}
187
188void EmulateInstructionLoongArch::Terminate() {
189 PluginManager::UnregisterPlugin(create_callback: CreateInstance);
190}
191
192lldb_private::EmulateInstruction *
193EmulateInstructionLoongArch::CreateInstance(const ArchSpec &arch,
194 InstructionType inst_type) {
195 if (EmulateInstructionLoongArch::SupportsThisInstructionType(inst_type) &&
196 SupportsThisArch(arch))
197 return new EmulateInstructionLoongArch(arch);
198 return nullptr;
199}
200
201bool EmulateInstructionLoongArch::SupportsThisArch(const ArchSpec &arch) {
202 return arch.GetTriple().isLoongArch();
203}
204
205bool EmulateInstructionLoongArch::EmulateBEQZ(uint32_t inst) {
206 return IsLoongArch64() ? EmulateBEQZ64(inst) : false;
207}
208
209bool EmulateInstructionLoongArch::EmulateBNEZ(uint32_t inst) {
210 return IsLoongArch64() ? EmulateBNEZ64(inst) : false;
211}
212
213bool EmulateInstructionLoongArch::EmulateBCEQZ(uint32_t inst) {
214 return IsLoongArch64() ? EmulateBCEQZ64(inst) : false;
215}
216
217bool EmulateInstructionLoongArch::EmulateBCNEZ(uint32_t inst) {
218 return IsLoongArch64() ? EmulateBCNEZ64(inst) : false;
219}
220
221bool EmulateInstructionLoongArch::EmulateJIRL(uint32_t inst) {
222 return IsLoongArch64() ? EmulateJIRL64(inst) : false;
223}
224
225bool EmulateInstructionLoongArch::EmulateB(uint32_t inst) {
226 return IsLoongArch64() ? EmulateB64(inst) : false;
227}
228
229bool EmulateInstructionLoongArch::EmulateBL(uint32_t inst) {
230 return IsLoongArch64() ? EmulateBL64(inst) : false;
231}
232
233bool EmulateInstructionLoongArch::EmulateBEQ(uint32_t inst) {
234 return IsLoongArch64() ? EmulateBEQ64(inst) : false;
235}
236
237bool EmulateInstructionLoongArch::EmulateBNE(uint32_t inst) {
238 return IsLoongArch64() ? EmulateBNE64(inst) : false;
239}
240
241bool EmulateInstructionLoongArch::EmulateBLT(uint32_t inst) {
242 return IsLoongArch64() ? EmulateBLT64(inst) : false;
243}
244
245bool EmulateInstructionLoongArch::EmulateBGE(uint32_t inst) {
246 return IsLoongArch64() ? EmulateBGE64(inst) : false;
247}
248
249bool EmulateInstructionLoongArch::EmulateBLTU(uint32_t inst) {
250 return IsLoongArch64() ? EmulateBLTU64(inst) : false;
251}
252
253bool EmulateInstructionLoongArch::EmulateBGEU(uint32_t inst) {
254 return IsLoongArch64() ? EmulateBGEU64(inst) : false;
255}
256
257bool EmulateInstructionLoongArch::EmulateNonJMP(uint32_t inst) { return false; }
258
259// beqz rj, offs21
260// if GR[rj] == 0:
261// PC = PC + SignExtend({offs21, 2'b0}, GRLEN)
262bool EmulateInstructionLoongArch::EmulateBEQZ64(uint32_t inst) {
263 bool success = false;
264 uint32_t rj = Bits32(bits: inst, msbit: 9, lsbit: 5);
265
266 auto addr = ReadPC();
267 if (!addr)
268 return false;
269 uint64_t pc = *addr;
270
271 uint32_t offs21 = Bits32(bits: inst, msbit: 25, lsbit: 10) + (Bits32(bits: inst, msbit: 4, lsbit: 0) << 16);
272 uint64_t rj_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rj, fail_value: 0, success_ptr: &success);
273 if (!success)
274 return false;
275 if (rj_val == 0) {
276 uint64_t next_pc = pc + llvm::SignExtend64<23>(x: offs21 << 2);
277 return WritePC(addr: next_pc);
278 } else
279 return WritePC(addr: pc + 4);
280}
281
282// bnez rj, offs21
283// if GR[rj] != 0:
284// PC = PC + SignExtend({offs21, 2'b0}, GRLEN)
285bool EmulateInstructionLoongArch::EmulateBNEZ64(uint32_t inst) {
286 bool success = false;
287 uint32_t rj = Bits32(bits: inst, msbit: 9, lsbit: 5);
288
289 auto addr = ReadPC();
290 if (!addr)
291 return false;
292 uint64_t pc = *addr;
293
294 uint32_t offs21 = Bits32(bits: inst, msbit: 25, lsbit: 10) + (Bits32(bits: inst, msbit: 4, lsbit: 0) << 16);
295 uint64_t rj_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rj, fail_value: 0, success_ptr: &success);
296 if (!success)
297 return false;
298 if (rj_val != 0) {
299 uint64_t next_pc = pc + llvm::SignExtend64<23>(x: offs21 << 2);
300 return WritePC(addr: next_pc);
301 } else
302 return WritePC(addr: pc + 4);
303}
304
305// bceqz cj, offs21
306// if CFR[cj] == 0:
307// PC = PC + SignExtend({offs21, 2'b0}, GRLEN)
308bool EmulateInstructionLoongArch::EmulateBCEQZ64(uint32_t inst) {
309 bool success = false;
310 uint32_t cj = Bits32(bits: inst, msbit: 7, lsbit: 5) + fpr_fcc0_loongarch;
311
312 auto addr = ReadPC();
313 if (!addr)
314 return false;
315 uint64_t pc = *addr;
316
317 uint32_t offs21 = Bits32(bits: inst, msbit: 25, lsbit: 10) + (Bits32(bits: inst, msbit: 4, lsbit: 0) << 16);
318 uint8_t cj_val =
319 (uint8_t)ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: cj, fail_value: 0, success_ptr: &success);
320 if (!success)
321 return false;
322 if (cj_val == 0) {
323 uint64_t next_pc = pc + llvm::SignExtend64<23>(x: offs21 << 2);
324 return WritePC(addr: next_pc);
325 } else
326 return WritePC(addr: pc + 4);
327 return false;
328}
329
330// bcnez cj, offs21
331// if CFR[cj] != 0:
332// PC = PC + SignExtend({offs21, 2'b0}, GRLEN)
333bool EmulateInstructionLoongArch::EmulateBCNEZ64(uint32_t inst) {
334 bool success = false;
335 uint32_t cj = Bits32(bits: inst, msbit: 7, lsbit: 5) + fpr_fcc0_loongarch;
336
337 auto addr = ReadPC();
338 if (!addr)
339 return false;
340 uint64_t pc = *addr;
341
342 uint32_t offs21 = Bits32(bits: inst, msbit: 25, lsbit: 10) + (Bits32(bits: inst, msbit: 4, lsbit: 0) << 16);
343 uint8_t cj_val =
344 (uint8_t)ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: cj, fail_value: 0, success_ptr: &success);
345 if (!success)
346 return false;
347 if (cj_val != 0) {
348 uint64_t next_pc = pc + llvm::SignExtend64<23>(x: offs21 << 2);
349 return WritePC(addr: next_pc);
350 } else
351 return WritePC(addr: pc + 4);
352 return false;
353}
354
355// jirl rd, rj, offs16
356// GR[rd] = PC + 4
357// PC = GR[rj] + SignExtend({offs16, 2'b0}, GRLEN)
358bool EmulateInstructionLoongArch::EmulateJIRL64(uint32_t inst) {
359 uint32_t rj = Bits32(bits: inst, msbit: 9, lsbit: 5);
360 uint32_t rd = Bits32(bits: inst, msbit: 4, lsbit: 0);
361 bool success = false;
362
363 auto addr = ReadPC();
364 if (!addr)
365 return false;
366 uint64_t pc = *addr;
367
368 EmulateInstruction::Context ctx;
369 if (!WriteRegisterUnsigned(context: ctx, reg_kind: eRegisterKindLLDB, reg_num: rd, reg_value: pc + 4))
370 return false;
371 uint64_t rj_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rj, fail_value: 0, success_ptr: &success);
372 if (!success)
373 return false;
374 uint64_t next_pc = rj_val + llvm::SignExtend64<18>(x: Bits32(bits: inst, msbit: 25, lsbit: 10) << 2);
375 return WritePC(addr: next_pc);
376}
377
378// b offs26
379// PC = PC + SignExtend({offs26, 2' b0}, GRLEN)
380bool EmulateInstructionLoongArch::EmulateB64(uint32_t inst) {
381 auto addr = ReadPC();
382 if (!addr)
383 return false;
384 uint64_t pc = *addr;
385
386 uint32_t offs26 = Bits32(bits: inst, msbit: 25, lsbit: 10) + (Bits32(bits: inst, msbit: 9, lsbit: 0) << 16);
387 uint64_t next_pc = pc + llvm::SignExtend64<28>(x: offs26 << 2);
388 return WritePC(addr: next_pc);
389}
390
391// bl offs26
392// GR[1] = PC + 4
393// PC = PC + SignExtend({offs26, 2'b0}, GRLEN)
394bool EmulateInstructionLoongArch::EmulateBL64(uint32_t inst) {
395 auto addr = ReadPC();
396 if (!addr)
397 return false;
398 uint64_t pc = *addr;
399
400 EmulateInstruction::Context ctx;
401 if (!WriteRegisterUnsigned(context: ctx, reg_kind: eRegisterKindLLDB, reg_num: gpr_r1_loongarch, reg_value: pc + 4))
402 return false;
403 uint32_t offs26 = Bits32(bits: inst, msbit: 25, lsbit: 10) + (Bits32(bits: inst, msbit: 9, lsbit: 0) << 16);
404 uint64_t next_pc = pc + llvm::SignExtend64<28>(x: offs26 << 2);
405 return WritePC(addr: next_pc);
406}
407
408// beq rj, rd, offs16
409// if GR[rj] == GR[rd]:
410// PC = PC + SignExtend({offs16, 2'b0}, GRLEN)
411bool EmulateInstructionLoongArch::EmulateBEQ64(uint32_t inst) {
412 bool success = false;
413 uint32_t rj = Bits32(bits: inst, msbit: 9, lsbit: 5);
414 uint32_t rd = Bits32(bits: inst, msbit: 4, lsbit: 0);
415
416 auto addr = ReadPC();
417 if (!addr)
418 return false;
419 uint64_t pc = *addr;
420
421 uint64_t rj_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rj, fail_value: 0, success_ptr: &success);
422 if (!success)
423 return false;
424 uint64_t rd_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rd, fail_value: 0, success_ptr: &success);
425 if (!success)
426 return false;
427 if (rj_val == rd_val) {
428 uint64_t next_pc = pc + llvm::SignExtend64<18>(x: Bits32(bits: inst, msbit: 25, lsbit: 10) << 2);
429 return WritePC(addr: next_pc);
430 } else
431 return WritePC(addr: pc + 4);
432}
433
434// bne rj, rd, offs16
435// if GR[rj] != GR[rd]:
436// PC = PC + SignExtend({offs16, 2'b0}, GRLEN)
437bool EmulateInstructionLoongArch::EmulateBNE64(uint32_t inst) {
438 bool success = false;
439 uint32_t rj = Bits32(bits: inst, msbit: 9, lsbit: 5);
440 uint32_t rd = Bits32(bits: inst, msbit: 4, lsbit: 0);
441
442 auto addr = ReadPC();
443 if (!addr)
444 return false;
445 uint64_t pc = *addr;
446
447 uint64_t rj_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rj, fail_value: 0, success_ptr: &success);
448 if (!success)
449 return false;
450 uint64_t rd_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rd, fail_value: 0, success_ptr: &success);
451 if (!success)
452 return false;
453 if (rj_val != rd_val) {
454 uint64_t next_pc = pc + llvm::SignExtend64<18>(x: Bits32(bits: inst, msbit: 25, lsbit: 10) << 2);
455 return WritePC(addr: next_pc);
456 } else
457 return WritePC(addr: pc + 4);
458}
459
460// blt rj, rd, offs16
461// if signed(GR[rj]) < signed(GR[rd]):
462// PC = PC + SignExtend({offs16, 2'b0}, GRLEN)
463bool EmulateInstructionLoongArch::EmulateBLT64(uint32_t inst) {
464 bool success = false;
465 uint32_t rj = Bits32(bits: inst, msbit: 9, lsbit: 5);
466 uint32_t rd = Bits32(bits: inst, msbit: 4, lsbit: 0);
467
468 auto addr = ReadPC();
469 if (!addr)
470 return false;
471 uint64_t pc = *addr;
472
473 int64_t rj_val =
474 (int64_t)ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rj, fail_value: 0, success_ptr: &success);
475 if (!success)
476 return false;
477 int64_t rd_val =
478 (int64_t)ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rd, fail_value: 0, success_ptr: &success);
479 if (!success)
480 return false;
481 if (rj_val < rd_val) {
482 uint64_t next_pc = pc + llvm::SignExtend64<18>(x: Bits32(bits: inst, msbit: 25, lsbit: 10) << 2);
483 return WritePC(addr: next_pc);
484 } else
485 return WritePC(addr: pc + 4);
486}
487
488// bge rj, rd, offs16
489// if signed(GR[rj]) >= signed(GR[rd]):
490// PC = PC + SignExtend({offs16, 2'b0}, GRLEN)
491bool EmulateInstructionLoongArch::EmulateBGE64(uint32_t inst) {
492 bool success = false;
493 uint32_t rj = Bits32(bits: inst, msbit: 9, lsbit: 5);
494 uint32_t rd = Bits32(bits: inst, msbit: 4, lsbit: 0);
495
496 auto addr = ReadPC();
497 if (!addr)
498 return false;
499 uint64_t pc = *addr;
500
501 int64_t rj_val =
502 (int64_t)ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rj, fail_value: 0, success_ptr: &success);
503 if (!success)
504 return false;
505 int64_t rd_val =
506 (int64_t)ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rd, fail_value: 0, success_ptr: &success);
507 if (!success)
508 return false;
509 if (rj_val >= rd_val) {
510 uint64_t next_pc = pc + llvm::SignExtend64<18>(x: Bits32(bits: inst, msbit: 25, lsbit: 10) << 2);
511 return WritePC(addr: next_pc);
512 } else
513 return WritePC(addr: pc + 4);
514}
515
516// bltu rj, rd, offs16
517// if unsigned(GR[rj]) < unsigned(GR[rd]):
518// PC = PC + SignExtend({offs16, 2'b0}, GRLEN)
519bool EmulateInstructionLoongArch::EmulateBLTU64(uint32_t inst) {
520 bool success = false;
521 uint32_t rj = Bits32(bits: inst, msbit: 9, lsbit: 5);
522 uint32_t rd = Bits32(bits: inst, msbit: 4, lsbit: 0);
523
524 auto addr = ReadPC();
525 if (!addr)
526 return false;
527 uint64_t pc = *addr;
528
529 uint64_t rj_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rj, fail_value: 0, success_ptr: &success);
530 if (!success)
531 return false;
532 uint64_t rd_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rd, fail_value: 0, success_ptr: &success);
533 if (!success)
534 return false;
535 if (rj_val < rd_val) {
536 uint64_t next_pc = pc + llvm::SignExtend64<18>(x: Bits32(bits: inst, msbit: 25, lsbit: 10) << 2);
537 return WritePC(addr: next_pc);
538 } else
539 return WritePC(addr: pc + 4);
540}
541
542// bgeu rj, rd, offs16
543// if unsigned(GR[rj]) >= unsigned(GR[rd]):
544// PC = PC + SignExtend({offs16, 2'b0}, GRLEN)
545bool EmulateInstructionLoongArch::EmulateBGEU64(uint32_t inst) {
546 bool success = false;
547 uint32_t rj = Bits32(bits: inst, msbit: 9, lsbit: 5);
548 uint32_t rd = Bits32(bits: inst, msbit: 4, lsbit: 0);
549
550 auto addr = ReadPC();
551 if (!addr)
552 return false;
553 uint64_t pc = *addr;
554
555 uint64_t rj_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rj, fail_value: 0, success_ptr: &success);
556 if (!success)
557 return false;
558 uint64_t rd_val = ReadRegisterUnsigned(reg_kind: eRegisterKindLLDB, reg_num: rd, fail_value: 0, success_ptr: &success);
559 if (!success)
560 return false;
561 if (rj_val >= rd_val) {
562 uint64_t next_pc = pc + llvm::SignExtend64<18>(x: Bits32(bits: inst, msbit: 25, lsbit: 10) << 2);
563 return WritePC(addr: next_pc);
564 } else
565 return WritePC(addr: pc + 4);
566}
567
568} // namespace lldb_private
569

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