~ubuntu-branches/debian/squeeze/erlang/squeeze

« back to all changes in this revision

Viewing changes to lib/hipe/amd64/hipe_amd64_encode.erl

  • Committer: Bazaar Package Importer
  • Author(s): Erlang Packagers, Sergei Golovan
  • Date: 2006-12-03 17:07:44 UTC
  • mfrom: (2.1.11 feisty)
  • Revision ID: james.westby@ubuntu.com-20061203170744-rghjwupacqlzs6kv
Tags: 1:11.b.2-4
[ Sergei Golovan ]
Fixed erlang-base and erlang-base-hipe prerm scripts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
%%% $Id$
 
2
%%% Copyright (C) 2000-2004 Mikael Pettersson
 
3
%%% Copyright (C) 2004 Daniel Luna
 
4
%%%
 
5
%%% This is the syntax of amd64 r/m operands:
 
6
%%%
 
7
%%% opnd  ::= reg                       mod == 11
 
8
%%%         | MEM[ea]                   mod != 11
 
9
%%%
 
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
 
17
%%%
 
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
 
23
%%%
 
24
%%% // sib12: mod == 01 or 10
 
25
%%% sib12  ::= (base,index,scale)       index != ESP
 
26
%%%         | (base)                    index == 100
 
27
%%%
 
28
%%% scale ::= 00 | 01 | 10 | 11         index << scale
 
29
%%%
 
30
%%% Notes:
 
31
%%%
 
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]
 
38
%%%    a SIB byte.
 
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.
 
42
 
 
43
-module(hipe_amd64_encode).
 
44
 
 
45
-export([% condition codes
 
46
         cc/1,
 
47
         % 8-bit registers
 
48
         %% al/0, cl/0, dl/0, bl/0, ah/0, ch/0, dh/0, bh/0,
 
49
         % 32-bit registers
 
50
         %% eax/0, ecx/0, edx/0, ebx/0, esp/0, ebp/0, esi/0, edi/0,
 
51
         % operands
 
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,
 
55
         ea_base/1,
 
56
         ea_disp32_sindex/1, %%ea_disp32_sindex/2,
 
57
         ea_sib/1, %ea_disp32_rip/1,
 
58
         rm_reg/1, rm_mem/1,
 
59
         % instructions
 
60
         insn_encode/3, insn_sizeof/2]).
 
61
 
 
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
 
65
-endif.
 
66
 
 
67
-define(ASSERT(F,G), if G -> [] ; true -> exit({?MODULE,F}) end).
 
68
%-define(ASSERT(F,G), []).
 
69
 
 
70
%%% condition codes
 
71
 
 
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
 
88
 
 
89
cc(o) -> ?CC_O;
 
90
cc(no) -> ?CC_NO;
 
91
cc(b) -> ?CC_B;
 
92
cc(ae) -> ?CC_AE;
 
93
cc(e) -> ?CC_E;
 
94
cc(ne) -> ?CC_NE;
 
95
cc(be) -> ?CC_BE;
 
96
cc(a) -> ?CC_A;
 
97
cc(s) -> ?CC_S;
 
98
cc(ns) -> ?CC_NS;
 
99
cc(pe) -> ?CC_PE;
 
100
cc(po) -> ?CC_PO;
 
101
cc(l) -> ?CC_L;
 
102
cc(ge) -> ?CC_GE;
 
103
cc(le) -> ?CC_LE;
 
104
cc(g) -> ?CC_G.
 
105
 
 
106
%%% 8-bit registers
 
