Skip to content

Commit e993302

Browse files
committed
LoongArch: Compute absolute address for address operand
To match behavior with other archs, compute absolute address instead of relative for address operands. Fixes capstone-engine#2689.
1 parent 42fbce6 commit e993302

File tree

3 files changed

+98
-0
lines changed

3 files changed

+98
-0
lines changed

arch/LoongArch/LoongArchInstPrinter.c

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,31 @@ static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
100100
}
101101

102102
if (MCOperand_isImm(MO)) {
103+
// rewrite offset immediate operand to absolute address in direct branch instructions
104+
// convert e.g.
105+
// 0x1000: beqz $t0, 0xc
106+
// to:
107+
// 0x1000: beqz $t0, 0x100c
108+
switch (MI->flat_insn->id) {
109+
case LOONGARCH_INS_B:
110+
case LOONGARCH_INS_BCEQZ:
111+
case LOONGARCH_INS_BCNEZ:
112+
case LOONGARCH_INS_BEQ:
113+
case LOONGARCH_INS_BEQZ:
114+
case LOONGARCH_INS_BGE:
115+
case LOONGARCH_INS_BGEU:
116+
case LOONGARCH_INS_BL:
117+
case LOONGARCH_INS_BLT:
118+
case LOONGARCH_INS_BLTU:
119+
case LOONGARCH_INS_BNE:
120+
case LOONGARCH_INS_BNEZ:
121+
printInt64(O, MCOperand_getImm(MO) + MI->address);
122+
return;
123+
124+
default:
125+
break;
126+
}
127+
103128
printInt64(O, MCOperand_getImm(MO));
104129
return;
105130
}

arch/LoongArch/LoongArchMapping.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,49 @@ void LoongArch_rewrite_memory_operand(MCInst *MI)
324324
}
325325
}
326326

327+
void LoongArch_rewrite_address_operand(MCInst *MI)
328+
{
329+
// rewrite offset immediate operand to absolute address in direct branch instructions
330+
// convert e.g.
331+
// 0x1000: beqz $t0, 0x100c
332+
// op_count: 2
333+
// operands[0].type: REG = t0
334+
// operands[0].access: READ
335+
// operands[1].type: IMM = 0xc
336+
// operands[1].access: READ
337+
// to:
338+
// op_count: 2
339+
// operands[0].type: REG = t0
340+
// operands[0].access: READ
341+
// operands[1].type: IMM = 0x100c
342+
// operands[1].access: READ
343+
344+
if (!detail_is_set(MI))
345+
return;
346+
347+
// handle different types of branch instructions
348+
switch (MI->flat_insn->id) {
349+
case LOONGARCH_INS_B:
350+
case LOONGARCH_INS_BCEQZ:
351+
case LOONGARCH_INS_BCNEZ:
352+
case LOONGARCH_INS_BEQ:
353+
case LOONGARCH_INS_BEQZ:
354+
case LOONGARCH_INS_BGE:
355+
case LOONGARCH_INS_BGEU:
356+
case LOONGARCH_INS_BL:
357+
case LOONGARCH_INS_BLT:
358+
case LOONGARCH_INS_BLTU:
359+
case LOONGARCH_INS_BNE:
360+
case LOONGARCH_INS_BNEZ:
361+
// last operand is address operand
362+
LoongArch_get_detail_op(MI, -1)->imm += MI->address;
363+
return;
364+
365+
default:
366+
break;
367+
}
368+
}
369+
327370
void LoongArch_set_instr_map_data(MCInst *MI)
328371
{
329372
map_cs_id(MI, loongarch_insns, ARR_SIZE(loongarch_insns));
@@ -432,6 +475,7 @@ void LoongArch_printer(MCInst *MI, SStream *O,
432475
LoongArch_LLVM_printInst(MI, MI->address, "", O);
433476

434477
LoongArch_rewrite_memory_operand(MI);
478+
LoongArch_rewrite_address_operand(MI);
435479
LoongArch_add_cs_groups(MI);
436480
#ifndef CAPSTONE_DIET
437481
map_set_alias_id(MI, O, insn_alias_mnem_map,

tests/details/loongarch.yaml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,3 +120,32 @@ test_cases:
120120
type: LOONGARCH_OP_IMM
121121
imm: 0x0
122122
groups: [ LOONGARCH_GRP_JUMP ]
123+
-
124+
input:
125+
bytes: [ 0x80, 0x0d, 0x00, 0x40, 0x00, 0xec, 0x0b, 0x54 ]
126+
arch: "loongarch"
127+
options: [ CS_OPT_DETAIL, CS_MODE_LOONGARCH64]
128+
address: 0x1000
129+
expected:
130+
insns:
131+
-
132+
asm_text: "beqz $t0, 0x100c"
133+
details:
134+
loongarch:
135+
operands:
136+
-
137+
type: LOONGARCH_OP_REG
138+
reg: t0
139+
-
140+
type: LOONGARCH_OP_IMM
141+
imm: 0x100c
142+
groups: [ LOONGARCH_GRP_JUMP, LOONGARCH_GRP_BRANCH_RELATIVE ]
143+
-
144+
asm_text: "bl 0x1bf0"
145+
details:
146+
loongarch:
147+
operands:
148+
-
149+
type: LOONGARCH_OP_IMM
150+
imm: 0x1bf0
151+
groups: [ LOONGARCH_GRP_CALL ]

0 commit comments

Comments
 (0)