2
%%% Copyright (C) 2000-2004 Mikael Pettersson
3
%%% Copyright (C) 2004 Daniel Luna
5
%%% This is the syntax of amd64 r/m operands:
7
%%% opnd ::= reg mod == 11
8
%%% | MEM[ea] mod != 11
10
%%% ea ::= disp32(reg) mod == 10, r/m != ESP
11
%%% | disp32 sib12 mod == 10, r/m == 100
12
%%% | disp8(reg) mod == 01, r/m != ESP
13
%%% | disp8 sib12 mod == 01, r/m == 100
14
%%% | (reg) mod == 00, r/m != ESP and EBP
15
%%% | sib0 mod == 00, r/m == 100
16
%%% | disp32(%rip) mod == 00, r/m == 101
18
%%% // sib0: mod == 00
19
%%% sib0 ::= disp32(,index,scale) base == EBP, index != ESP
20
%%% | disp32 base == EBP, index == 100
21
%%% | (base,index,scale) base != EBP, index != ESP
22
%%% | (base) base != EBP, index == 100
24
%%% // sib12: mod == 01 or 10
25
%%% sib12 ::= (base,index,scale) index != ESP
26
%%% | (base) index == 100
28
%%% scale ::= 00 | 01 | 10 | 11 index << scale
32
%%% 1. ESP cannot be used as index register.
33
%%% 2. Use of ESP as base register requires a SIB byte.
34
%%% 3. disp(reg), when reg != ESP, can be represented without
35
%%% [r/m == reg] or with [r/m == 100, base == reg] a SIB byte.
36
%%% 4. disp32 can be represented without [mod == 00, r/m == 101]
37
%%% or with [mod == 00, r/m == 100, base == 101, index == 100]
39
%%% 5. AMD64 and x86 interpret mod==00b r/m==101b EAs differently:
40
%%% on x86 the disp32 is an absolute address, but on AMD64 the
41
%%% disp32 is relative to the %rip of the next instruction.
43
-module(hipe_amd64_encode).
45
-export([% condition codes
48
%% al/0, cl/0, dl/0, bl/0, ah/0, ch/0, dh/0, bh/0,
50
%% eax/0, ecx/0, edx/0, ebx/0, esp/0, ebp/0, esi/0, edi/0,
52
sindex/2, sib/1, sib/2,
53
ea_disp32_base/2, ea_disp32_sib/2,
54
ea_disp8_base/2, ea_disp8_sib/2,
56
ea_disp32_sindex/1, %%ea_disp32_sindex/2,
57
ea_sib/1, %ea_disp32_rip/1,
60
insn_encode/3, insn_sizeof/2]).
62
%%-define(DO_HIPE_AMD64_ENCODE_TEST,true).
63
-ifdef(DO_HIPE_AMD64_ENCODE_TEST).
64
-export([dotest/0, dotest/1]). % for testing, don't use
67
-define(ASSERT(F,G), if G -> [] ; true -> exit({?MODULE,F}) end).
68
%-define(ASSERT(F,G), []).
72
-define(CC_O, 2#0000). % overflow
73
-define(CC_NO, 2#0001). % no overflow
74
-define(CC_B, 2#0010). % below, <u
75
-define(CC_AE, 2#0011). % above or equal, >=u
76
-define(CC_E, 2#0100). % equal
77
-define(CC_NE, 2#0101). % not equal
78
-define(CC_BE, 2#0110). % below or equal, <=u
79
-define(CC_A, 2#0111). % above, >u
80
-define(CC_S, 2#1000). % sign, +
81
-define(CC_NS, 2#1001). % not sign, -
82
-define(CC_PE, 2#1010). % parity even
83
-define(CC_PO, 2#1011). % parity odd
84
-define(CC_L, 2#1100). % less than, <s
85
-define(CC_GE, 2#1101). % greater or equal, >=s
86
-define(CC_LE, 2#1110). % less or equal, <=s
87
-define(CC_G, 2#1111). % greater than, >s
148
sindex(Scale, Index) ->
149
?ASSERT(sindex, Scale >= 0),
150
?ASSERT(sindex, Scale =< 3),
151
?ASSERT(sindex, Index =/= ?ESP),
152
{sindex, Scale, Index}.
154
-record(sib, {sindex_opt, base}).
155
sib(Base) -> #sib{sindex_opt=none, base=Base}.
156
sib(Base, Sindex) -> #sib{sindex_opt=Sindex, base=Base}.
158
ea_disp32_base(Disp32, Base) ->
159
?ASSERT(ea_disp32_base, Base =/= ?ESP),
160
{ea_disp32_base, Disp32, Base}.
161
ea_disp32_sib(Disp32, SIB) -> {ea_disp32_sib, Disp32, SIB}.
162
ea_disp8_base(Disp8, Base) ->
163
?ASSERT(ea_disp8_base, Base =/= ?ESP),
164
{ea_disp8_base, Disp8, Base}.
165
ea_disp8_sib(Disp8, SIB) -> {ea_disp8_sib, Disp8, SIB}.
167
?ASSERT(ea_base, Base =/= ?ESP),
168
?ASSERT(ea_base, Base =/= ?EBP),
170
ea_disp32_sindex(Disp32) -> {ea_disp32_sindex, Disp32, none}.
171
%% ea_disp32_sindex(Disp32, Sindex) -> {ea_disp32_sindex, Disp32, Sindex}.
173
?ASSERT(ea_sib, SIB#sib.base =/= ?EBP),
175
%ea_disp32_rip(Disp32) -> {ea_disp32_rip, Disp32}.
177
rm_reg(Reg) -> {rm_reg, Reg}.
178
rm_mem(EA) -> {rm_mem, EA}.
180
mk_modrm(Mod, RO, RM) ->
181
{rex([{r,RO}, {b,RM}]),
182
(Mod bsl 6) bor ((RO band 2#111) bsl 3) bor (RM band 2#111)}.
184
mk_sib(Scale, Index, Base) ->
185
{rex([{x,Index}, {b,Base}]),
186
(Scale bsl 6) bor ((Index band 2#111) bsl 3) bor (Base band 2#111)}.
188
rex(REXs) -> {rex, rex_(REXs)}.
190
rex_([{r8, Reg8}| Rest]) -> % 8 bit registers
192
{rm_mem, _} -> rex_(Rest);
193
4 -> (1 bsl 8) bor rex_(Rest);
194
5 -> (1 bsl 8) bor rex_(Rest);
195
6 -> (1 bsl 8) bor rex_(Rest);
196
7 -> (1 bsl 8) bor rex_(Rest);
197
X when is_integer(X) -> rex_(Rest)
199
rex_([{w, REXW}| Rest]) -> % 64-bit mode
200
(REXW bsl 3) bor rex_(Rest);
201
rex_([{r, ModRM_regRegister}| Rest]) -> % ModRM reg
202
REXR = if (ModRM_regRegister > 7) -> 1;
205
(REXR bsl 2) bor rex_(Rest);
206
rex_([{x, SIB_indexRegister}| Rest]) -> % SIB index
207
REXX = if (SIB_indexRegister > 7) -> 1;
210
(REXX bsl 1) bor rex_(Rest);
211
rex_([{b, OtherRegister}| Rest]) -> % ModRM r/m, SIB base or opcode reg
212
REXB = if (OtherRegister > 7) -> 1;
218
[Word band 16#FF, (Word bsr 8) band 16#FF | Tail].
220
le32(Word, Tail) when is_integer(Word) ->
221
[Word band 16#FF, (Word bsr 8) band 16#FF,
222
(Word bsr 16) band 16#FF, (Word bsr 24) band 16#FF | Tail];
223
le32({Tag,Val}, Tail) -> % a relocatable datum
224
[{le32,Tag,Val} | Tail].
226
le64(Word, Tail) when is_integer(Word) ->
227
[ Word band 16#FF, (Word bsr 8) band 16#FF,
228
(Word bsr 16) band 16#FF, (Word bsr 24) band 16#FF,
229
(Word bsr 32) band 16#FF, (Word bsr 40) band 16#FF,
230
(Word bsr 48) band 16#FF, (Word bsr 56) band 16#FF | Tail];
231
le64({Tag,Val}, Tail) ->
232
[{le64,Tag,Val} | Tail].
234
enc_sindex_opt({sindex,Scale,Index}) -> {Scale, Index};
235
enc_sindex_opt(none) -> {2#00, 2#100}.
237
enc_sib(#sib{sindex_opt=SindexOpt, base=Base}) ->
238
{Scale, Index} = enc_sindex_opt(SindexOpt),
239
mk_sib(Scale, Index, Base).
241
enc_ea(EA, RO, Tail) ->
243
{ea_disp32_base, Disp32, Base} ->
244
[mk_modrm(2#10, RO, Base) | le32(Disp32, Tail)];
245
{ea_disp32_sib, Disp32, SIB} ->
246
[mk_modrm(2#10, RO, 2#100), enc_sib(SIB) | le32(Disp32, Tail)];
247
{ea_disp8_base, Disp8, Base} ->
248
[mk_modrm(2#01, RO, Base), Disp8 | Tail];
249
{ea_disp8_sib, Disp8, SIB} ->
250
[mk_modrm(2#01, RO, 2#100), enc_sib(SIB), Disp8 | Tail];
252
[mk_modrm(2#00, RO, Base) | Tail];
253
{ea_disp32_sindex, Disp32, SindexOpt} ->
254
{Scale, Index} = enc_sindex_opt(SindexOpt),
255
SIB = mk_sib(Scale, Index, 2#101),
256
MODRM = mk_modrm(2#00, RO, 2#100),
257
[MODRM, SIB | le32(Disp32, Tail)];
259
[mk_modrm(2#00, RO, 2#100), enc_sib(SIB) | Tail];
260
{ea_disp32_rip, Disp32} ->
261
[mk_modrm(2#00, RO, 2#101) | le32(Disp32, Tail)]
264
encode_rm(RM, RO, Tail) ->
266
{rm_reg, Reg} -> [mk_modrm(2#11, RO, Reg) | Tail];
267
{rm_mem, EA} -> enc_ea(EA, RO, Tail)
271
%% case element(1, EA) of
272
%% ea_disp32_base -> 5;
273
%% ea_disp32_sib -> 6;
274
%% ea_disp8_base -> 2;
275
%% ea_disp8_sib -> 3;
277
%% ea_disp32_sindex -> 6;
279
%% ea_disp32_rip -> 5
285
%% {rm_mem, EA} -> sizeof_ea(EA)
288
%%% x87 stack postitions
311
%%% Insn ::= {Op,Opnds}
312
%%% Opnds ::= {Opnd1,...,Opndn} (n >= 0)
313
%%% Opnd ::= eax | ax | al | 1 | cl
314
%%% | {imm32,Imm32} | {imm16,Imm16} | {imm8,Imm8}
315
%%% | {rm32,RM32} | {rm16,RM16} | {rm8,RM8}
316
%%% | {rel32,Rel32} | {rel8,Rel8}
317
%%% | {moffs32,Moffs32} | {moffs16,Moffs16} | {moffs8,Moffs8}
319
%%% | {reg32,Reg32} | {reg16,Reg16} | {reg8,Reg8}
322
-define(PFX_OPND_16BITS, 16#66).
324
arith_binop_encode(SubOpcode, Opnds) ->
325
%% add, or, adc, sbb, and, sub, xor, cmp
327
{eax, {imm32,Imm32}} ->
328
[16#05 bor (SubOpcode bsl 3) | le32(Imm32, [])];
329
{{rm32,RM32}, {imm32,Imm32}} ->
330
[16#81 | encode_rm(RM32, SubOpcode, le32(Imm32, []))];
331
{{rm32,RM32}, {imm8,Imm8}} ->
332
[16#83 | encode_rm(RM32, SubOpcode, [Imm8])];
333
{{rm32,RM32}, {reg32,Reg32}} ->
334
[16#01 bor (SubOpcode bsl 3) | encode_rm(RM32, Reg32, [])];
335
{{reg32,Reg32}, {rm32,RM32}} ->
336
[16#03 bor (SubOpcode bsl 3) | encode_rm(RM32, Reg32, [])];
337
%% Below starts amd64 stuff with rex prefix
338
{rax, {imm32,Imm32}} ->
339
[rex([{w,1}]), 16#05 bor (SubOpcode bsl 3) | le32(Imm32, [])];
340
{{rm64,RM64}, {imm32,Imm32}} ->
342
| encode_rm(RM64, SubOpcode, le32(Imm32, []))];
343
{{rm64,RM64}, {imm8,Imm8}} ->
344
[rex([{w,1}]), 16#83 | encode_rm(RM64, SubOpcode, [Imm8])];
345
{{rm64,RM64}, {reg64,Reg64}} ->
346
[rex([{w,1}]), 16#01 bor (SubOpcode bsl 3)
347
| encode_rm(RM64, Reg64, [])];
348
{{reg64,Reg64}, {rm64,RM64}} ->
349
[rex([{w,1}]), 16#03 bor (SubOpcode bsl 3)
350
| encode_rm(RM64, Reg64, [])]
353
sse2_arith_binop_encode(Prefix, Opcode, {{xmm, XMM64}, {rm64fp, RM64}}) ->
354
%% addpd, cmpsd, divsd, maxsd, minsd, mulsd, sqrtsd, subsd
355
[Prefix, 16#0F, Opcode | encode_rm(RM64, XMM64, [])].
357
sse2_cvtsi2sd_encode({{xmm,XMM64}, {rm64,RM64}}) ->
358
[rex([{w, 1}]), 16#F2, 16#0F, 16#2A�| encode_rm(RM64, XMM64, [])].
360
sse2_mov_encode(Opnds) ->
362
{{xmm, XMM64}, {rm64fp, RM64}} -> % movsd
363
[16#F2, 16#0F, 16#10�| encode_rm(RM64, XMM64, [])];
364
{{rm64fp, RM64}, {xmm, XMM64}} -> % movsd
365
[16#F2, 16#0F, 16#11�| encode_rm(RM64, XMM64, [])]
366
% {{xmm, XMM64}, {rm64, RM64}} -> % cvtsi2sd
367
% [rex([{w, 1}]), 16#F2, 16#0F, 16#2A�| encode_rm(RM64, XMM64, [])]
370
%% arith_binop_sizeof(Opnds) ->
371
%% %% add, or, adc, sbb, and, sub, xor, cmp
373
%% {eax, {imm32,_}} ->
375
%% {{rm32,RM32}, {imm32,_}} ->
376
%% 1 + sizeof_rm(RM32) + 4;
377
%% {{rm32,RM32}, {imm8,_}} ->
378
%% 1 + sizeof_rm(RM32) + 1;
379
%% {{rm32,RM32}, {reg32,_}} ->
380
%% 1 + sizeof_rm(RM32);
381
%% {{reg32,_}, {rm32,RM32}} ->
382
%% 1 + sizeof_rm(RM32)
385
bs_op_encode(Opcode, {{reg32,Reg32}, {rm32,RM32}}) -> % bsf, bsr
386
[16#0F, Opcode | encode_rm(RM32, Reg32, [])].
388
%% bs_op_sizeof({{reg32,_}, {rm32,RM32}}) -> % bsf, bsr
389
%% 2 + sizeof_rm(RM32).
391
bswap_encode(Opnds) ->
394
[rex([{b, Reg32}]), 16#0F, 16#C8 bor (Reg32 band 2#111)];
396
[rex([{w, 1}, {b, Reg64}]), 16#0F, 16#C8 bor (Reg64 band 2#111)]
399
%% bswap_sizeof({{reg32,_}}) ->
402
bt_op_encode(SubOpcode, Opnds) -> % bt, btc, btr, bts
404
{{rm32,RM32}, {reg32,Reg32}} ->
405
[16#0F, 16#A3 bor (SubOpcode bsl 3) | encode_rm(RM32, Reg32, [])];
406
{{rm32,RM32}, {imm8,Imm8}} ->
407
[16#0F, 16#BA | encode_rm(RM32, SubOpcode, [Imm8])]
410
%% bt_op_sizeof(Opnds) -> % bt, btc, btr, bts
412
%% {{rm32,RM32}, {reg32,_}} ->
413
%% 2 + sizeof_rm(RM32);
414
%% {{rm32,RM32}, {imm8,_}} ->
415
%% 2 + sizeof_rm(RM32) + 1
418
call_encode(Opnds) ->
421
[16#E8 | le32(Rel32, [])];
423
%%% [16#FF | encode_rm(RM32, 2#010, [])];
424
{{rm64,RM64}} -> % Defaults to 64 bits on amd64
425
[16#FF | encode_rm(RM64, 2#010, [])]
428
%% call_sizeof(Opnds) ->
433
%% 1 + sizeof_rm(RM32)
437
[?PFX_OPND_16BITS, 16#98].
442
nullary_op_encode(Opcode, {}) ->
443
%% cdq, clc, cld, cmc, cwde, into, leave, nop, prefix_fs, stc, std
446
nullary_op_sizeof({}) ->
447
%% cdq, clc, cld, cmc, cwde, into, leave, nop, prefix_fs, stc, std
450
cmovcc_encode({{cc,CC}, {reg32,Reg32}, {rm32,RM32}}) ->
451
[16#0F, 16#40 bor CC | encode_rm(RM32, Reg32, [])].
453
%% cmovcc_sizeof({{cc,_}, {reg32,_}, {rm32,RM32}}) ->
454
%% 2 + sizeof_rm(RM32).
456
incdec_encode(SubOpcode, Opnds) -> % SubOpcode is either 0 or 1
459
[16#FF | encode_rm(RM32, SubOpcode, [])];
461
[rex([{w, 1}]), 16#FF | encode_rm(RM64, SubOpcode, [])]
464
%% incdec_sizeof(Opnds) ->
467
%% 1 + sizeof_rm(RM32);
472
arith_unop_encode(Opcode, Opnds) -> % div, idiv, mul, neg, not
475
[16#F7 | encode_rm(RM32, Opcode, [])];
477
[rex([{w,1}]), 16#F7 | encode_rm(RM64, Opcode, [])]
480
%% arith_unop_sizeof({{rm32,RM32}}) -> % div, idiv, mul, neg, not
481
%% 1 + sizeof_rm(RM32).
483
enter_encode({{imm16,Imm16}, {imm8,Imm8}}) ->
484
[16#C8 | le16(Imm16, [Imm8])].
486
enter_sizeof({{imm16,_}, {imm8,_}}) ->
489
imul_encode(Opnds) ->
491
{{rm32,RM32}} -> % <edx,eax> *= rm32
492
[16#F7 | encode_rm(RM32, 2#101, [])];
493
{{reg32,Reg32}, {rm32,RM32}} -> % reg *= rm32
494
[16#0F, 16#AF | encode_rm(RM32, Reg32, [])];
495
{{reg32,Reg32}, {rm32,RM32}, {imm8,Imm8}} -> % reg := rm32 * sext(imm8)
496
[16#6B | encode_rm(RM32, Reg32, [Imm8])];
497
{{reg32,Reg32}, {rm32,RM32}, {imm32,Imm32}} -> % reg := rm32 * imm32
498
[16#69 | encode_rm(RM32, Reg32, le32(Imm32, []))]
501
%% imul_sizeof(Opnds) ->
504
%% 1 + sizeof_rm(RM32);
505
%% {{reg32,_}, {rm32,RM32}} ->
506
%% 2 + sizeof_rm(RM32);
507
%% {{reg32,_}, {rm32,RM32}, {imm8,_}} ->
508
%% 1 + sizeof_rm(RM32) + 1;
509
%% {{reg32,_}, {rm32,RM32}, {imm32,_}} ->
510
%% 1 + sizeof_rm(RM32) + 4
515
{{cc,CC}, {rel8,Rel8}} ->
516
[16#70 bor CC, Rel8];
517
{{cc,CC}, {rel32,Rel32}} ->
518
[16#0F, 16#80 bor CC | le32(Rel32, [])]
523
{{cc,_}, {rel8,_}} ->
525
{{cc,_}, {rel32,_}} ->
529
jmp8_op_encode(Opcode, {{rel8,Rel8}}) -> % jecxz, loop, loope, loopne
532
jmp8_op_sizeof({{rel8,_}}) -> % jecxz, loop, loope, loopne
540
[16#E9 | le32(Rel32, [])];
542
%%% [16#FF | encode_rm(RM32, 2#100, [])]
544
[16#FF | encode_rm(RM64, 2#100, [])]
547
%% jmp_sizeof(Opnds) ->
554
%% 1 + sizeof_rm(RM32)
557
lea_encode({{reg32,Reg32}, {ea,EA}}) ->
558
[16#8D | enc_ea(EA, Reg32, [])];
559
lea_encode({{reg64,Reg64}, {ea,EA}}) ->
560
[rex([{w, 1}]), 16#8D | enc_ea(EA, Reg64, [])].
562
%% lea_sizeof({{reg32,_}, {ea,EA}}) ->
563
%% 1 + sizeof_ea(EA).
567
{{rm8,RM8}, {reg8,Reg8}} ->
568
[rex([{r8, RM8}, {r8, Reg8}]), 16#88 | encode_rm(RM8, Reg8, [])];
569
{{rm16,RM16}, {reg16,Reg16}} ->
570
[?PFX_OPND_16BITS, 16#89 | encode_rm(RM16, Reg16, [])];
571
{{rm32,RM32}, {reg32,Reg32}} ->
572
[16#89 | encode_rm(RM32, Reg32, [])];
573
{{rm64,RM64}, {reg64,Reg64}} ->
574
[rex([{w, 1}]), 16#89 | encode_rm(RM64, Reg64, [])];
575
{{reg8,Reg8}, {rm8,RM8}} ->
576
[rex([{r8, RM8}, {r8, Reg8}]), 16#8A |
577
encode_rm(RM8, Reg8, [])];
578
{{reg16,Reg16}, {rm16,RM16}} ->
579
[?PFX_OPND_16BITS, 16#8B | encode_rm(RM16, Reg16, [])];
580
{{reg32,Reg32}, {rm32,RM32}} ->
581
[16#8B | encode_rm(RM32, Reg32, [])];
582
{{reg64,Reg64}, {rm64,RM64}} ->
583
[rex([{w, 1}]), 16#8B | encode_rm(RM64, Reg64, [])];
584
{al, {moffs8,Moffs8}} ->
585
[16#A0 | le32(Moffs8, [])];
586
{ax, {moffs16,Moffs16}} ->
587
[?PFX_OPND_16BITS, 16#A1 | le32(Moffs16, [])];
588
{eax, {moffs32,Moffs32}} ->
589
[16#A1 | le32(Moffs32, [])];
590
{rax, {moffs32,Moffs32}} ->
591
[rex([{w, 1}]), 16#A1 | le32(Moffs32, [])];
592
{{moffs8,Moffs8}, al} ->
593
[16#A2 | le32(Moffs8, [])];
594
{{moffs16,Moffs16}, ax} ->
595
[?PFX_OPND_16BITS, 16#A3 | le32(Moffs16, [])];
596
{{moffs32,Moffs32}, eax} ->
597
[16#A3 | le32(Moffs32, [])];
598
{{moffs32,Moffs32}, rax} ->
599
[rex([{w, 1}]), 16#A3 | le32(Moffs32, [])];
600
{{reg8,Reg8}, {imm8,Imm8}} ->
601
[rex([{b, Reg8}, {r8, Reg8}]), 16#B0 bor (Reg8 band 2#111), Imm8];
602
{{reg16,Reg16}, {imm16,Imm16}} ->
603
[?PFX_OPND_16BITS, rex([{b, Reg16}]), 16#B8 bor (Reg16 band 2#111)
605
{{reg32,Reg32}, {imm32,Imm32}} ->
606
[rex([{b, Reg32}]), 16#B8 bor (Reg32 band 2#111)
608
{{reg64,Reg64}, {imm64,Imm64}} ->
609
[rex([{w, 1}, {b, Reg64}]), 16#B8 bor (Reg64 band 2#111)
611
{{rm8,RM8}, {imm8,Imm8}} ->
612
[rex([{r8, RM8}]), 16#C6 | encode_rm(RM8, 2#000, [Imm8])];
613
{{rm16,RM16}, {imm16,Imm16}} ->
614
[?PFX_OPND_16BITS, 16#C7 |
615
encode_rm(RM16, 2#000, le16(Imm16, []))];
616
{{rm32,RM32}, {imm32,Imm32}} ->
617
[16#C7 | encode_rm(RM32, 2#000, le32(Imm32, []))];
618
{{rm64,RM64}, {imm32,Imm32}} ->
619
[rex([{w, 1}]), 16#C7 | encode_rm(RM64, 2#000, le32(Imm32, []))]
622
%% mov_sizeof(Opnds) ->
624
%% {{rm8,RM8}, {reg8,_}} ->
625
%% 1 + sizeof_rm(RM8);
626
%% {{rm16,RM16}, {reg16,_}} ->
627
%% 2 + sizeof_rm(RM16);
628
%% {{rm32,RM32}, {reg32,_}} ->
629
%% 1 + sizeof_rm(RM32);
630
%% {{reg8,_}, {rm8,RM8}} ->
631
%% 1 + sizeof_rm(RM8);
632
%% {{reg16,_}, {rm16,RM16}} ->
633
%% 2 + sizeof_rm(RM16);
634
%% {{reg32,_}, {rm32,RM32}} ->
635
%% 1 + sizeof_rm(RM32);
636
%% {al, {moffs8,_}} ->
638
%% {ax, {moffs16,_}} ->
640
%% {eax, {moffs32,_}} ->
642
%% {{moffs8,_}, al} ->
644
%% {{moffs16,_}, ax} ->
646
%% {{moffs32,_}, eax} ->
648
%% {{reg8,_}, {imm8,_}} ->
650
%% {{reg16,_}, {imm16,_}} ->
652
%% {{reg32,_}, {imm32,_}} ->
654
%% {{rm8,RM8}, {imm8,_}} ->
655
%% 1 + sizeof_rm(RM8) + 1;
656
%% {{rm16,RM16}, {imm16,_}} ->
657
%% 2 + sizeof_rm(RM16) + 2;
658
%% {{rm32,RM32}, {imm32,_}} ->
659
%% 1 + sizeof_rm(RM32) + 4
662
movx_op_encode(Opcode, Opnds) -> % movsx, movzx
664
{{reg16,Reg16}, {rm8,RM8}} ->
665
[?PFX_OPND_16BITS, rex([{r8, RM8}]), 16#0F, Opcode |
666
encode_rm(RM8, Reg16, [])];
667
{{reg32,Reg32}, {rm8,RM8}} ->
668
[rex([{r8, RM8}]), 16#0F, Opcode | encode_rm(RM8, Reg32, [])];
669
{{reg32,Reg32}, {rm16,RM16}} ->
670
[16#0F, Opcode bor 1 | encode_rm(RM16, Reg32, [])];
671
{{reg64,Reg64}, {rm8,RM8}} ->
672
[rex([{w,1}]), 16#0F, Opcode | encode_rm(RM8, Reg64, [])];
673
{{reg64,Reg64}, {rm16,RM16}} ->
674
[rex([{w,1}]), 16#0F, Opcode bor 1 | encode_rm(RM16, Reg64, [])];
675
{{reg64,Reg64}, {rm32,RM32}} ->
676
%% This is magic... /Luna
677
[rex([{w,(1 band (Opcode bsr 3))}]), 16#63 |
678
encode_rm(RM32, Reg64, [])]
681
%% movx_op_sizeof(Opnds) ->
683
%% {{reg16,_}, {rm8,RM8}} ->
684
%% 3 + sizeof_rm(RM8);
685
%% {{reg32,_}, {rm8,RM8}} ->
686
%% 1 + 2 + sizeof_rm(RM8);
687
%% {{reg32,_}, {rm16,RM16}} ->
688
%% 1 + 2 + sizeof_rm(RM16)
694
[16#8F | encode_rm(RM64, 2#000, [])];
696
[rex([{b,Reg64}]),16#58 bor (Reg64 band 2#111)]
699
%% pop_sizeof(Opnds) ->
702
%% 1 + sizeof_rm(RM32);
707
push_encode(Opnds) ->
710
%%% [16#FF | encode_rm(RM32, 2#110, [])];
712
[16#FF | encode_rm(RM64, 2#110, [])];
713
%%% {{reg32,Reg32}} ->
714
%%% [rex([{b, 1}]), 16#50 bor (Reg32 band 2#111)];
716
[rex([{b, Reg64}]), 16#50 bor (Reg64 band 2#111)];
717
{{imm8,Imm8}} -> % sign-extended
719
{{imm32,Imm32}} -> % Sign extended to 64 bits
720
[16#68 | le32(Imm32, [])]
723
%% push_sizeof(Opnds) ->
726
%% 1 + sizeof_rm(RM32);
735
shift_op_encode(SubOpcode, Opnds) -> % rol, ror, rcl, rcr, shl, shr, sar
738
[16#D1 | encode_rm(RM32, SubOpcode, [])];
740
[16#D3 | encode_rm(RM32, SubOpcode, [])];
741
{{rm32,RM32}, {imm8,Imm8}} ->
742
[16#C1 | encode_rm(RM32, SubOpcode, [Imm8])];
744
[rex([{w,1}]), 16#D1 | encode_rm(RM64, SubOpcode, [])];
746
[rex([{w,1}]), 16#D3 | encode_rm(RM64, SubOpcode, [])];
747
{{rm64,RM64}, {imm8,Imm8}} ->
748
[rex([{w,1}]), 16#C1 | encode_rm(RM64, SubOpcode, [Imm8])]
751
%% shift_op_sizeof(Opnds) -> % rcl, rcr, rol, ror, sar, shl, shr
753
%% {{rm32,RM32}, 1} ->
754
%% 1 + sizeof_rm(RM32);
755
%% {{rm32,RM32}, cl} ->
756
%% 1 + sizeof_rm(RM32);
757
%% {{rm32,RM32}, {imm8,_Imm8}} ->
758
%% 1 + sizeof_rm(RM32) + 1
766
[16#C2 | le16(Imm16, [])]
777
setcc_encode({{cc,CC}, {rm8,RM8}}) ->
778
[rex([{r8, RM8}]), 16#0F, 16#90 bor CC | encode_rm(RM8, 2#000, [])].
780
%% setcc_sizeof({{cc,_}, {rm8,RM8}}) ->
781
%% 2 + sizeof_rm(RM8).
783
shd_op_encode(Opcode, Opnds) ->
785
{{rm32,RM32}, {reg32,Reg32}, {imm8,Imm8}} ->
786
[16#0F, Opcode | encode_rm(RM32, Reg32, [Imm8])];
787
{{rm32,RM32}, {reg32,Reg32}, cl} ->
788
[16#0F, Opcode bor 1 | encode_rm(RM32, Reg32, [])]
791
%% shd_op_sizeof(Opnds) ->
793
%% {{rm32,RM32}, {reg32,_}, {imm8,_}} ->
794
%% 2 + sizeof_rm(RM32) + 1;
795
%% {{rm32,RM32}, {reg32,_}, cl} ->
796
%% 2 + sizeof_rm(RM32)
799
test_encode(Opnds) ->
801
{eax, {imm32,Imm32}} ->
802
[16#A9 | le32(Imm32, [])];
803
{{rm32,RM32}, {imm32,Imm32}} ->
804
[16#F7 | encode_rm(RM32, 2#000, le32(Imm32, []))];
805
{{rm32,RM32}, {reg32,Reg32}} ->
806
[16#85 | encode_rm(RM32, Reg32, [])]
809
%% test_sizeof(Opnds) ->
811
%% {eax, {imm32,_}} ->
813
%% {{rm32,RM32}, {imm32,_}} ->
814
%% 1 + sizeof_rm(RM32) + 4;
815
%% {{rm32,RM32}, {reg32,_}} ->
816
%% 1 + sizeof_rm(RM32)
819
fild_encode(Opnds) ->
820
%% The operand cannot be a register!
821
{{rm64, RM64}} = Opnds,
822
[16#DB | encode_rm(RM64, 2#000, [])].
824
%% fild_sizeof(Opnds) ->
825
%% {{rm32, RM32}} = Opnds,
826
%% 1 + sizeof_rm(RM32).
830
{{rm64fp, RM64fp}} ->
831
[16#DD | encode_rm(RM64fp, 2#000, [])];
833
[16#D9, 16#C0 bor st(St)]
836
%% fld_sizeof(Opnds) ->
838
%% {{rm64fp, RM64fp}} ->
839
%% 1 + sizeof_rm(RM64fp);
844
x87_comm_arith_encode(OpCode, Opnds) ->
847
{{rm64fp, RM64fp}} ->
848
[16#DC | encode_rm(RM64fp, OpCode, [])];
849
{{fpst,0}, {fpst,St}} ->
850
[16#D8, (16#C0 bor (OpCode bsl 3)) bor st(St)];
851
{{fpst,St}, {fpst,0}} ->
852
[16#DC, (16#C0 bor (OpCode bsl 3)) bor st(St)]
855
x87_comm_arith_pop_encode(OpCode, Opnds) ->
859
[16#DE, 16#C0 bor (OpCode bsl 3) bor st(1)];
860
{{fpst,St},{fpst,0}} ->
861
[16#DE, 16#C0 bor (OpCode bsl 3) bor st(St)]
864
x87_arith_encode(OpCode, Opnds) ->
867
{{rm64fp, RM64fp}} ->
868
[16#DC | encode_rm(RM64fp, OpCode, [])];
869
{{fpst,0}, {fpst,St}} ->
870
OpCode0 = OpCode band 2#110,
871
[16#D8, 16#C0 bor (OpCode0 bsl 3) bor st(St)];
872
{{fpst,St}, {fpst,0}} ->
873
OpCode0 = OpCode bor 1,
874
[16#DC, 16#C0 bor (OpCode0 bsl 3) bor st(St)]
877
x87_arith_pop_encode(OpCode, Opnds) ->
879
OpCode0 = OpCode bor 1,
882
[16#DE, 16#C8 bor (OpCode0 bsl 3) bor st(1)];
883
{{fpst,St}, {fpst,0}} ->
884
[16#DE, 16#C8 bor (OpCode0 bsl 3) bor st(St)]
887
x87_arith_rev_encode(OpCode, Opnds) ->
890
{{rm64fp, RM64fp}} ->
891
[16#DC | encode_rm(RM64fp, OpCode, [])];
892
{{fpst,0}, {fpst,St}} ->
893
OpCode0 = OpCode bor 1,
894
[16#D8, 16#C0 bor (OpCode0 bsl 3) bor st(St)];
895
{{fpst,St}, {fpst,0}} ->
896
OpCode0 = OpCode band 2#110,
897
[16#DC, 16#C0 bor (OpCode0 bsl 3) bor st(St)]
900
x87_arith_rev_pop_encode(OpCode, Opnds) ->
902
OpCode0 = OpCode band 2#110,
905
[16#DE, 16#C0 bor (OpCode0 bsl 3) bor st(1)];
906
{{fpst,St}, {fpst, 0}} ->
907
[16#DE, 16#C0 bor (OpCode0 bsl 3) bor st(St)]
910
%% x87_arith_sizeof(Opnds) ->
912
%% {{rm64fp, RM64fp}} ->
913
%% 1 + sizeof_rm(RM64fp);
914
%% {{fpst,0}, {fpst,_}} ->
916
%% {{fpst,_}, {fpst,0}} ->
920
fst_encode(OpCode, Opnds) ->
922
{{rm64fp, RM64fp}} ->
923
[16#DD | encode_rm(RM64fp, OpCode, [])];
925
[16#DD, 16#C0 bor (OpCode bsl 3) bor st(St)]
928
%% fst_sizeof(Opnds) ->
930
%% {{rm64fp, RM64fp}} ->
931
%% 1 + sizeof_rm(RM64fp);
942
ffree_encode({{fpst, St}})->
943
[16#DD, 16#C0 bor st(St)].
954
fxch_encode(Opnds) ->
957
[16#D9, 16#C8 bor st(1)];
959
[16#D9, 16#C8 bor st(St)]
965
insn_encode(Op, Opnds, Offset) ->
966
Bytes_and_REX = insn_encode_internal(Op, Opnds),
967
Bytes = fix_rex(Bytes_and_REX),
968
case has_relocs(Bytes) of
969
false -> % the common case
972
fix_relocs(Bytes, Offset, [], [])
976
fix_rex(Bytes, 2#0100 bsl 4, []).
978
fix_rex([{rex, REX} | Rest], REXAcc, Bytes) ->
979
fix_rex(Rest, REXAcc bor REX, Bytes);
980
fix_rex([{{rex, REX}, Byte} | Rest], REXAcc, Bytes) ->
981
fix_rex(Rest, REXAcc bor REX, [Byte | Bytes]);
982
fix_rex([Byte | Rest], REXAcc, Bytes) ->
983
fix_rex(Rest, REXAcc, [Byte | Bytes]);
984
fix_rex([], 2#01000000, Bytes) -> % no rex prefix
985
lists:reverse(Bytes);
986
fix_rex([], REX0, Bytes) -> % rex prefix...
987
REX = REX0 band 16#FF, % for 8 bit registers
988
[Head|Tail] = lists:reverse(Bytes),
990
16#66 -> % ...and 16 bit/sse2 prefix
992
16#F2 -> % ...and sse2 prefix
998
has_relocs([{le32,_,_}|_]) -> true;
999
has_relocs([{le64,_,_}|_]) -> true;
1000
has_relocs([_|Bytes]) -> has_relocs(Bytes);
1001
has_relocs([]) -> false.
1003
fix_relocs([{le32,Tag,Val}|Bytes], Offset, Code, Relocs) ->
1004
fix_relocs(Bytes, Offset+4,
1005
[16#00, 16#00, 16#00, 16#00 | Code],
1006
[{Tag,Offset,Val}|Relocs]);
1007
fix_relocs([{le64,Tag,Val}|Bytes], Offset, Code, Relocs) ->
1008
fix_relocs(Bytes, Offset+8,
1009
[16#00, 16#00, 16#00, 16#00,
1010
16#00, 16#00, 16#00, 16#00 | Code],
1011
[{Tag,Offset,Val}|Relocs]);
1012
fix_relocs([Byte|Bytes], Offset, Code, Relocs) ->
1013
fix_relocs(Bytes, Offset+1, [Byte|Code], Relocs);
1014
fix_relocs([], _Offset, Code, Relocs) ->
1015
{lists:reverse(Code), lists:reverse(Relocs)}.
1017
insn_encode_internal(Op, Opnds) ->
1019
'adc' -> arith_binop_encode(2#010, Opnds);
1020
'add' -> arith_binop_encode(2#000, Opnds);
1021
'and' -> arith_binop_encode(2#100, Opnds);
1022
'bsf' -> bs_op_encode(16#BC, Opnds);
1023
'bsr' -> bs_op_encode(16#BD, Opnds);
1024
'bswap' -> bswap_encode(Opnds);
1025
'bt' -> bt_op_encode(2#100, Opnds);
1026
'btc' -> bt_op_encode(2#111, Opnds);
1027
'btr' -> bt_op_encode(2#110, Opnds);
1028
'bts' -> bt_op_encode(2#101, Opnds);
1029
'call' -> call_encode(Opnds);
1030
'cbw' -> cbw_encode(Opnds);
1031
'cdq' -> nullary_op_encode(16#99, Opnds);
1032
'clc' -> nullary_op_encode(16#F8, Opnds);
1033
'cld' -> nullary_op_encode(16#FC, Opnds);
1034
'cmc' -> nullary_op_encode(16#F5, Opnds);
1035
'cmovcc' -> cmovcc_encode(Opnds);
1036
'cmp' -> arith_binop_encode(2#111, Opnds);
1037
'cwde' -> nullary_op_encode(16#98, Opnds);
1038
'dec' -> incdec_encode(2#001, Opnds);
1039
'div' -> arith_unop_encode(2#110, Opnds);
1040
'enter' -> enter_encode(Opnds);
1041
'idiv' -> arith_unop_encode(2#111, Opnds);
1042
'imul' -> imul_encode(Opnds);
1043
'inc' -> incdec_encode(2#000, Opnds);
1044
'into' -> case get(hipe_target_arch) of
1045
x86 -> nullary_op_encode(16#CE, Opnds);
1046
amd64 -> exit({invalid_amd64_opcode,
1047
hipe_amd64_encode__erl})
1049
'jcc' -> jcc_encode(Opnds);
1050
'jecxz' -> jmp8_op_encode(16#E3, Opnds);
1051
'jmp' -> jmp_encode(Opnds);
1052
'lea' -> lea_encode(Opnds);
1053
'leave' -> nullary_op_encode(16#C9, Opnds);
1054
'loop' -> jmp8_op_encode(16#E2, Opnds);
1055
'loope' -> jmp8_op_encode(16#E1, Opnds);
1056
'loopne' -> jmp8_op_encode(16#E0, Opnds);
1057
'mov' -> mov_encode(Opnds);
1058
'movsx' -> movx_op_encode(16#BE, Opnds);
1059
'movzx' -> movx_op_encode(16#B6, Opnds);
1060
'mul' -> arith_unop_encode(2#100, Opnds);
1061
'neg' -> arith_unop_encode(2#011, Opnds);
1062
'nop' -> nullary_op_encode(16#90, Opnds);
1063
'not' -> arith_unop_encode(2#010, Opnds);
1064
'or' -> arith_binop_encode(2#001, Opnds);
1065
'pop' -> pop_encode(Opnds);
1066
'prefix_fs' -> nullary_op_encode(16#64, Opnds);
1067
'push' -> push_encode(Opnds);
1068
'rcl' -> shift_op_encode(2#010, Opnds);
1069
'rcr' -> shift_op_encode(2#011, Opnds);
1070
'ret' -> ret_encode(Opnds);
1071
'rol' -> shift_op_encode(2#000, Opnds);
1072
'ror' -> shift_op_encode(2#001, Opnds);
1073
'sar' -> shift_op_encode(2#111, Opnds);
1074
'sbb' -> arith_binop_encode(2#011, Opnds);
1075
'setcc' -> setcc_encode(Opnds);
1076
'shl' -> shift_op_encode(2#100, Opnds);
1077
'shld' -> shd_op_encode(16#A4, Opnds);
1078
'shr' -> shift_op_encode(2#101, Opnds);
1079
'shrd' -> shd_op_encode(16#AC, Opnds);
1080
'stc' -> nullary_op_encode(16#F9, Opnds);
1081
'std' -> nullary_op_encode(16#FD, Opnds);
1082
'sub' -> arith_binop_encode(2#101, Opnds);
1083
'test' -> test_encode(Opnds);
1084
'xor' -> arith_binop_encode(2#110, Opnds);
1087
'addsd' -> sse2_arith_binop_encode(16#F2, 16#58, Opnds);
1088
'cmpsd' -> sse2_arith_binop_encode(16#F2, 16#C2, Opnds);
1089
'comisd' -> sse2_arith_binop_encode(16#66, 16#2F, Opnds);
1090
'cvtsi2sd' -> sse2_cvtsi2sd_encode(Opnds);
1091
'divsd' -> sse2_arith_binop_encode(16#F2, 16#5E, Opnds);
1092
'maxsd' -> sse2_arith_binop_encode(16#F2, 16#5F, Opnds);
1093
'minsd' -> sse2_arith_binop_encode(16#F2, 16#5D, Opnds);
1094
'movsd' -> sse2_mov_encode(Opnds);
1095
'mulsd' -> sse2_arith_binop_encode(16#F2, 16#59, Opnds);
1096
'sqrtsd' -> sse2_arith_binop_encode(16#F2, 16#51, Opnds);
1097
'subsd' -> sse2_arith_binop_encode(16#F2, 16#5C, Opnds);
1098
'ucomisd' -> sse2_arith_binop_encode(16#66, 16#2E, Opnds);
1099
'xorpd' -> sse2_arith_binop_encode(16#66, 16#57, Opnds);
1103
'fadd' -> x87_comm_arith_encode(2#000, Opnds);
1104
'faddp' -> x87_comm_arith_pop_encode(2#000, Opnds);
1105
'fchs' -> fchs_encode();
1106
'fdiv' -> x87_arith_encode(2#110, Opnds);
1107
'fdivp' -> x87_arith_pop_encode(2#110, Opnds);
1108
'fdivr' -> x87_arith_rev_encode(2#111, Opnds);
1109
'fdivrp' -> x87_arith_rev_pop_encode(2#111, Opnds);
1110
'ffree' -> ffree_encode(Opnds);
1111
'fild' -> fild_encode(Opnds);
1112
'fld' -> fld_encode(Opnds);
1113
'fmul' -> x87_comm_arith_encode(2#001, Opnds);
1114
'fmulp' -> x87_comm_arith_pop_encode(2#001, Opnds);
1115
'fst' -> fst_encode(2#010, Opnds);
1116
'fstp' -> fst_encode(2#011, Opnds);
1117
'fsub' -> x87_arith_encode(2#100, Opnds);
1118
'fsubp' -> x87_arith_pop_encode(2#100, Opnds);
1119
'fsubr' -> x87_arith_rev_encode(2#101, Opnds);
1120
'fsubrp' -> x87_arith_rev_pop_encode(2#101, Opnds);
1121
'fwait' -> fwait_encode();
1122
'fxch' -> fxch_encode(Opnds);
1125
_ -> exit({?MODULE,insn_encode,Op})
1128
insn_sizeof(Op, Opnds) ->
1130
'cbw' -> cbw_sizeof(Opnds);
1131
'cdq' -> nullary_op_sizeof(Opnds);
1132
'clc' -> nullary_op_sizeof(Opnds);
1133
'cld' -> nullary_op_sizeof(Opnds);
1134
'cmc' -> nullary_op_sizeof(Opnds);
1135
'cwde' -> nullary_op_sizeof(Opnds);
1136
'enter' -> enter_sizeof(Opnds);
1137
'into' -> nullary_op_sizeof(Opnds);
1138
'jcc' -> jcc_sizeof(Opnds);
1139
'jecxz' -> jmp8_op_sizeof(Opnds);
1140
'leave' -> nullary_op_sizeof(Opnds);
1141
'loop' -> jmp8_op_sizeof(Opnds);
1142
'loope' -> jmp8_op_sizeof(Opnds);
1143
'loopne' -> jmp8_op_sizeof(Opnds);
1144
'nop' -> nullary_op_sizeof(Opnds);
1145
'prefix_fs' -> nullary_op_sizeof(Opnds);
1146
'ret' -> ret_sizeof(Opnds);
1147
'stc' -> nullary_op_sizeof(Opnds);
1148
'std' -> nullary_op_sizeof(Opnds);
1151
%% 'fadd' -> x87_arith_sizeof(Opnds);
1152
%% 'faddp' -> x87_arith_sizeof(Opnds);
1153
'fchs' -> fchs_sizeof();
1154
%% 'fdiv' -> x87_arith_sizeof(Opnds);
1155
%% 'fdivp' -> x87_arith_sizeof(Opnds);
1156
%% 'fdivr' -> x87_arith_sizeof(Opnds);
1157
%% 'fdivrp' -> x87_arith_sizeof(Opnds);
1158
'ffree' -> ffree_sizeof();
1159
%% 'fild' -> fild_sizeof(Opnds);
1160
%% 'fld' -> fld_sizeof(Opnds);
1161
%% 'fmul' -> x87_arith_sizeof(Opnds);
1162
%% 'fmulp' -> x87_arith_sizeof(Opnds);
1163
%% 'fst' -> fst_sizeof(Opnds);
1164
%% 'fstp' -> fst_sizeof(Opnds);
1165
%% 'fsub' -> x87_arith_sizeof(Opnds);
1166
%% 'fsubp' -> x87_arith_sizeof(Opnds);
1167
%% 'fsubr' -> x87_arith_sizeof(Opnds);
1168
%% 'fsubrp' -> x87_arith_sizeof(Opnds);
1169
'fwait' -> fwait_sizeof();
1170
'fxch' -> fxch_sizeof();
1172
_ -> %% Hack that is to be removed some day... Maybe...
1173
{Bytes, _} = insn_encode(Op, Opnds, 0),
1175
%% 'adc' -> arith_binop_sizeof(Opnds);
1176
%% 'add' -> arith_binop_sizeof(Opnds);
1177
%% 'and' -> arith_binop_sizeof(Opnds);
1178
%% 'bsf' -> bs_op_sizeof(Opnds);
1179
%% 'bsr' -> bs_op_sizeof(Opnds);
1180
%% 'bswap' -> bswap_sizeof(Opnds);
1181
%% 'bt' -> bt_op_sizeof(Opnds);
1182
%% 'btc' -> bt_op_sizeof(Opnds);
1183
%% 'btr' -> bt_op_sizeof(Opnds);
1184
%% 'bts' -> bt_op_sizeof(Opnds);
1185
%% 'call' -> call_sizeof(Opnds);
1186
%% 'cmovcc' -> cmovcc_sizeof(Opnds);
1187
%% 'cmp' -> arith_binop_sizeof(Opnds);
1188
%% 'dec' -> incdec_sizeof(Opnds);
1189
%% 'div' -> arith_unop_sizeof(Opnds);
1190
%% 'idiv' -> arith_unop_sizeof(Opnds);
1191
%% 'imul' -> imul_sizeof(Opnds);
1192
%% 'inc' -> incdec_sizeof(Opnds);
1193
%% 'jmp' -> jmp_sizeof(Opnds);
1194
%% 'lea' -> lea_sizeof(Opnds);
1195
%% 'mov' -> mov_sizeof(Opnds);
1196
%% 'movsx' -> movx_op_sizeof(Opnds);
1197
%% 'movzx' -> movx_op_sizeof(Opnds);
1198
%% 'mul' -> arith_unop_sizeof(Opnds);
1199
%% 'neg' -> arith_unop_sizeof(Opnds);
1200
%% 'not' -> arith_unop_sizeof(Opnds);
1201
%% 'or' -> arith_binop_sizeof(Opnds);
1202
%% 'pop' -> pop_sizeof(Opnds);
1203
%% 'push' -> push_sizeof(Opnds);
1204
%% 'rcl' -> shift_op_sizeof(Opnds);
1205
%% 'rcr' -> shift_op_sizeof(Opnds);
1206
%% 'rol' -> shift_op_sizeof(Opnds);
1207
%% 'ror' -> shift_op_sizeof(Opnds);
1208
%% 'sar' -> shift_op_sizeof(Opnds);
1209
%% 'sbb' -> arith_binop_sizeof(Opnds);
1210
%% 'setcc' -> setcc_sizeof(Opnds);
1211
%% 'shl' -> shift_op_sizeof(Opnds);
1212
%% 'shld' -> shd_op_sizeof(Opnds);
1213
%% 'shr' -> shift_op_sizeof(Opnds);
1214
%% 'shrd' -> shd_op_sizeof(Opnds);
1215
%% 'sub' -> arith_binop_sizeof(Opnds);
1216
%% 'test' -> test_sizeof(Opnds);
1217
%% 'xor' -> arith_binop_sizeof(Opnds);
1218
%% _ -> exit({?MODULE,insn_sizeof,Op})
1221
%%=====================================================================
1222
%% testing interface
1223
%%=====================================================================
1225
-ifdef(DO_HIPE_AMD64_ENCODE_TEST).
1228
file:write(OS, Str).
1231
Dig = Dig0 band 16#F,
1232
if Dig >= 16#A -> $A + (Dig - 16#A);
1236
say_byte(OS, Byte) ->
1238
say(OS, [digit16(Byte bsr 4)]),
1239
say(OS, [digit16(Byte)]).
1242
say(OS, "\t.text\n").
1244
say_bytes(OS, Byte0, Bytes0) ->
1245
say_byte(OS, Byte0),
1251
say_bytes(OS, Byte1, Bytes1)
1255
insn_sizeof(Op, Opnds),
1256
{[Byte|Bytes],[]} = insn_encode(Op, Opnds, 0),
1257
say(OS, "\t.byte "),
1258
say_bytes(OS, Byte, Bytes).
1262
% exercise all rm32 types
1263
t(OS,lea,{{reg32,?EAX},{ea,ea_disp32_rip(16#87654321)}}),
1264
t(OS,lea,{{reg32,?EAX},{ea,ea_sib(sib(?ECX))}}),
1265
t(OS,lea,{{reg32,?EAX},{ea,ea_sib(sib(?ECX,sindex(2#10,?EDI)))}}),
1266
t(OS,lea,{{reg32,?EAX},{ea,ea_disp32_sindex(16#87654321)}}),
1267
t(OS,lea,{{reg32,?EAX},{ea,ea_disp32_sindex(16#87654321,sindex(2#10,?EDI))}}),
1268
t(OS,lea,{{reg32,?EAX},{ea,ea_base(?ECX)}}),
1269
t(OS,lea,{{reg32,?EAX},{ea,ea_disp8_sib(16#03,sib(?ECX))}}),
1270
t(OS,lea,{{reg32,?EAX},{ea,ea_disp8_sib(16#03,sib(?ECX,sindex(2#10,?EDI)))}}),
1271
t(OS,lea,{{reg32,?EAX},{ea,ea_disp8_base(16#3,?ECX)}}),
1272
t(OS,lea,{{reg32,?EAX},{ea,ea_disp32_sib(16#87654321,sib(?ECX))}}),
1273
t(OS,lea,{{reg32,?EAX},{ea,ea_disp32_sib(16#87654321,sib(?ECX,sindex(2#10,?EDI)))}}),
1274
t(OS,lea,{{reg32,?EAX},{ea,ea_disp32_base(16#87654321,?EBP)}}),
1275
t(OS,call,{{rm32,rm_reg(?EAX)}}),
1276
t(OS,call,{{rm32,rm_mem(ea_disp32_sindex(16#87654321,sindex(2#10,?EDI)))}}),
1277
t(OS,call,{{rel32,-5}}),
1278
% default parameters for the tests below
1279
Word32 = 16#87654321,
1282
Imm32 = {imm32,Word32},
1283
Imm16 = {imm16,Word16},
1284
Imm8 = {imm8,Word8},
1285
RM32 = {rm32,rm_reg(?EDX)},
1286
RM16 = {rm16,rm_reg(?EDX)},
1287
RM8 = {rm8,rm_reg(?EDX)},
1288
Rel32 = {rel32,Word32},
1289
Rel8 = {rel8,Word8},
1290
Moffs32 = {moffs32,Word32},
1291
Moffs16 = {moffs16,Word32},
1292
Moffs8 = {moffs8,Word32},
1294
Reg32 = {reg32,?EAX},
1295
Reg16 = {reg16,?EAX},
1297
EA = {ea,ea_base(?ECX)},
1298
% exercise each instruction definition
1299
t(OS,'adc',{eax,Imm32}),
1300
t(OS,'adc',{RM32,Imm32}),
1301
t(OS,'adc',{RM32,Imm8}),
1302
t(OS,'adc',{RM32,Reg32}),
1303
t(OS,'adc',{Reg32,RM32}),
1304
t(OS,'add',{eax,Imm32}),
1305
t(OS,'add',{RM32,Imm32}),
1306
t(OS,'add',{RM32,Imm8}),
1307
t(OS,'add',{RM32,Reg32}),
1308
t(OS,'add',{Reg32,RM32}),
1309
t(OS,'and',{eax,Imm32}),
1310
t(OS,'and',{RM32,Imm32}),
1311
t(OS,'and',{RM32,Imm8}),
1312
t(OS,'and',{RM32,Reg32}),
1313
t(OS,'and',{Reg32,RM32}),
1314
t(OS,'bsf',{Reg32,RM32}),
1315
t(OS,'bsr',{Reg32,RM32}),
1316
t(OS,'bswap',{Reg32}),
1317
t(OS,'bt',{RM32,Reg32}),
1318
t(OS,'bt',{RM32,Imm8}),
1319
t(OS,'btc',{RM32,Reg32}),
1320
t(OS,'btc',{RM32,Imm8}),
1321
t(OS,'btr',{RM32,Reg32}),
1322
t(OS,'btr',{RM32,Imm8}),
1323
t(OS,'bts',{RM32,Reg32}),
1324
t(OS,'bts',{RM32,Imm8}),
1325
t(OS,'call',{Rel32}),
1326
t(OS,'call',{RM32}),
1332
t(OS,'cmovcc',{CC,Reg32,RM32}),
1333
t(OS,'cmp',{eax,Imm32}),
1334
t(OS,'cmp',{RM32,Imm32}),
1335
t(OS,'cmp',{RM32,Imm8}),
1336
t(OS,'cmp',{RM32,Reg32}),
1337
t(OS,'cmp',{Reg32,RM32}),
1340
t(OS,'dec',{Reg32}),
1342
t(OS,'enter',{Imm16,{imm8,3}}),
1343
t(OS,'idiv',{RM32}),
1344
t(OS,'imul',{RM32}),
1345
t(OS,'imul',{Reg32,RM32}),
1346
t(OS,'imul',{Reg32,RM32,Imm8}),
1347
t(OS,'imul',{Reg32,RM32,Imm32}),
1349
t(OS,'inc',{Reg32}),
1351
t(OS,'jcc',{CC,Rel8}),
1352
t(OS,'jcc',{CC,Rel32}),
1353
t(OS,'jecxz',{Rel8}),
1355
t(OS,'jmp',{Rel32}),
1357
t(OS,'lea',{Reg32,EA}),
1359
t(OS,'loop',{Rel8}),
1360
t(OS,'loope',{Rel8}),
1361
t(OS,'loopne',{Rel8}),
1362
t(OS,'mov',{RM8,Reg8}),
1363
t(OS,'mov',{RM16,Reg16}),
1364
t(OS,'mov',{RM32,Reg32}),
1365
t(OS,'mov',{Reg8,RM8}),
1366
t(OS,'mov',{Reg16,RM16}),
1367
t(OS,'mov',{Reg32,RM32}),
1368
t(OS,'mov',{al,Moffs8}),
1369
t(OS,'mov',{ax,Moffs16}),
1370
t(OS,'mov',{eax,Moffs32}),
1371
t(OS,'mov',{Moffs8,al}),
1372
t(OS,'mov',{Moffs16,ax}),
1373
t(OS,'mov',{Moffs32,eax}),
1374
t(OS,'mov',{Reg8,Imm8}),
1375
t(OS,'mov',{Reg16,Imm16}),
1376
t(OS,'mov',{Reg32,Imm32}),
1377
t(OS,'mov',{RM8,Imm8}),
1378
t(OS,'mov',{RM16,Imm16}),
1379
t(OS,'mov',{RM32,Imm32}),
1380
t(OS,'movsx',{Reg16,RM8}),
1381
t(OS,'movsx',{Reg32,RM8}),
1382
t(OS,'movsx',{Reg32,RM16}),
1383
t(OS,'movzx',{Reg16,RM8}),
1384
t(OS,'movzx',{Reg32,RM8}),
1385
t(OS,'movzx',{Reg32,RM16}),
1390
t(OS,'or',{eax,Imm32}),
1391
t(OS,'or',{RM32,Imm32}),
1392
t(OS,'or',{RM32,Imm8}),
1393
t(OS,'or',{RM32,Reg32}),
1394
t(OS,'or',{Reg32,RM32}),
1396
t(OS,'pop',{Reg32}),
1397
t(OS,'push',{RM32}),
1398
t(OS,'push',{Reg32}),
1399
t(OS,'push',{Imm8}),
1400
t(OS,'push',{Imm32}),
1401
t(OS,'rcl',{RM32,1}),
1402
t(OS,'rcl',{RM32,cl}),
1403
t(OS,'rcl',{RM32,Imm8}),
1404
t(OS,'rcr',{RM32,1}),
1405
t(OS,'rcr',{RM32,cl}),
1406
t(OS,'rcr',{RM32,Imm8}),
1408
t(OS,'ret',{Imm16}),
1409
t(OS,'rol',{RM32,1}),
1410
t(OS,'rol',{RM32,cl}),
1411
t(OS,'rol',{RM32,Imm8}),
1412
t(OS,'ror',{RM32,1}),
1413
t(OS,'ror',{RM32,cl}),
1414
t(OS,'ror',{RM32,Imm8}),
1415
t(OS,'sar',{RM32,1}),
1416
t(OS,'sar',{RM32,cl}),
1417
t(OS,'sar',{RM32,Imm8}),
1418
t(OS,'sbb',{eax,Imm32}),
1419
t(OS,'sbb',{RM32,Imm32}),
1420
t(OS,'sbb',{RM32,Imm8}),
1421
t(OS,'sbb',{RM32,Reg32}),
1422
t(OS,'sbb',{Reg32,RM32}),
1423
t(OS,'setcc',{CC,RM8}),
1424
t(OS,'shl',{RM32,1}),
1425
t(OS,'shl',{RM32,cl}),
1426
t(OS,'shl',{RM32,Imm8}),
1427
t(OS,'shld',{RM32,Reg32,Imm8}),
1428
t(OS,'shld',{RM32,Reg32,cl}),
1429
t(OS,'shr',{RM32,1}),
1430
t(OS,'shr',{RM32,cl}),
1431
t(OS,'shr',{RM32,Imm8}),
1432
t(OS,'shrd',{RM32,Reg32,Imm8}),
1433
t(OS,'shrd',{RM32,Reg32,cl}),
1436
t(OS,'sub',{eax,Imm32}),
1437
t(OS,'sub',{RM32,Imm32}),
1438
t(OS,'sub',{RM32,Imm8}),
1439
t(OS,'sub',{RM32,Reg32}),
1440
t(OS,'sub',{Reg32,RM32}),
1441
t(OS,'test',{eax,Imm32}),
1442
t(OS,'test',{RM32,Imm32}),
1443
t(OS,'test',{RM32,Reg32}),
1444
t(OS,'xor',{eax,Imm32}),
1445
t(OS,'xor',{RM32,Imm32}),
1446
t(OS,'xor',{RM32,Imm8}),
1447
t(OS,'xor',{RM32,Reg32}),
1448
t(OS,'xor',{Reg32,RM32}),
1449
t(OS,'prefix_fs',{}), t(OS,'add',{{reg32,?EAX},{rm32,rm_mem(ea_disp32_rip(16#20))}}),
1452
dotest() -> dotest1(group_leader()). % stdout == group_leader
1455
{ok,OS} = file:open(File, [write]),