107
 
 
108
-define(AL, 2#000).
 
109
-define(CL, 2#001).
 
110
-define(DL, 2#010).
 
111
-define(BL, 2#011).
 
112
-define(AH, 2#100).
 
113
-define(CH, 2#101).
 
114
-define(DH, 2#110).
 
115
-define(BH, 2#111).
 
116
 
 
117
%% al() -> ?AL.
 
118
%% cl() -> ?CL.
 
119
%% dl() -> ?DL.
 
120
%% bl() -> ?BL.
 
121
%% ah() -> ?AH.
 
122
%% ch() -> ?CH.
 
123
%% dh() -> ?DH.
 
124
%% bh() -> ?BH.
 
125
 
 
126
%%% 32-bit registers
 
127
 
 
128
-define(EAX, 2#000).
 
129
-define(ECX, 2#001).
 
130
-define(EDX, 2#010).
 
131
-define(EBX, 2#011).
 
132
-define(ESP, 2#100).
 
133
-define(EBP, 2#101).
 
134
-define(ESI, 2#110).
 
135
-define(EDI, 2#111).
 
136
 
 
137
%% eax() -> ?EAX.
 
138
%% ecx() -> ?ECX.
 
139
%% edx() -> ?EDX.
 
140
%% ebx() -> ?EBX.
 
141
%% esp() -> ?ESP.
 
142
%% ebp() -> ?EBP.
 
143
%% esi() -> ?ESI.
 
144
%% edi() -> ?EDI.
 
145
 
 
146
%%% r/m operands
 
147
 
 
148
sindex(Scale, Index) ->
 
149
    ?ASSERT(sindex, Scale >= 0),
 
150
    ?ASSERT(sindex, Scale =< 3),
 
151
    ?ASSERT(sindex, Index =/= ?ESP),
 
152
    {sindex, Scale, Index}.
 
153
 
 
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}.
 
157
 
 
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}.
 
166
ea_base(Base) ->
 
167
    ?ASSERT(ea_base, Base =/= ?ESP),
 
168
    ?ASSERT(ea_base, Base =/= ?EBP),
 
169
    {ea_base, Base}.
 
170
ea_disp32_sindex(Disp32) -> {ea_disp32_sindex, Disp32, none}.
 
171
%% ea_disp32_sindex(Disp32, Sindex) -> {ea_disp32_sindex, Disp32, Sindex}.
 
172
ea_sib(SIB) ->
 
173
    ?ASSERT(ea_sib, SIB#sib.base =/= ?EBP),
 
174
    {ea_sib, SIB}.
 
175
%ea_disp32_rip(Disp32) -> {ea_disp32_rip, Disp32}.
 
176
 
 
177
rm_reg(Reg) -> {rm_reg, Reg}.
 
178
rm_mem(EA) -> {rm_mem, EA}.
 
179
 
 
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)}.
 
183
 
 
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)}.
 
187
 
 
188
rex(REXs) -> {rex, rex_(REXs)}.
 
189
rex_([]) -> 0;
 
190
rex_([{r8, Reg8}| Rest]) ->             % 8 bit registers
 
191
    case Reg8 of
 
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)
 
198
    end;
 
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;
 
203
              true           -> 0
 
204
           end,
 
205
    (REXR bsl 2) bor rex_(Rest);
 
206
rex_([{x, SIB_indexRegister}| Rest]) -> % SIB index
 
207
    REXX = if (SIB_indexRegister > 7) -> 1;
 
208
              true           -> 0
 
209
           end,
 
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;
 
213
              true           -> 0
 
214
           end,
 
215
    REXB bor rex_(Rest).
 
216
 
 
217
le16(Word, Tail) ->
 
218
    [Word band 16#FF, (Word bsr 8) band 16#FF | Tail].
 
219
 
 
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].
 
225
 
 
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].
 
233
 
 
234
enc_sindex_opt({sindex,Scale,Index}) -> {Scale, Index};
 
235
enc_sindex_opt(none) -> {2#00, 2#100}.
 
236
 
 
237
enc_sib(#sib{sindex_opt=SindexOpt, base=Base}) ->
 
238
    {Scale, Index} = enc_sindex_opt(SindexOpt),
 
239
    mk_sib(Scale, Index, Base).
 
240
 
 
241
enc_ea(EA, RO, Tail) ->
 
242
    case EA of
 
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];
 
251
        {ea_base, Base} ->
 
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)];
 
258
        {ea_sib, SIB} ->
 
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)]
 
262
    end.
 
263
 
 
264
encode_rm(RM, RO, Tail) ->
 
265
    case RM of
 
266
        {rm_reg, Reg} -> [mk_modrm(2#11, RO, Reg) | Tail];
 
267
        {rm_mem, EA} -> enc_ea(EA, RO, Tail)
 
268
    end.
 
269
 
 
270
%% sizeof_ea(EA) ->
 
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;
 
276
%%      ea_base -> 1;
 
277
%%      ea_disp32_sindex -> 6;
 
278
%%      ea_sib -> 2;
 
279
%%      ea_disp32_rip -> 5
 
280
%%     end.
 
281
 
 
282
%% sizeof_rm(RM) ->
 
283
%%    case RM of
 
284
%%      {rm_reg, _} -> 1;
 
285
%%      {rm_mem, EA} -> sizeof_ea(EA)
 
286
%%    end.
 
287
 
 
288
%%% x87 stack postitions
 
289
 
 
290
-define(ST0, 2#000).
 
291
-define(ST1, 2#001).
 
292
-define(ST2, 2#010).
 
293
-define(ST3, 2#011).
 
294
-define(ST4, 2#100).
 
295
-define(ST5, 2#101).
 
296
-define(ST6, 2#110).
 
297
-define(ST7, 2#111).
 
298
 
 
299
st(0) -> ?ST0;
 
300
st(1) -> ?ST1;
 
301
st(2) -> ?ST2;
 
302
st(3) -> ?ST3;
 
303
st(4) -> ?ST4;
 
304
st(5) -> ?ST5;
 
305
st(6) -> ?ST6;
 
306
st(7) -> ?ST7.
 
307
 
 
308
 
 
309
%%% Instructions
 
310
%%%
 
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}
 
318
%%%               | {cc,CC}
 
319
%%%               | {reg32,Reg32} | {reg16,Reg16} | {reg8,Reg8}
 
320
%%%               | {ea,EA}
 
321
 
 
322
-define(PFX_OPND_16BITS, 16#66).
 
323
 
 
324
arith_binop_encode(SubOpcode, Opnds) ->
 
325
    %% add, or, adc, sbb, and, sub, xor, cmp
 
326
     case Opnds of
 
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}} ->
 
341
             [rex([{w,1}]), 16#81 
 
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, [])]
 
351
    end.
 
352
 
 
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, [])].
 
356
 
 
357
sse2_cvtsi2sd_encode({{xmm,XMM64}, {rm64,RM64}}) ->
 
358
    [rex([{w, 1}]), 16#F2, 16#0F, 16#2A�| encode_rm(RM64, XMM64, [])].
 
359
 
 
360
sse2_mov_encode(Opnds) ->
 
361
    case Opnds of
 
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, [])]
 
368
    end.
 
369
 
 
370
%% arith_binop_sizeof(Opnds) ->
 
371
%%     %% add, or, adc, sbb, and, sub, xor, cmp
 
372
%%    case Opnds of
 
373
%%      {eax, {imm32,_}} ->
 
374
%%          1 + 4;
 
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)
 
383
%%    end.
 
384
 
 
385
bs_op_encode(Opcode, {{reg32,Reg32}, {rm32,RM32}}) ->   % bsf, bsr
 
386
    [16#0F, Opcode | encode_rm(RM32, Reg32, [])].
 
387
 
 
388
%% bs_op_sizeof({{reg32,_}, {rm32,RM32}}) ->            % bsf, bsr
 
389
%%    2 + sizeof_rm(RM32).
 
390
 
 
391
bswap_encode(Opnds) ->
 
392
    case Opnds of
 
393
        {{reg32,Reg32}} ->
 
394
            [rex([{b, Reg32}]), 16#0F, 16#C8 bor (Reg32 band 2#111)];
 
395
        {{reg64,Reg64}} ->
 
396
            [rex([{w, 1}, {b, Reg64}]), 16#0F, 16#C8 bor (Reg64 band 2#111)]
 
397
    end.        
 
398
 
 
399
%% bswap_sizeof({{reg32,_}}) ->
 
400
%%    2.
 
401
 
 
402
bt_op_encode(SubOpcode, Opnds) ->       % bt, btc, btr, bts
 
403
    case Opnds of
 
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])]
 
408
    end.
 
409
 
 
410
%% bt_op_sizeof(Opnds) ->                       % bt, btc, btr, bts
 
411
%%    case Opnds of
 
412
%%      {{rm32,RM32}, {reg32,_}} ->
 
413
%%          2 + sizeof_rm(RM32);
 
414
%%      {{rm32,RM32}, {imm8,_}} ->
 
415
%%          2 + sizeof_rm(RM32) + 1
 
416
%%    end.
 
417
 
 
418
call_encode(Opnds) ->
 
419
    case Opnds of
 
420
        {{rel32,Rel32}} ->
 
421
            [16#E8 | le32(Rel32, [])];
 
422
%%%     {{rm32,RM32}} ->
 
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, [])]
 
426
    end.
 
427
 
 
428
%% call_sizeof(Opnds) ->
 
429
%%    case Opnds of
 
430
%%      {{rel32,_}} ->
 
431
%%          1 + 4;
 
432
%%      {{rm32,RM32}} ->
 
433
%%          1 + sizeof_rm(RM32)
 
434
%%    end.
 
435
 
 
436
cbw_encode({}) ->
 
437
    [?PFX_OPND_16BITS, 16#98].
 
438
 
 
439
cbw_sizeof({}) ->
 
440
    2.
 
441
 
 
442
nullary_op_encode(Opcode, {}) ->
 
443
    %% cdq, clc, cld, cmc, cwde, into, leave, nop, prefix_fs, stc, std
 
444
    [Opcode].
 
445
 
 
446
nullary_op_sizeof({}) ->
 
447
    %% cdq, clc, cld, cmc, cwde, into, leave, nop, prefix_fs, stc, std
 
448
    1.
 
449
 
 
450
cmovcc_encode({{cc,CC}, {reg32,Reg32}, {rm32,RM32}}) ->
 
451
    [16#0F, 16#40 bor CC | encode_rm(RM32, Reg32, [])].
 
452
 
 
453
%% cmovcc_sizeof({{cc,_}, {reg32,_}, {rm32,RM32}}) ->
 
454
%%    2 + sizeof_rm(RM32).
 
455
 
 
456
incdec_encode(SubOpcode, Opnds) ->      % SubOpcode is either 0 or 1
 
457
    case Opnds of
 
458
        {{rm32,RM32}} ->
 
459
            [16#FF | encode_rm(RM32, SubOpcode, [])];
 
460
        {{rm64,RM64}} ->
 
461
            [rex([{w, 1}]), 16#FF | encode_rm(RM64, SubOpcode, [])]
 
462
    end.
 
463
 
 
464
%% incdec_sizeof(Opnds) ->
 
465
%%    case Opnds of
 
466
%%      {{rm32,RM32}} ->
 
467
%%          1 + sizeof_rm(RM32);
 
468
%%      {{reg32,_}} ->
 
469
%%          1
 
470
%%    end.
 
471
 
 
472
arith_unop_encode(Opcode, Opnds) ->  % div, idiv, mul, neg, not
 
473
    case Opnds of
 
474
        {{rm32,RM32}} ->
 
475
            [16#F7 | encode_rm(RM32, Opcode, [])];
 
476
        {{rm64,RM64}} ->
 
477
            [rex([{w,1}]), 16#F7 | encode_rm(RM64, Opcode, [])]
 
478
    end.
 
479
 
 
480
%% arith_unop_sizeof({{rm32,RM32}}) ->  % div, idiv, mul, neg, not
 
481
%%    1 + sizeof_rm(RM32).
 
482
 
 
483
enter_encode({{imm16,Imm16}, {imm8,Imm8}}) ->
 
484
    [16#C8 | le16(Imm16, [Imm8])].
 
485
 
 
486
enter_sizeof({{imm16,_}, {imm8,_}}) ->
 
487
    1 + 2 + 1.
 
488
 
 
489
imul_encode(Opnds) ->
 
490
    case Opnds of
 
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, []))]
 
499
    end.
 
500
 
 
501
%% imul_sizeof(Opnds) ->
 
502
%%    case Opnds of
 
503
%%      {{rm32,RM32}} ->
 
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
 
511
%%    end.
 
512
 
 
513
jcc_encode(Opnds) ->
 
514
    case Opnds of
 
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, [])]
 
519
    end.
 
520
 
 
521
jcc_sizeof(Opnds) ->
 
522
    case Opnds of
 
523
       {{cc,_}, {rel8,_}} ->
 
524
           2;
 
525
       {{cc,_}, {rel32,_}} ->
 
526
           2 + 4
 
527
   end.
 
528
 
 
529
jmp8_op_encode(Opcode, {{rel8,Rel8}}) ->        % jecxz, loop, loope, loopne
 
530
    [Opcode, Rel8].
 
531
 
 
532
jmp8_op_sizeof({{rel8,_}}) ->                   % jecxz, loop, loope, loopne
 
533
    2.
 
534
 
 
535
jmp_encode(Opnds) ->
 
536
    case Opnds of
 
537
        {{rel8,Rel8}} ->
 
538
            [16#EB, Rel8];
 
539
        {{rel32,Rel32}} ->
 
540
            [16#E9 | le32(Rel32, [])];
 
541
%%%     {{rm32,RM32}} ->
 
542
%%%         [16#FF | encode_rm(RM32, 2#100, [])]
 
543
        {{rm64,RM64}} ->
 
544
            [16#FF | encode_rm(RM64, 2#100, [])]
 
545
    end.
 
546
 
 
547
%% jmp_sizeof(Opnds) ->
 
548
%%    case Opnds of
 
549
%%      {{rel8,_}} ->
 
550
%%          2;
 
551
%%      {{rel32,_}} ->
 
552
%%          1 + 4;
 
553
%%      {{rm32,RM32}} ->
 
554
%%          1 + sizeof_rm(RM32)
 
555
%%    end.
 
556
 
 
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, [])].
 
561
 
 
562
%% lea_sizeof({{reg32,_}, {ea,EA}}) ->
 
563
%%    1 + sizeof_ea(EA).
 
564
 
 
565
mov_encode(Opnds) ->
 
566
    case Opnds of
 
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) 
 
604
             | le16(Imm16, [])];
 
605
        {{reg32,Reg32}, {imm32,Imm32}} ->
 
606
            [rex([{b, Reg32}]), 16#B8 bor (Reg32 band 2#111)
 
607
             | le32(Imm32, [])];
 
608
        {{reg64,Reg64}, {imm64,Imm64}} ->
 
609
            [rex([{w, 1}, {b, Reg64}]), 16#B8 bor (Reg64 band 2#111)
 
610
             | le64(Imm64, [])];
 
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, []))]
 
620
    end.
 
621
 
 
622
%% mov_sizeof(Opnds) ->
 
623
%%     case Opnds of
 
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,_}} ->
 
637
%%          1 + 4;
 
638
%%      {ax, {moffs16,_}} ->
 
639
%%          2 + 4;
 
640
%%      {eax, {moffs32,_}} ->
 
641
%%          1 + 4;
 
642
%%      {{moffs8,_}, al} ->
 
643
%%          1 + 4;
 
644
%%      {{moffs16,_}, ax} ->
 
645
%%          2 + 4;
 
646
%%      {{moffs32,_}, eax} ->
 
647
%%          1 + 4;
 
648
%%      {{reg8,_}, {imm8,_}} ->
 
649
%%          2;
 
650
%%      {{reg16,_}, {imm16,_}} ->
 
651
%%          2 + 2;
 
652
%%      {{reg32,_}, {imm32,_}} ->
 
653
%%          1 + 4;
 
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
 
660
%%     end.
 
661
 
 
662
movx_op_encode(Opcode, Opnds) ->        % movsx, movzx
 
663
    case Opnds of
 
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, [])]
 
679
    end.
 
680
 
 
681
%% movx_op_sizeof(Opnds) ->
 
682
%%    case Opnds of
 
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)
 
689
%%    end.
 
690
 
 
691
pop_encode(Opnds) ->
 
692
    case Opnds of
 
693
        {{rm64,RM64}} ->
 
694
            [16#8F | encode_rm(RM64, 2#000, [])];
 
695
        {{reg64,Reg64}} ->
 
696
            [rex([{b,Reg64}]),16#58 bor (Reg64 band 2#111)]
 
697
    end.
 
698
 
 
699
%% pop_sizeof(Opnds) ->
 
700
%%    case Opnds of
 
701
%%      {{rm32,RM32}} ->
 
702
%%          1 + sizeof_rm(RM32);
 
703
%%      {{reg32,_}} ->
 
704
%%          1
 
705
%%    end.
 
706
 
 
707
push_encode(Opnds) ->
 
708
    case Opnds of
 
709
%%%     {{rm32,RM32}} ->
 
710
%%%         [16#FF | encode_rm(RM32, 2#110, [])];
 
711
        {{rm64,RM64}} ->
 
712
            [16#FF | encode_rm(RM64, 2#110, [])];
 
713
%%%     {{reg32,Reg32}} ->
 
714
%%%         [rex([{b, 1}]), 16#50 bor (Reg32 band 2#111)];
 
715
        {{reg64,Reg64}} ->
 
716
            [rex([{b, Reg64}]), 16#50 bor (Reg64 band 2#111)];        
 
717
        {{imm8,Imm8}} ->        % sign-extended
 
718
            [16#6A, Imm8];
 
719
        {{imm32,Imm32}} -> % Sign extended to 64 bits
 
720
            [16#68 | le32(Imm32, [])]
 
721
    end.
 
722
 
 
723
%% push_sizeof(Opnds) ->
 
724
%%    case Opnds of
 
725
%%      {{rm32,RM32}} ->
 
726
%%          1 + sizeof_rm(RM32);
 
727
%%      {{reg32,_}} ->
 
728
%%          1;
 
729
%%      {{imm8,_}} ->
 
730
%%          2;
 
731
%%      {{imm32,_}} ->
 
732
%%          1 + 4
 
733
%%    end.
 
734
 
 
735
shift_op_encode(SubOpcode, Opnds) ->    % rol, ror, rcl, rcr, shl, shr, sar
 
736
     case Opnds of
 
737
         {{rm32,RM32}, 1} ->
 
738
             [16#D1 | encode_rm(RM32, SubOpcode, [])];
 
739
         {{rm32,RM32}, cl} ->
 
740
             [16#D3 | encode_rm(RM32, SubOpcode, [])];
 
741
         {{rm32,RM32}, {imm8,Imm8}} ->
 
742
             [16#C1 | encode_rm(RM32, SubOpcode, [Imm8])];
 
743
         {{rm64,RM64}, 1} ->
 
744
             [rex([{w,1}]), 16#D1 | encode_rm(RM64, SubOpcode, [])];
 
745
         {{rm64,RM64}, cl} ->
 
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])]
 
749
     end.
 
750
 
 
751
%% shift_op_sizeof(Opnds) ->            % rcl, rcr, rol, ror, sar, shl, shr
 
752
%%     case Opnds of
 
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
 
759
%%     end.
 
760
 
 
761
ret_encode(Opnds) ->
 
762
    case Opnds of
 
763
        {} ->
 
764
            [16#C3];
 
765
        {{imm16,Imm16}} ->
 
766
            [16#C2 | le16(Imm16, [])]
 
767
    end.
 
768
 
 
769
ret_sizeof(Opnds) ->
 
770
    case Opnds of
 
771
        {} ->
 
772
            1;
 
773
        {{imm16,_}} ->
 
774
            1 + 2
 
775
    end.
 
776
 
 
777
setcc_encode({{cc,CC}, {rm8,RM8}}) ->
 
778
    [rex([{r8, RM8}]), 16#0F, 16#90 bor CC | encode_rm(RM8, 2#000, [])].
 
779
 
 
780
%% setcc_sizeof({{cc,_}, {rm8,RM8}}) ->
 
781
%%    2 + sizeof_rm(RM8).
 
782
 
 
783
shd_op_encode(Opcode, Opnds) ->
 
784
    case Opnds of
 
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, [])]
 
789
    end.
 
790
 
 
791
%% shd_op_sizeof(Opnds) ->
 
792
%%    case Opnds of
 
793
%%      {{rm32,RM32}, {reg32,_}, {imm8,_}} ->
 
794
%%          2 + sizeof_rm(RM32) + 1;
 
795
%%      {{rm32,RM32}, {reg32,_}, cl} ->
 
796
%%          2 + sizeof_rm(RM32)
 
797
%%    end.
 
798
 
 
799
test_encode(Opnds) ->
 
800
    case Opnds of
 
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, [])]
 
807
    end.
 
808
 
 
809
%% test_sizeof(Opnds) ->
 
810
%%     case Opnds of
 
811
%%      {eax, {imm32,_}} ->
 
812
%%          1 + 4;
 
813
%%      {{rm32,RM32}, {imm32,_}} ->
 
814
%%          1 + sizeof_rm(RM32) + 4;
 
815
%%      {{rm32,RM32}, {reg32,_}} ->
 
816
%%          1 + sizeof_rm(RM32)
 
817
%%     end.
 
818
 
 
819
fild_encode(Opnds) ->
 
820
    %% The operand cannot be a register!
 
821
    {{rm64, RM64}} = Opnds,
 
822
    [16#DB | encode_rm(RM64, 2#000, [])].
 
823
 
 
824
%% fild_sizeof(Opnds) ->
 
825
%%    {{rm32, RM32}} = Opnds,
 
826
%%    1 + sizeof_rm(RM32).
 
827
 
 
828
fld_encode(Opnds) ->
 
829
    case Opnds of
 
830
        {{rm64fp, RM64fp}} ->
 
831
            [16#DD | encode_rm(RM64fp, 2#000, [])];
 
832
        {{fpst, St}} ->
 
833
            [16#D9, 16#C0 bor st(St)]
 
834
    end.
 
835
 
 
836
%% fld_sizeof(Opnds) ->
 
837
%%    case Opnds of
 
838
%%      {{rm64fp, RM64fp}} ->
 
839
%%          1 + sizeof_rm(RM64fp);
 
840
%%      {{fpst, _}} ->
 
841
%%          2
 
842
%%    end.
 
843
 
 
844
x87_comm_arith_encode(OpCode, Opnds) ->
 
845
    %% fadd, fmul
 
846
    case Opnds of
 
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)]
 
853
    end.
 
854
            
 
855
x87_comm_arith_pop_encode(OpCode, Opnds) ->
 
856
    %% faddp, fmulp
 
857
    case Opnds of
 
858
        [] ->
 
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)]
 
862
    end.
 
863
 
 
864
x87_arith_encode(OpCode, Opnds) ->
 
865
    %% fdiv, fsub
 
866
    case Opnds of
 
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)]
 
875
    end.
 
876
            
 
877
x87_arith_pop_encode(OpCode, Opnds) ->
 
878
    %% fdivp, fsubp
 
879
    OpCode0 = OpCode bor 1,
 
880
    case Opnds of
 
881
        [] ->
 
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)]
 
885
    end.
 
886
 
 
887
x87_arith_rev_encode(OpCode, Opnds) ->
 
888
    %% fdivr, fsubr
 
889
    case Opnds of
 
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)]
 
898
    end.
 
899
            
 
900
x87_arith_rev_pop_encode(OpCode, Opnds) ->
 
901
    %% fdivrp, fsubrp
 
902
    OpCode0 = OpCode band 2#110,
 
903
    case Opnds of
 
904
        [] ->
 
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)]
 
908
    end.
 
909
 
 
910
%% x87_arith_sizeof(Opnds) ->
 
911
%%    case Opnds of
 
912
%%      {{rm64fp, RM64fp}} ->
 
913
%%          1 + sizeof_rm(RM64fp);
 
914
%%      {{fpst,0}, {fpst,_}} ->
 
915
%%          2;
 
916
%%      {{fpst,_}, {fpst,0}} ->
 
917
%%          2
 
918
%%    end.
 
919
 
 
920
fst_encode(OpCode, Opnds) ->
 
921
    case Opnds of
 
922
        {{rm64fp, RM64fp}} ->
 
923
            [16#DD | encode_rm(RM64fp, OpCode, [])];
 
924
        {{fpst, St}} ->
 
925
            [16#DD, 16#C0 bor (OpCode bsl 3) bor st(St)]
 
926
    end.
 
927
 
 
928
%% fst_sizeof(Opnds) ->
 
929
%%     case Opnds of
 
930
%%      {{rm64fp, RM64fp}} ->
 
931
%%          1 + sizeof_rm(RM64fp);
 
932
%%      {{fpst, _}} ->
 
933
%%          2
 
934
%%     end.
 
935
    
 
936
fchs_encode() ->
 
937
    [16#D9, 16#E0].
 
938
 
 
939
fchs_sizeof() ->
 
940
    2.
 
941
 
 
942
ffree_encode({{fpst, St}})->
 
943
    [16#DD, 16#C0 bor st(St)].
 
944
 
 
945
ffree_sizeof() ->
 
946
    2.
 
947
 
 
948
fwait_encode() ->
 
949
    [16#9B].
 
950
 
 
951
fwait_sizeof() ->
 
952
    1.
 
953
 
 
954
fxch_encode(Opnds) ->
 
955
    case Opnds of
 
956
        [] ->
 
957
            [16#D9, 16#C8 bor st(1)];
 
958
        {{fpst, St}} ->
 
959
            [16#D9, 16#C8 bor st(St)]
 
960
    end.
 
961
 
 
962
fxch_sizeof() ->
 
963
    2.
 
964
 
 
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
 
970
            {Bytes, []};
 
971
        _ ->
 
972
            fix_relocs(Bytes, Offset, [], [])
 
973
    end.
 
974
 
 
975
fix_rex(Bytes) ->
 
976
    fix_rex(Bytes, 2#0100 bsl 4, []).
 
977
 
 
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),
 
989
    case Head of
 
990
        16#66 ->                               % ...and 16 bit/sse2 prefix
 
991
            [16#66, REX | Tail];
 
992
        16#F2 ->                               % ...and sse2 prefix
 
993
            [16#F2, REX | Tail];
 
994
        _ ->                                   % ...only
 
995
           [REX, Head | Tail]
 
996
    end.
 
997
 
 
998
has_relocs([{le32,_,_}|_]) -> true;
 
999
has_relocs([{le64,_,_}|_]) -> true;
 
1000
has_relocs([_|Bytes]) -> has_relocs(Bytes);
 
1001
has_relocs([]) -> false.
 
1002
 
 
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)}.
 
1016
 
 
1017
insn_encode_internal(Op, Opnds) ->
 
1018
    case Op of
 
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})
 
1048
                  end;
 
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);
 
1085
 
 
1086
        %% sse2
 
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);
 
1100
        %% End of sse2
 
1101
 
 
1102
        %% x87
 
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);
 
1123
        %% End of x87
 
1124
 
 
1125
        _ -> exit({?MODULE,insn_encode,Op})
 
1126
    end.
 
1127
 
 
1128
insn_sizeof(Op, Opnds) ->
 
1129
    case Op of
 
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);
 
1149
 
 
1150
%%      %% x87
 
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();      
 
1171
%%      %% End of x87
 
1172
        _ -> %% Hack that is to be removed some day... Maybe...
 
1173
            {Bytes, _} = insn_encode(Op, Opnds, 0),
 
1174
            length(Bytes)
 
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})
 
