Coverage Report

Created: 2023-09-30 09:22

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