Первая моя наивная попытка добавить их самостоятельно провалилась с позором. Например пишем в x86optable.xml скажем для
psignb
что-нть такое:
<instruction mnemonic="psignb">
<opcode> aso rexr rexx rexb ; sse66 0f 38 08 ; V W </opcode>
<opcode> aso rexr rexx rexb ; 0f 38 08 ; P Q </opcode>
</instruction>
компилируем и смотрим itab.c
И например видим что дескрипторы для инструкции попали в таблицы ud_itab_entry itab__0f & itab__pfx_sse66__0f
Впрочем такой вариант тоже не работает:
<instruction mnemonic="psignb">
<opcode> aso rexr rexx rexb ; sse66 0f sse38 08 ; V W </opcode>
<opcode> aso rexr rexx rexb ; 0f sse38 08 ; P Q </opcode>
</instruction>
Похоже что текущая реализация opgen.py не поддерживает opcodes длиннее 3х байт. Добавить же нужно следующие инструкции
# SSSE3
psignb (66) 0f 38 08 /r
psignw (66) 0f 38 09 /r
psignd (66) 0f 38 0A /r
pshufb (66) 0F 38 00 /r
pmulhrsw (66) 0F 38 0B /r
pmaddubsw (66) 0F 38 04 /r
phsubsw (66) 0F 38 07 /r
phaddsw (66) 0F 38 03 /r
phaddw (66) 0F 38 01 /r
phaddd (66) 0F 38 02 /r
phsubw (66) 0F 38 05 /r
phsubd (66) 0F 38 06 /r
palignr (66) 0F 3A 0F /r ib
pabsb (66) 0F 38 1C /r
pabsw (66) 0F 38 1D /r
pabsd (66) 0F 38 1E /r
# SSE4
blendpd 66 0F 3A 0D /r ib
blendps 66 0F 3A 0C /r ib
blendvpd 66 0F 38 15 /r
blendvps 66 0F 38 14 /r
dppd 66 0F 3A 41 /r ib
dpps 66 0F 3A 40 /r ib
extractps 66 0F 3A 17 /r ib
insertps 66 0F 3A 21 /r ib
movntdqa 66 0F 38 2A /r
mpsadbw 66 0F 3A 42 /r ib
packusdw 66 0F 38 2B /r
pblendvb 66 0F 38 10 /r
pblendw 66 0F 3A 0E /r ib
pextrb 66 0F 3A 14 /r ib
pextrd 66 0F 3A 16 /r ib
phminposuw 66 0F 38 41 /r
pinsrb 66 0F 3A 20 /r ib
pinsrd 66 0F 3A 22 /r ib
pmaxsb 66 0F 38 3C /r
pmaxsd 66 0F 38 3D /r
pmaxud 66 0F 38 3F /r
pmaxuw 66 0F 38 3E /r
pminsb 66 0F 38 38 /r
pminsd 66 0F 38 39 /r
pminud 66 0F 38 3B /r
pminuw 66 0F 38 3A /r
pmovsxbw 66 0f 38 20 /r
pmovsxbd 66 0f 38 21 /r
pmovsxbq 66 0f 38 22 /r
pmovsxwd 66 0f 38 23 /r
pmovsxwq 66 0f 38 24 /r
pmovsxdq 66 0f 38 25 /r
pmovzxbw 66 0f 38 30 /r
pmovzxbd 66 0f 38 31 /r
pmovzxbq 66 0f 38 32 /r
pmovzxwd 66 0f 38 33 /r
pmovzxwq 66 0f 38 34 /r
pmovzxdq 66 0f 38 35 /r
pmuldq 66 0F 38 28 /r
pmulld 66 0F 38 40 /r
ptest 66 0F 38 17 /r
roundpd 66 0F 3A 09 /r ib
roundps 66 0F 3A 08 /r ib
roundsd 66 0F 3A 0B /r ib
roundss 66 0F 3A 0A /r ib
Если внимательно помедитировать на эту табличку, то можно сделать вывод что нам нужны 4 таблицы по 256 элементов каждая:
- 0f 38 XX - таблица ITAB__PFX_SSE38
- 0f 3a XX - таблица ITAB__PFX_SSE3A - самая кстати наименее заполненная - там будет дескриптор для всего одной инструкции palignr
- 66 0f 38 XX - таблица ITAB__PFX_SSE66__SSE38
- 66 0f 3a XX - таблица ITAB__PFX_SSE66__SSE3A
if ( 0x66 == u->pfx_insn ) {
if ( (curr == 0x38) || (curr == 0x3A) )
{
table = (curr == 0x38) ? ITAB__PFX_SSE66__SSE38 : ITAB__PFX_SSE66__SSE3A;
curr = inp_next(u);
if ( u->error )
return -1;
u->pfx_opr = 0;
}
else if ( ud_itab_list[ ITAB__PFX_SSE66__0F ][ curr ].mnemonic != UD_Iinvalid ) {
table = ITAB__PFX_SSE66__0F;
u->pfx_opr = 0;
}
...
else if ( (curr == 0x38) || (curr == 0x3A) )
{
table = (curr == 0x38) ? ITAB__PFX_SSE38 : ITAB__PFX_SSE3A;
curr = inp_next(u);
if ( u->error )
return -1;
}
Первый if проверят что зачитаны 66 & 0f и текущий байт - либо 38 либо 3a, и устанавливает соотв-щую таблицу opcodes.
Второй if проверяет что зачитан 0f и текущий байт в свою очередь тоже 38 или 3a.
Теперь нам нужно сказать opgen.py сгенерировать эти четыре таблицы. Есс-но это можно сделать бесчисленным множеством способом, я выбрал специальную обработку для opcodes sse38 & sse3A:
if op == 'SSE3A' or op == 'SSE38':
# we can have two kind of table - when there already was some sse prefix (like 66)
# or not. In first case table name will be itab__pfx_SSE__[3a|38]
# In last case (SSSE3 mostly) itab__pfx__[3a|38]
if len(old_sse_tab):
table_name = "itab__pfx_%s__%s" % (old_sse_tab, op)
else:
table_name = "itab__pfx_%s" % op
table_sse = op
table_size = 256
was38_3a = 1
elif op[0:3] == 'SSE':
table_sse = op
old_sse_tab = op
elif op == '0F' and len(table_sse) and was38_3a == 0:
table_name = "itab__pfx_%s__0f" % table_sse
table_size = 256
table_sse = ''
elif op == '0F' and was38_3a == 0:
table_name = "itab__0f"
table_size = 256
IMHO тут все просто и самодокументированно. Единственная сложная вещь - специальная обработка байта 0f. Если снова внимательно посмотреть на табличку с opcodes, то можно увидеть, что инструкция palignr имеет 0f последним байтом. Соотв-но нужно проверить что данная 0f встретилась после sse38 или sse3a и тогда не делать ничего
sources on sourceforge
Update: добавил сегодня инструкции pcmpeqq, pcmpgtq, pclmulqdq & movbe
ты написал на питоне??
ОтветитьУдалитьтам был уже готовый транслятор с мета-языка в таблицы plain C
ОтветитьУдалитьно вообще я обычно знаю языки и технологии, над которыми глумлюсь, так что поцчему ви удивляетесь ?