1219
    end.
 
1220
 
 
1221
%%=====================================================================
 
1222
%% testing interface
 
1223
%%=====================================================================
 
1224
 
 
1225
-ifdef(DO_HIPE_AMD64_ENCODE_TEST).
 
1226
 
 
1227
say(OS, Str) ->
 
1228
    file:write(OS, Str).
 
1229
 
 
1230
digit16(Dig0) ->
 
1231
    Dig = Dig0 band 16#F,
 
1232
    if Dig >= 16#A -> $A + (Dig - 16#A);
 
1233
       true -> $0 + Dig
 
1234
    end.
 
1235
 
 
1236
say_byte(OS, Byte) ->
 
1237
    say(OS, "0x"),
 
1238
    say(OS, [digit16(Byte bsr 4)]),
 
1239
    say(OS, [digit16(Byte)]).
 
1240
 
 
1241
init(OS) ->
 
1242
    say(OS, "\t.text\n").
 
1243
 
 
1244
say_bytes(OS, Byte0, Bytes0) ->
 
1245
    say_byte(OS, Byte0),
 
1246
    case Bytes0 of
 
1247
        [] ->
 
1248
            say(OS, "\n");
 
1249
        [Byte1|Bytes1] ->
 
1250
            say(OS, ","),
 
1251
            say_bytes(OS, Byte1, Bytes1)
 
