diff --git a/api/docs/release.dox b/api/docs/release.dox
index 13312174afd..199355300e1 100644
--- a/api/docs/release.dox
+++ b/api/docs/release.dox
@@ -129,7 +129,8 @@ changes:
- No compatibility changes yet.
Further non-compatibility-affecting changes include:
- - No changes yet.
+ - Added instr_get_operation_size() and instr_set_operation_size() APIs for
+ #DR_ISA_REGDEPS #instr_t.
**************************************************
diff --git a/core/ir/instr_api.h b/core/ir/instr_api.h
index 33f46c809b9..2dff45a4a42 100644
--- a/core/ir/instr_api.h
+++ b/core/ir/instr_api.h
@@ -1995,6 +1995,22 @@ DR_API
instr_t *
instr_convert_short_meta_jmp_to_long(void *drcontext, instrlist_t *ilist, instr_t *instr);
+DR_API
+/**
+ * Returns the operation size of \p instr if it's a #DR_ISA_REGDEPS instruction, #OPSZ_NA
+ * otherwise.
+ */
+opnd_size_t
+instr_get_operation_size(instr_t *instr);
+
+DR_API
+/**
+ * Sets the operation size of \p instr to \p operation_size only if instr is a
+ * #DR_ISA_REGDEPS instruction.
+ */
+void
+instr_set_operation_size(instr_t *instr, opnd_size_t operation_size);
+
DR_API
/**
* Converts a real ISA (e.g., #DR_ISA_AMD64) instruction \p instr_real_isa into a
diff --git a/core/ir/instr_shared.c b/core/ir/instr_shared.c
index d61ab038787..89df9c237e2 100644
--- a/core/ir/instr_shared.c
+++ b/core/ir/instr_shared.c
@@ -2999,6 +2999,27 @@ instr_uses_fp_reg(instr_t *instr)
return false;
}
+opnd_size_t
+instr_get_operation_size(instr_t *instr)
+{
+ /* Only DR_ISA_REGDEPS instructions can have an operation_size.
+ */
+ if (instr_get_isa_mode(instr) == DR_ISA_REGDEPS)
+ return instr->operation_size;
+
+ return OPSZ_NA;
+}
+
+void
+instr_set_operation_size(instr_t *instr, opnd_size_t operation_size)
+{
+ CLIENT_ASSERT(instr_get_isa_mode(instr) != DR_ISA_REGDEPS,
+ "instr_set_operation_size: only DR_ISA_REGDEPS instructions can have "
+ "an operation_size");
+ instr->operation_size = operation_size;
+ return;
+}
+
void
instr_convert_to_isa_regdeps(void *drcontext, instr_t *instr_real_isa,
instr_t *instr_regdeps_isa)
@@ -3097,10 +3118,14 @@ instr_convert_to_isa_regdeps(void *drcontext, instr_t *instr_real_isa,
instr_set_category(instr_regdeps_isa, instr_get_category(instr_real_isa));
/* Convert max_src_opnd_size_bytes from number of bytes to opnd_size_t (which holds
- * OPSZ_ enum values).
+ * OPSZ_ enum values). If we have no operands, operation_size is OPSZ_0, same as a
+ * decoded DR_ISA_REGDEPS instruction.
*/
opnd_size_t max_opnd_size = opnd_size_from_bytes(max_src_opnd_size_bytes);
- instr_regdeps_isa->operation_size = max_opnd_size;
+ if (num_dsts + num_srcs > 0)
+ instr_regdeps_isa->operation_size = max_opnd_size;
+ else
+ instr_regdeps_isa->operation_size = OPSZ_0;
/* Set the source and destination register operands for the converted instruction.
*/
diff --git a/suite/tests/api/ir_regdeps.c b/suite/tests/api/ir_regdeps.c
index 739336840db..b4da7795ef7 100644
--- a/suite/tests/api/ir_regdeps.c
+++ b/suite/tests/api/ir_regdeps.c
@@ -108,11 +108,23 @@ test_instr_encode_decode_disassemble_synthetic(void *dc, instr_t *instr,
byte *next_pc_decode = decode(dc, bytes, instr_synthetic_decoded);
ASSERT(next_pc_decode != NULL);
ASSERT(next_pc_encode == next_pc_decode);
+
+ /* Check instruction length.
+ */
+ ASSERT((next_pc_encode - bytes) == instr_length(dc, instr_synthetic_decoded));
+ ASSERT(instr_length(dc, instr_synthetic_decoded) != 0);
+
/* Check for overflow.
*/
ASSERT((next_pc_encode - bytes) <= sizeof(bytes));
ASSERT((next_pc_decode - bytes) <= sizeof(bytes));
+ /* Check operation size.
+ */
+ ASSERT(instr_get_operation_size(instr_synthetic_decoded) != OPSZ_NA);
+ ASSERT(instr_get_operation_size(instr_synthetic_decoded) ==
+ instr_get_operation_size(instr_synthetic_converted));
+
/* Disassemble regdeps synthetic encodings to buffer.
*/
char dbuf[512];