static UInt32 parse_prefixes(long offset, ref INSTRUCTION instr, INTERNAL_DATA idata, byte ext_table_index, byte ext_pref_index, ref DISASM_INOUT_PARAMS param)
{
byte pref_code;
byte rex_found;
byte pref_id;
byte pref_index;
UInt32 res;
UInt32 tmp;
OPCODE_DESCRIPTOR ptr;
res = 0;
rex_found = 0;
while(true)
{
//pref_code = *offset;
pref_code = assembly.Image.ReadBytes(offset, 1)[0];
if (res > MAX_INSTRUCTION_LEN)
{
idata.severe_err = ERRS.ERR_TOO_LONG;//error: instruction too long.
break;
}
ptr = tables[IDX_1BYTE].opcodes[pref_code];
if ( !( ((ptr.groups & GRP_PREFIX)!=0) ||
(param.mode == DISMODE.DISASSEMBLE_MODE_64 && (pref_code >= 0x40) && (pref_code <= 0x4F) && (rex_found == 0))))
{
break;
}
else
{
if (rex_found!=0)
{
idata.severe_err = ERRS.ERR_REX_NOOPCD;//error: an opcode should follow after rex.
break;
}
if ((rex_found != 0) && (param.mode == DISMODE.DISASSEMBLE_MODE_64))
{
if ( (pref_code >= 0x40) && (pref_code <= 0x4F) )
{
idata.prefixes[PREF_REX_INDEX] = PREF_REX_ID;
instr.rex = pref_code;
rex_found = 1;
res++;
offset++;
continue;
}
}
tmp = tq_handlers[ptr.ops[0].type](0, 0, ref instr, 0, new OPERAND_SIZE(), new INTERNAL_DATA(), param.mode);
pref_index = (byte)(tmp >> 8);
pref_id = (byte)tmp;// &0xFF;
if (idata.prefixes[pref_index] != 0xFF)
{
add_sf_prefix(idata.prefixes, pref_index, ref instr, ref param);
}
idata.prefixes[pref_index] = pref_id;
//Used later for prefix table switch.
if (ptr.id == ID_66 || ptr.id == ID_REPZ || ptr.id == ID_REPNZ)
{
ext_table_index =(byte)(ptr.props);
ext_pref_index = pref_index;
}
res++;
offset++;
}
}
return res;
}