1252
    end.
 
1253
 
 
1254
t(OS, Op, Opnds) ->
 
1255
    insn_sizeof(Op, Opnds),
 
1256
    {[Byte|Bytes],[]} = insn_encode(Op, Opnds, 0),
 
1257
    say(OS, "\t.byte "),
 
1258
    say_bytes(OS, Byte, Bytes).
 
1259
 
 
1260
dotest1(OS) ->
 
1261
    init(OS),
 
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,
 
1280
    Word16 = 16#F00F,
 
1281
    Word8 = 16#80,
 
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},
 
1293
    CC = {cc,?CC_G},
 
1294
    Reg32 = {reg32,?EAX},
 
1295
    Reg16 = {reg16,?EAX},
 
1296
    Reg8 = {reg8,?AH},
 
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}),
 
1327
    t(OS,'cbw',{}),
 
1328
    t(OS,'cdq',{}),
 
1329
    t(OS,'clc',{}),
 
1330
    t(OS,'cld',{}),
 
1331
    t(OS,'cmc',{}),
 
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}),
 
1338
    t(OS,'cwde',{}),
 
1339
    t(OS,'dec',{RM32}),
 
1340
    t(OS,'dec',{Reg32}),
 
1341
    t(OS,'div',{RM32}),
 
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}),
 
1348
    t(OS,'inc',{RM32}),
 
1349
    t(OS,'inc',{Reg32}),
 
1350
    t(OS,'into',{}),
 
1351
    t(OS,'jcc',{CC,Rel8}),
 
1352
    t(OS,'jcc',{CC,Rel32}),
 
1353
    t(OS,'jecxz',{Rel8}),
 
1354
    t(OS,'jmp',{Rel8}),
 
1355
    t(OS,'jmp',{Rel32}),
 
1356
    t(OS,'jmp',{RM32}),
 
1357
    t(OS,'lea',{Reg32,EA}),
 
1358
    t(OS,'leave',{}),
 
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}),
 
1386
    t(OS,'mul',{RM32}),
 
1387
    t(OS,'neg',{RM32}),
 
1388
    t(OS,'nop',{}),
 
1389
    t(OS,'not',{RM32}),
 
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}),
 
1395
    t(OS,'pop',{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}),
 
1407
    t(OS,'ret',{}),
 
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}),
 
1434
    t(OS,'stc',{}),
 
1435
    t(OS,'std',{}),
 
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))}}),
 
1450
    [].
 
1451
 
 
1452
dotest() -> dotest1(group_leader()).    % stdout == group_leader
 
1453
 
 
1454
dotest(File) ->
 
1455
    {ok,OS} = file:open(File, [write]),
 
1456
    dotest1(OS),
 
1457
    file:close(OS).
 
1458
-endif.