1%%% Licensed under the Apache License, Version 2.0 (the "License");
2%%% you may not use this file except in compliance with the License.
3%%% You may obtain a copy of the License at
4%%%
5%%%     http://www.apache.org/licenses/LICENSE-2.0
6%%%
7%%% Unless required by applicable law or agreed to in writing, software
8%%% distributed under the License is distributed on an "AS IS" BASIS,
9%%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10%%% See the License for the specific language governing permissions and
11%%% limitations under the License.
12%%%
13%%% Copyright (C) 2000-2005 Mikael Pettersson
14%%%
15%%% This is the syntax of x86 r/m operands:
16%%%
17%%% opnd  ::= reg			mod == 11
18%%%	    | MEM[ea]			mod != 11
19%%%
20%%% ea    ::= disp32(reg)		mod == 10, r/m != ESP
21%%%  	    | disp32 sib12		mod == 10, r/m == 100
22%%%	    | disp8(reg)		mod == 01, r/m != ESP
23%%%	    | disp8 sib12		mod == 01, r/m == 100
24%%%	    | (reg)			mod == 00, r/m != ESP and EBP
25%%%	    | sib0			mod == 00, r/m == 100
26%%%	    | disp32			mod == 00, r/m == 101 [on x86-32]
27%%%	    | disp32(%rip)		mod == 00, r/m == 101 [on x86-64]
28%%%
29%%% // sib0: mod == 00
30%%% sib0  ::= disp32(,index,scale)	base == EBP, index != ESP
31%%%	    | disp32			base == EBP, index == 100
32%%%	    | (base,index,scale)	base != EBP, index != ESP
33%%%	    | (base)			base != EBP, index == 100
34%%%
35%%% // sib12: mod == 01 or 10
36%%% sib12  ::= (base,index,scale)	index != ESP
37%%%	    | (base)			index == 100
38%%%
39%%% scale ::= 00 | 01 | 10 | 11		index << scale
40%%%
41%%% Notes:
42%%%
43%%% 1. ESP cannot be used as index register.
44%%% 2. Use of ESP as base register requires a SIB byte.
45%%% 3. disp(reg), when reg != ESP, can be represented without
46%%%    [r/m == reg] or with [r/m == 100, base == reg] a SIB byte.
47%%% 4. disp32 can be represented without [mod == 00, r/m == 101]
48%%%    or with [mod == 00, r/m == 100, base == 101, index == 100]
49%%%    a SIB byte.
50%%% 5. x86-32 and x86-64 interpret mod==00b r/m==101b EAs differently:
51%%%    on x86-32 the disp32 is an absolute address, but on x86-64 the
52%%%    disp32 is relative to the %rip of the next instruction.
53%%%    Absolute disp32s need a SIB on x86-64.
54
55-module(hipe_x86_encode).
56
57-export([% condition codes
58	 cc/1,
59	 % 8-bit registers
60	 %% al/0, cl/0, dl/0, bl/0, ah/0, ch/0, dh/0, bh/0,
61	 reg_has_8bit/1,
62	 % 32-bit registers
63	 %% eax/0, ecx/0, edx/0, ebx/0, esp/0, ebp/0, esi/0, edi/0,
64	 % operands
65	 sindex/2, sib/1, sib/2,
66	 ea_disp32_base/2, ea_disp32_sib/2,
67	 ea_disp8_base/2, ea_disp8_sib/2,
68	 ea_base/1,
69	 %% ea_disp32_sindex/1, % XXX: do not use on x86-32, only on x86-64
70	 ea_disp32_sindex/2,
71	 ea_sib/1, ea_disp32/1,
72	 rm_reg/1, rm_mem/1,
73	 % instructions
74	 insn_encode/3, insn_sizeof/2]).
75
76%%-define(DO_HIPE_X86_ENCODE_TEST,true).
77-ifdef(DO_HIPE_X86_ENCODE_TEST).
78-export([dotest/0, dotest/1]).	% for testing, don't use
79-endif.
80
81-define(ASSERT(F,G), if G -> [] ; true -> exit({?MODULE,F}) end).
82%-define(ASSERT(F,G), []).
83
84%%% condition codes
85
86-define(CC_O,  2#0000).	% overflow
87-define(CC_NO, 2#0001).	% no overflow
88-define(CC_B,  2#0010).	% below, <u
89-define(CC_AE, 2#0011).	% above or equal, >=u
90-define(CC_E,  2#0100).	% equal
91-define(CC_NE, 2#0101).	% not equal
92-define(CC_BE, 2#0110).	% below or equal, <=u
93-define(CC_A,  2#0111).	% above, >u
94-define(CC_S,  2#1000).	% sign, +
95-define(CC_NS, 2#1001).	% not sign, -
96-define(CC_PE, 2#1010).	% parity even
97-define(CC_PO, 2#1011).	% parity odd
98-define(CC_L,  2#1100).	% less than, <s
99-define(CC_GE, 2#1101).	% greater or equal, >=s
100-define(CC_LE, 2#1110).	% less or equal, <=s
101-define(CC_G,  2#1111).	% greater than, >s
102
103cc(o) -> ?CC_O;
104cc(no) -> ?CC_NO;
105cc(b) -> ?CC_B;
106cc(ae) -> ?CC_AE;
107cc(e) -> ?CC_E;
108cc(ne) -> ?CC_NE;
109cc(be) -> ?CC_BE;
110cc(a) -> ?CC_A;
111cc(s) -> ?CC_S;
112cc(ns) -> ?CC_NS;
113cc(pe) -> ?CC_PE;
114cc(po) -> ?CC_PO;
115cc(l) -> ?CC_L;
116cc(ge) -> ?CC_GE;
117cc(le) -> ?CC_LE;
118cc(g) -> ?CC_G.
119
120%%% 8-bit registers
121
122-define(AL, 2#000).
123-define(CL, 2#001).
124-define(DL, 2#010).
125-define(BL, 2#011).
126-define(AH, 2#100).
127-define(CH, 2#101).
128-define(DH, 2#110).
129-define(BH, 2#111).
130
131%% al() -> ?AL.
132%% cl() -> ?CL.
133%% dl() -> ?DL.
134%% bl() -> ?BL.
135%% ah() -> ?AH.
136%% ch() -> ?CH.
137%% dh() -> ?DH.
138%% bh() -> ?BH.
139
140reg_has_8bit(Reg) -> Reg =< ?BL.
141
142%%% 32-bit registers
143
144-define(EAX, 2#000).
145-define(ECX, 2#001).
146-define(EDX, 2#010).
147-define(EBX, 2#011).
148-define(ESP, 2#100).
149-define(EBP, 2#101).
150-define(ESI, 2#110).
151-define(EDI, 2#111).
152
153%% eax() -> ?EAX.
154%% ecx() -> ?ECX.
155%% edx() -> ?EDX.
156%% ebx() -> ?EBX.
157%% esp() -> ?ESP.
158%% ebp() -> ?EBP.
159%% esi() -> ?ESI.
160%% edi() -> ?EDI.
161
162%%% r/m operands
163
164sindex(Scale, Index) when is_integer(Scale), is_integer(Index) ->
165    ?ASSERT(sindex, Scale >= 0),
166    ?ASSERT(sindex, Scale =< 3),
167    ?ASSERT(sindex, Index =/= ?ESP),
168    {sindex, Scale, Index}.
169
170-record(sib, {sindex_opt, base :: integer()}).
171sib(Base) when is_integer(Base) -> #sib{sindex_opt=none, base=Base}.
172sib(Base, Sindex) when is_integer(Base) -> #sib{sindex_opt=Sindex, base=Base}.
173
174ea_disp32_base(Disp32, Base) when is_integer(Base) ->
175    ?ASSERT(ea_disp32_base, Base =/= ?ESP),
176    {ea_disp32_base, Disp32, Base}.
177ea_disp32_sib(Disp32, SIB) -> {ea_disp32_sib, Disp32, SIB}.
178ea_disp8_base(Disp8, Base) when is_integer(Base) ->
179    ?ASSERT(ea_disp8_base, Base =/= ?ESP),
180    {ea_disp8_base, Disp8, Base}.
181ea_disp8_sib(Disp8, SIB) -> {ea_disp8_sib, Disp8, SIB}.
182ea_base(Base) when is_integer(Base) ->
183    ?ASSERT(ea_base, Base =/= ?ESP),
184    ?ASSERT(ea_base, Base =/= ?EBP),
185    {ea_base, Base}.
186%% ea_disp32_sindex(Disp32) -> {ea_disp32_sindex, Disp32, none}.
187ea_disp32_sindex(Disp32, Sindex) -> {ea_disp32_sindex, Disp32, Sindex}.
188ea_sib(SIB) ->
189    ?ASSERT(ea_sib, SIB#sib.base =/= ?EBP),
190    {ea_sib, SIB}.
191ea_disp32(Disp32) -> {ea_disp32, Disp32}.
192
193rm_reg(Reg) -> {rm_reg, Reg}.
194rm_mem(EA) -> {rm_mem, EA}.
195
196mk_modrm(Mod, RO, RM) ->
197    (Mod bsl 6) bor (RO bsl 3) bor RM.
198
199mk_sib(Scale, Index, Base) ->
200    (Scale bsl 6) bor (Index bsl 3) bor Base.
201
202le16(Word, Tail) ->
203    [Word band 16#FF, (Word bsr 8) band 16#FF | Tail].
204
205le32(Word, Tail) when is_integer(Word) ->
206    [Word band 16#FF, (Word bsr 8) band 16#FF,
207     (Word bsr 16) band 16#FF, (Word bsr 24) band 16#FF | Tail];
208le32({Tag,Val}, Tail) ->	% a relocatable datum
209    [{le32,Tag,Val} | Tail].
210
211enc_sindex_opt({sindex,Scale,Index}) -> {Scale, Index};
212enc_sindex_opt(none) -> {2#00, 2#100}.
213
214enc_sib(#sib{sindex_opt=SindexOpt, base=Base}) ->
215    {Scale, Index} = enc_sindex_opt(SindexOpt),
216    mk_sib(Scale, Index, Base).
217
218enc_ea(EA, RO, Tail) ->
219    case EA of
220	{ea_disp32_base, Disp32, Base} ->
221	    [mk_modrm(2#10, RO, Base) | le32(Disp32, Tail)];
222	{ea_disp32_sib, Disp32, SIB} ->
223	    [mk_modrm(2#10, RO, 2#100), enc_sib(SIB) | le32(Disp32, Tail)];
224	{ea_disp8_base, Disp8, Base} ->
225	    [mk_modrm(2#01, RO, Base), Disp8 | Tail];
226	{ea_disp8_sib, Disp8, SIB} ->
227	    [mk_modrm(2#01, RO, 2#100), enc_sib(SIB), Disp8 | Tail];
228	{ea_base, Base} ->
229	    [mk_modrm(2#00, RO, Base) | Tail];
230	{ea_disp32_sindex, Disp32, SindexOpt} ->
231	    {Scale, Index} = enc_sindex_opt(SindexOpt),
232	    SIB = mk_sib(Scale, Index, 2#101),
233	    MODRM = mk_modrm(2#00, RO, 2#100),
234	    [MODRM, SIB | le32(Disp32, Tail)];
235	{ea_sib, SIB} ->
236	    [mk_modrm(2#00, RO, 2#100), enc_sib(SIB) | Tail];
237	{ea_disp32, Disp32} ->
238	    [mk_modrm(2#00, RO, 2#101) | le32(Disp32, Tail)]
239    end.
240
241encode_rm(RM, RO, Tail) ->
242    case RM of
243	{rm_reg, Reg} -> [mk_modrm(2#11, RO, Reg) | Tail];
244	{rm_mem, EA} -> enc_ea(EA, RO, Tail)
245    end.
246
247sizeof_ea(EA) ->
248    case element(1, EA) of
249	ea_disp32_base -> 5;
250	ea_disp32_sib -> 6;
251	ea_disp8_base -> 2;
252	ea_disp8_sib -> 3;
253	ea_base -> 1;
254	ea_disp32_sindex -> 6;
255	ea_sib -> 2;
256	ea_disp32 -> 5
257    end.
258
259sizeof_rm(RM) ->
260    case RM of
261	{rm_reg, _} -> 1;
262	{rm_mem, EA} -> sizeof_ea(EA)
263    end.
264
265%%% Floating point stack positions
266
267-define(ST0, 2#000).
268-define(ST1, 2#001).
269-define(ST2, 2#010).
270-define(ST3, 2#011).
271-define(ST4, 2#100).
272-define(ST5, 2#101).
273-define(ST6, 2#110).
274-define(ST7, 2#111).
275
276st(0) -> ?ST0;
277st(1) -> ?ST1;
278st(2) -> ?ST2;
279st(3) -> ?ST3;
280st(4) -> ?ST4;
281st(5) -> ?ST5;
282st(6) -> ?ST6;
283st(7) -> ?ST7.
284
285
286%%% Instructions
287%%%
288%%% Insn	::= {Op,Opnds}
289%%% Opnds	::= {Opnd1,...,Opndn}	(n >= 0)
290%%% Opnd	::= eax | ax | al | 1 | cl
291%%%		  | {imm32,Imm32} | {imm16,Imm16} | {imm8,Imm8}
292%%%		  | {rm32,RM32} | {rm16,RM16} | {rm8,RM8}
293%%%		  | {rel32,Rel32} | {rel8,Rel8}
294%%%		  | {moffs32,Moffs32} | {moffs16,Moffs16} | {moffs8,Moffs8}
295%%%		  | {cc,CC}
296%%%		  | {reg32,Reg32} | {reg16,Reg16} | {reg8,Reg8}
297%%%		  | {ea,EA}
298
299-define(PFX_OPND, 16#66).
300
301arith_binop_encode(SubOpcode, Opnds) ->
302    %% add, or, adc, sbb, and, sub, xor, cmp
303    case Opnds of
304	{eax, {imm32,Imm32}} ->
305	    [16#05 bor (SubOpcode bsl 3) | le32(Imm32, [])];
306	{{rm32,RM32}, {imm32,Imm32}} ->
307	    [16#81 | encode_rm(RM32, SubOpcode, le32(Imm32, []))];
308	{{rm32,RM32}, {imm8,Imm8}} ->
309	    [16#83 | encode_rm(RM32, SubOpcode, [Imm8])];
310	{{rm32,RM32}, {reg32,Reg32}} ->
311	    [16#01 bor (SubOpcode bsl 3) | encode_rm(RM32, Reg32, [])];
312	{{reg32,Reg32}, {rm32,RM32}} ->
313	    [16#03 bor (SubOpcode bsl 3) | encode_rm(RM32, Reg32, [])]
314    end.
315
316arith_binop_sizeof(Opnds) ->
317    %% add, or, adc, sbb, and, sub, xor, cmp
318    case Opnds of
319	{eax, {imm32,_}} ->
320	    1 + 4;
321	{{rm32,RM32}, {imm32,_}} ->
322	    1 + sizeof_rm(RM32) + 4;
323	{{rm32,RM32}, {imm8,_}} ->
324	    1 + sizeof_rm(RM32) + 1;
325	{{rm32,RM32}, {reg32,_}} ->
326	    1 + sizeof_rm(RM32);
327	{{reg32,_}, {rm32,RM32}} ->
328	    1 + sizeof_rm(RM32)
329    end.
330
331bs_op_encode(Opcode, {{reg32,Reg32}, {rm32,RM32}}) ->	% bsf, bsr
332    [16#0F, Opcode | encode_rm(RM32, Reg32, [])].
333
334bs_op_sizeof({{reg32,_}, {rm32,RM32}}) ->		% bsf, bsr
335    2 + sizeof_rm(RM32).
336
337bswap_encode({{reg32,Reg32}}) ->
338    [16#0F, 16#C8 bor Reg32].
339
340bswap_sizeof({{reg32,_}}) ->
341    2.
342
343bt_op_encode(SubOpcode, Opnds) ->	% bt, btc, btr, bts
344    case Opnds of
345	{{rm32,RM32}, {reg32,Reg32}} ->
346	    [16#0F, 16#A3 bor (SubOpcode bsl 3) | encode_rm(RM32, Reg32, [])];
347	{{rm32,RM32}, {imm8,Imm8}} ->
348	    [16#0F, 16#BA | encode_rm(RM32, SubOpcode, [Imm8])]
349    end.
350
351bt_op_sizeof(Opnds) ->			% bt, btc, btr, bts
352    case Opnds of
353	{{rm32,RM32}, {reg32,_}} ->
354	    2 + sizeof_rm(RM32);
355	{{rm32,RM32}, {imm8,_}} ->
356	    2 + sizeof_rm(RM32) + 1
357    end.
358
359call_encode(Opnds) ->
360    case Opnds of
361	{{rel32,Rel32}} ->
362	    [16#E8 | le32(Rel32, [])];
363	{{rm32,RM32}} ->
364	    [16#FF | encode_rm(RM32, 2#010, [])]
365    end.
366
367call_sizeof(Opnds) ->
368    case Opnds of
369	{{rel32,_}} ->
370	    1 + 4;
371	{{rm32,RM32}} ->
372	    1 + sizeof_rm(RM32)
373    end.
374
375cbw_encode({}) ->
376    [?PFX_OPND, 16#98].
377
378cbw_sizeof({}) ->
379    2.
380
381nullary_op_encode(Opcode, {}) ->
382    %% cdq, clc, cld, cmc, cwde, into, leave, nop, prefix_fs, stc, std
383    [Opcode].
384
385nullary_op_sizeof({}) ->
386    %% cdq, clc, cld, cmc, cwde, into, leave, nop, prefix_fs, stc, std
387    1.
388
389cmovcc_encode({{cc,CC}, {reg32,Reg32}, {rm32,RM32}}) ->
390    [16#0F, 16#40 bor CC | encode_rm(RM32, Reg32, [])].
391
392cmovcc_sizeof({{cc,_}, {reg32,_}, {rm32,RM32}}) ->
393    2 + sizeof_rm(RM32).
394
395incdec_encode(SubOpcode, Opnds) ->	% SubOpcode is either 0 or 1
396    case Opnds of
397	{{rm32,RM32}} ->
398	    [16#FF | encode_rm(RM32, SubOpcode, [])];
399	{{reg32,Reg32}} ->
400	    [16#40 bor (SubOpcode bsl 3) bor Reg32]
401    end.
402
403incdec_sizeof(Opnds) ->
404    case Opnds of
405	{{rm32,RM32}} ->
406	    1 + sizeof_rm(RM32);
407	{{reg32,_}} ->
408	    1
409    end.
410
411arith_unop_encode(Opcode, {{rm32,RM32}}) ->	% div, idiv, mul, neg, not
412    [16#F7 | encode_rm(RM32, Opcode, [])].
413
414arith_unop_sizeof({{rm32,RM32}}) ->	% div, idiv, mul, neg, not
415    1 + sizeof_rm(RM32).
416
417enter_encode({{imm16,Imm16}, {imm8,Imm8}}) ->
418    [16#C8 | le16(Imm16, [Imm8])].
419
420enter_sizeof({{imm16,_}, {imm8,_}}) ->
421    1 + 2 + 1.
422
423imul_encode(Opnds) ->
424    case Opnds of
425	{{rm32,RM32}} ->				% <edx,eax> *= rm32
426	    [16#F7 | encode_rm(RM32, 2#101, [])];
427	{{reg32,Reg32}, {rm32,RM32}} ->			% reg *= rm32
428	    [16#0F, 16#AF | encode_rm(RM32, Reg32, [])];
429	{{reg32,Reg32}, {rm32,RM32}, {imm8,Imm8}} ->	% reg := rm32 * sext(imm8)
430	    [16#6B | encode_rm(RM32, Reg32, [Imm8])];
431	{{reg32,Reg32}, {rm32,RM32}, {imm32,Imm32}} ->	% reg := rm32 * imm32
432	    [16#69 | encode_rm(RM32, Reg32, le32(Imm32, []))]
433    end.
434
435imul_sizeof(Opnds) ->
436    case Opnds of
437	{{rm32,RM32}} ->
438	    1 + sizeof_rm(RM32);
439	{{reg32,_}, {rm32,RM32}} ->
440	    2 + sizeof_rm(RM32);
441	{{reg32,_}, {rm32,RM32}, {imm8,_}} ->
442	    1 + sizeof_rm(RM32) + 1;
443	{{reg32,_}, {rm32,RM32}, {imm32,_}} ->
444	    1 + sizeof_rm(RM32) + 4
445    end.
446
447jcc_encode(Opnds) ->
448    case Opnds of
449	{{cc,CC}, {rel8,Rel8}} ->
450	    [16#70 bor CC, Rel8];
451	{{cc,CC}, {rel32,Rel32}} ->
452	    [16#0F, 16#80 bor CC | le32(Rel32, [])]
453    end.
454
455jcc_sizeof(Opnds) ->
456    case Opnds of
457	{{cc,_}, {rel8,_}} ->
458	    2;
459	{{cc,_}, {rel32,_}} ->
460	    2 + 4
461    end.
462
463jmp8_op_encode(Opcode, {{rel8,Rel8}}) ->	% jecxz, loop, loope, loopne
464    [Opcode, Rel8].
465
466jmp8_op_sizeof({{rel8,_}}) ->			% jecxz, loop, loope, loopne
467    2.
468
469jmp_encode(Opnds) ->
470    case Opnds of
471	{{rel8,Rel8}} ->
472	    [16#EB, Rel8];
473	{{rel32,Rel32}} ->
474	    [16#E9 | le32(Rel32, [])];
475	{{rm32,RM32}} ->
476	    [16#FF | encode_rm(RM32, 2#100, [])]
477    end.
478
479jmp_sizeof(Opnds) ->
480    case Opnds of
481	{{rel8,_}} ->
482	    2;
483	{{rel32,_}} ->
484	    1 + 4;
485	{{rm32,RM32}} ->
486	    1 + sizeof_rm(RM32)
487    end.
488
489lea_encode({{reg32,Reg32}, {ea,EA}}) ->
490    [16#8D | enc_ea(EA, Reg32, [])].
491
492lea_sizeof({{reg32,_}, {ea,EA}}) ->
493    1 + sizeof_ea(EA).
494
495mov_encode(Opnds) ->
496    case Opnds of
497	{{rm8,RM8}, {reg8,Reg8}} ->
498	    [16#88 | encode_rm(RM8, Reg8, [])];
499	{{rm16,RM16}, {reg16,Reg16}} ->
500	    [?PFX_OPND, 16#89 | encode_rm(RM16, Reg16, [])];
501	{{rm32,RM32}, {reg32,Reg32}} ->
502	    [16#89 | encode_rm(RM32, Reg32, [])];
503	{{reg8,Reg8}, {rm8,RM8}} ->
504	    [16#8A | encode_rm(RM8, Reg8, [])];
505	{{reg16,Reg16}, {rm16,RM16}} ->
506	    [?PFX_OPND, 16#8B | encode_rm(RM16, Reg16, [])];
507	{{reg32,Reg32}, {rm32,RM32}} ->
508	    [16#8B | encode_rm(RM32, Reg32, [])];
509	{al, {moffs8,Moffs8}} ->
510	    [16#A0 | le32(Moffs8, [])];
511	{ax, {moffs16,Moffs16}} ->
512	    [?PFX_OPND, 16#A1 | le32(Moffs16, [])];
513	{eax, {moffs32,Moffs32}} ->
514	    [16#A1 | le32(Moffs32, [])];
515	{{moffs8,Moffs8}, al} ->
516	    [16#A2 | le32(Moffs8, [])];
517	{{moffs16,Moffs16}, ax} ->
518	    [?PFX_OPND, 16#A3 | le32(Moffs16, [])];
519	{{moffs32,Moffs32}, eax} ->
520	    [16#A3 | le32(Moffs32, [])];
521	{{reg8,Reg8}, {imm8,Imm8}} ->
522	    [16#B0 bor Reg8, Imm8];
523	{{reg16,Reg16}, {imm16,Imm16}} ->
524	    [?PFX_OPND, 16#B8 bor Reg16 | le16(Imm16, [])];
525	{{reg32,Reg32}, {imm32,Imm32}} ->
526	    [16#B8 bor Reg32 | le32(Imm32, [])];
527	{{rm8,RM8}, {imm8,Imm8}} ->
528	    [16#C6 | encode_rm(RM8, 2#000, [Imm8])];
529	{{rm16,RM16}, {imm16,Imm16}} ->
530	    [?PFX_OPND, 16#C7 | encode_rm(RM16, 2#000, le16(Imm16, []))];
531	{{rm32,RM32}, {imm32,Imm32}} ->
532	    [16#C7 | encode_rm(RM32, 2#000, le32(Imm32, []))]
533    end.
534
535mov_sizeof(Opnds) ->
536    case Opnds of
537	{{rm8,RM8}, {reg8,_}} ->
538	    1 + sizeof_rm(RM8);
539	{{rm16,RM16}, {reg16,_}} ->
540	    2 + sizeof_rm(RM16);
541	{{rm32,RM32}, {reg32,_}} ->
542	    1 + sizeof_rm(RM32);
543	{{reg8,_}, {rm8,RM8}} ->
544	    1 + sizeof_rm(RM8);
545	{{reg16,_}, {rm16,RM16}} ->
546	    2 + sizeof_rm(RM16);
547	{{reg32,_}, {rm32,RM32}} ->
548	    1 + sizeof_rm(RM32);
549	{al, {moffs8,_}} ->
550	    1 + 4;
551	{ax, {moffs16,_}} ->
552	    2 + 4;
553	{eax, {moffs32,_}} ->
554	    1 + 4;
555	{{moffs8,_}, al} ->
556	    1 + 4;
557	{{moffs16,_}, ax} ->
558	    2 + 4;
559	{{moffs32,_}, eax} ->
560	    1 + 4;
561	{{reg8,_}, {imm8,_}} ->
562	    2;
563	{{reg16,_}, {imm16,_}} ->
564	    2 + 2;
565	{{reg32,_}, {imm32,_}} ->
566	    1 + 4;
567	{{rm8,RM8}, {imm8,_}} ->
568	    1 + sizeof_rm(RM8) + 1;
569	{{rm16,RM16}, {imm16,_}} ->
570	    2 + sizeof_rm(RM16) + 2;
571	{{rm32,RM32}, {imm32,_}} ->
572	    1 + sizeof_rm(RM32) + 4
573    end.
574
575movx_op_encode(Opcode, Opnds) ->	% movsx, movzx
576    case Opnds of
577	{{reg16,Reg16}, {rm8,RM8}} ->
578	    [?PFX_OPND, 16#0F, Opcode | encode_rm(RM8, Reg16, [])];
579	{{reg32,Reg32}, {rm8,RM8}} ->
580	    [16#0F, Opcode | encode_rm(RM8, Reg32, [])];
581	{{reg32,Reg32}, {rm16,RM16}} ->
582	    [16#0F, Opcode bor 1 | encode_rm(RM16, Reg32, [])]
583    end.
584
585movx_op_sizeof(Opnds) ->
586    case Opnds of
587	{{reg16,_}, {rm8,RM8}} ->
588	    3 + sizeof_rm(RM8);
589	{{reg32,_}, {rm8,RM8}} ->
590	    2 + sizeof_rm(RM8);
591	{{reg32,_}, {rm16,RM16}} ->
592	    2 + sizeof_rm(RM16)
593    end.
594
595pop_encode(Opnds) ->
596    case Opnds of
597	{{rm32,RM32}} ->
598	    [16#8F | encode_rm(RM32, 2#000, [])];
599	{{reg32,Reg32}} ->
600	    [16#58 bor Reg32]
601    end.
602
603pop_sizeof(Opnds) ->
604    case Opnds of
605	{{rm32,RM32}} ->
606	    1 + sizeof_rm(RM32);
607	{{reg32,_}} ->
608	    1
609    end.
610
611push_encode(Opnds) ->
612    case Opnds of
613	{{rm32,RM32}} ->
614	    [16#FF | encode_rm(RM32, 2#110, [])];
615	{{reg32,Reg32}} ->
616	    [16#50 bor Reg32];
617	{{imm8,Imm8}} ->	% sign-extended
618	    [16#6A, Imm8];
619	{{imm32,Imm32}} ->
620	    [16#68 | le32(Imm32, [])]
621    end.
622
623push_sizeof(Opnds) ->
624    case Opnds of
625	{{rm32,RM32}} ->
626	    1 + sizeof_rm(RM32);
627	{{reg32,_}} ->
628	    1;
629	{{imm8,_}} ->
630	    2;
631	{{imm32,_}} ->
632	    1 + 4
633    end.
634
635shift_op_encode(SubOpcode, Opnds) ->	% rcl, rcr, rol, ror, sar, shl, shr
636    case Opnds of
637	{{rm32,RM32}, 1} ->
638	    [16#D1 | encode_rm(RM32, SubOpcode, [])];
639	{{rm32,RM32}, cl} ->
640	    [16#D3 | encode_rm(RM32, SubOpcode, [])];
641	{{rm32,RM32}, {imm8,Imm8}} ->
642	    [16#C1 | encode_rm(RM32, SubOpcode, [Imm8])];
643	{{rm16,RM16}, {imm8,Imm8}} ->
644	    [?PFX_OPND, 16#C1 | encode_rm(RM16, SubOpcode, [Imm8])]
645    end.
646
647shift_op_sizeof(Opnds) ->		% rcl, rcr, rol, ror, sar, shl, shr
648    case Opnds of
649	{{rm32,RM32}, 1} ->
650	    1 + sizeof_rm(RM32);
651	{{rm32,RM32}, cl} ->
652	    1 + sizeof_rm(RM32);
653	{{rm32,RM32}, {imm8,_Imm8}} ->
654	    1 + sizeof_rm(RM32) + 1;
655	{{rm16,RM16}, {imm8,_Imm8}} ->
656	    1 + 1 + sizeof_rm(RM16) + 1
657    end.
658
659ret_encode(Opnds) ->
660    case Opnds of
661	{} ->
662	    [16#C3];
663	{{imm16,Imm16}} ->
664	    [16#C2 | le16(Imm16, [])]
665    end.
666
667ret_sizeof(Opnds) ->
668    case Opnds of
669	{} ->
670	    1;
671	{{imm16,_}} ->
672	    1 + 2
673    end.
674
675setcc_encode({{cc,CC}, {rm8,RM8}}) ->
676    [16#0F, 16#90 bor CC | encode_rm(RM8, 2#000, [])].
677
678setcc_sizeof({{cc,_}, {rm8,RM8}}) ->
679    2 + sizeof_rm(RM8).
680
681shd_op_encode(Opcode, Opnds) ->
682    case Opnds of
683	{{rm32,RM32}, {reg32,Reg32}, {imm8,Imm8}} ->
684	    [16#0F, Opcode | encode_rm(RM32, Reg32, [Imm8])];
685	{{rm32,RM32}, {reg32,Reg32}, cl} ->
686	    [16#0F, Opcode bor 1 | encode_rm(RM32, Reg32, [])]
687    end.
688
689shd_op_sizeof(Opnds) ->
690    case Opnds of
691	{{rm32,RM32}, {reg32,_}, {imm8,_}} ->
692	    2 + sizeof_rm(RM32) + 1;
693	{{rm32,RM32}, {reg32,_}, cl} ->
694	    2 + sizeof_rm(RM32)
695    end.
696
697test_encode(Opnds) ->
698    case Opnds of
699	{al, {imm8,Imm8}} ->
700	    [16#A8, Imm8];
701	{ax, {imm16,Imm16}} ->
702	    [?PFX_OPND, 16#A9 | le16(Imm16, [])];
703	{eax, {imm32,Imm32}} ->
704	    [16#A9 | le32(Imm32, [])];
705	{{rm8,RM8}, {imm8,Imm8}} ->
706	    [16#F6 | encode_rm(RM8, 2#000, [Imm8])];
707	{{rm16,RM16}, {imm16,Imm16}} ->
708	    [?PFX_OPND, 16#F7 | encode_rm(RM16, 2#000, le16(Imm16, []))];
709	{{rm32,RM32}, {imm32,Imm32}} ->
710	    [16#F7 | encode_rm(RM32, 2#000, le32(Imm32, []))];
711	{{rm32,RM32}, {reg32,Reg32}} ->
712	    [16#85 | encode_rm(RM32, Reg32, [])]
713    end.
714
715test_sizeof(Opnds) ->
716    case Opnds of
717	{al, {imm8,_}} ->
718	    1 + 1;
719	{ax, {imm16,_}} ->
720	    2 + 2;
721	{eax, {imm32,_}} ->
722	    1 + 4;
723	{{rm8,RM8}, {imm8,_}} ->
724	    1 + sizeof_rm(RM8) + 1;
725	{{rm16,RM16}, {imm16,_}} ->
726	    2 + sizeof_rm(RM16) + 2;
727	{{rm32,RM32}, {imm32,_}} ->
728	    1 + sizeof_rm(RM32) + 4;
729	{{rm32,RM32}, {reg32,_}} ->
730	    1 + sizeof_rm(RM32)
731    end.
732
733fild_encode(Opnds) ->
734    %% The operand cannot be a register!
735    {{rm32, RM32}} = Opnds,
736    [16#DB | encode_rm(RM32, 2#000, [])].
737
738fild_sizeof(Opnds) ->
739    {{rm32, RM32}} = Opnds,
740    1 + sizeof_rm(RM32).
741
742fld_encode(Opnds) ->
743    case Opnds of
744	{{rm64fp, RM64fp}} ->
745	    [16#DD | encode_rm(RM64fp, 2#000, [])];
746	{{fpst, St}} ->
747	    [16#D9, 16#C0 bor st(St)]
748    end.
749
750fld_sizeof(Opnds) ->
751    case Opnds of
752	{{rm64fp, RM64fp}} ->
753	    1 + sizeof_rm(RM64fp);
754	{{fpst, _}} ->
755	    2
756    end.
757
758fp_comm_arith_encode(OpCode, Opnds) ->
759    %% fadd, fmul
760    case Opnds of
761	{{rm64fp, RM64fp}} ->
762	    [16#DC | encode_rm(RM64fp, OpCode, [])];
763	{{fpst,0}, {fpst,St}} ->
764	    [16#D8, (16#C0 bor (OpCode bsl 3)) bor st(St)];
765	{{fpst,St}, {fpst,0}} ->
766	    [16#DC, (16#C0 bor (OpCode bsl 3)) bor st(St)]
767    end.
768
769fp_comm_arith_pop_encode(OpCode, Opnds) ->
770    %% faddp, fmulp
771    case Opnds of
772	[] ->
773	    [16#DE, 16#C0 bor (OpCode bsl 3) bor st(1)];
774	{{fpst,St},{fpst,0}} ->
775	    [16#DE, 16#C0 bor (OpCode bsl 3) bor st(St)]
776    end.
777
778fp_arith_encode(OpCode, Opnds) ->
779    %% fdiv, fsub
780    case Opnds of
781	{{rm64fp, RM64fp}} ->
782	    [16#DC | encode_rm(RM64fp, OpCode, [])];
783	{{fpst,0}, {fpst,St}} ->
784	    OpCode0 = OpCode band 2#110,
785	    [16#D8, 16#C0 bor (OpCode0 bsl 3) bor st(St)];
786	{{fpst,St}, {fpst,0}} ->
787	    OpCode0 = OpCode bor 1,
788	    [16#DC, 16#C0 bor (OpCode0 bsl 3) bor st(St)]
789    end.
790
791fp_arith_pop_encode(OpCode, Opnds) ->
792    %% fdivp, fsubp
793    OpCode0 = OpCode bor 1,
794    case Opnds of
795	[] ->
796	    [16#DE, 16#C8 bor (OpCode0 bsl 3) bor st(1)];
797	{{fpst,St}, {fpst,0}} ->
798	    [16#DE, 16#C8 bor (OpCode0 bsl 3) bor st(St)]
799    end.
800
801fp_arith_rev_encode(OpCode, Opnds) ->
802    %% fdivr, fsubr
803    case Opnds of
804	{{rm64fp, RM64fp}} ->
805	    [16#DC | encode_rm(RM64fp, OpCode, [])];
806	{{fpst,0}, {fpst,St}} ->
807	    OpCode0 = OpCode bor 1,
808	    [16#D8, 16#C0 bor (OpCode0 bsl 3) bor st(St)];
809	{{fpst,St}, {fpst,0}} ->
810	    OpCode0 = OpCode band 2#110,
811	    [16#DC, 16#C0 bor (OpCode0 bsl 3) bor st(St)]
812    end.
813
814fp_arith_rev_pop_encode(OpCode, Opnds) ->
815    %% fdivrp, fsubrp
816    OpCode0 = OpCode band 2#110,
817    case Opnds of
818	[] ->
819	    [16#DE, 16#C0 bor (OpCode0 bsl 3) bor st(1)];
820	{{fpst,St}, {fpst, 0}} ->
821	    [16#DE, 16#C0 bor (OpCode0 bsl 3) bor st(St)]
822    end.
823
824fp_arith_sizeof(Opnds) ->
825    case Opnds of
826	{{rm64fp, RM64fp}} ->
827	    1 + sizeof_rm(RM64fp);
828	{{fpst,0}, {fpst,_}} ->
829	    2;
830	{{fpst,_}, {fpst,0}} ->
831	    2
832    end.
833
834fst_encode(OpCode, Opnds) ->
835    case Opnds of
836	{{rm64fp, RM64fp}} ->
837	    [16#DD | encode_rm(RM64fp, OpCode, [])];
838	{{fpst, St}} ->
839	    [16#DD, 16#C0 bor (OpCode bsl 3) bor st(St)]
840    end.
841
842fst_sizeof(Opnds) ->
843    case Opnds of
844	{{rm64fp, RM64fp}} ->
845	    1 + sizeof_rm(RM64fp);
846	{{fpst, _}} ->
847	    2
848    end.
849
850fchs_encode() ->
851    [16#D9, 16#E0].
852fchs_sizeof() ->
853    2.
854
855ffree_encode({{fpst, St}})->
856    [16#DD, 16#C0 bor st(St)].
857ffree_sizeof() ->
858    2.
859
860fwait_encode() ->
861    [16#9B].
862fwait_sizeof() ->
863    1.
864
865fxch_encode(Opnds) ->
866    case Opnds of
867	[] ->
868	    [16#D9, 16#C8 bor st(1)];
869	{{fpst, St}} ->
870	    [16#D9, 16#C8 bor st(St)]
871    end.
872fxch_sizeof() ->
873    2.
874
875insn_encode(Op, Opnds, Offset) ->
876    Bytes = insn_encode_internal(Op, Opnds),
877    case has_relocs(Bytes) of
878	false ->	% the common case
879	    {Bytes, []};
880	_ ->
881	    fix_relocs(Bytes, Offset, [], [])
882    end.
883
884has_relocs([{le32,_,_}|_]) -> true;
885has_relocs([_|Bytes]) -> has_relocs(Bytes);
886has_relocs([]) -> false.
887
888fix_relocs([{le32,Tag,Val}|Bytes], Offset, Code, Relocs) ->
889    fix_relocs(Bytes, Offset+4,
890	       [16#00, 16#00, 16#00, 16#00 | Code],
891	       [{Tag,Offset,Val}|Relocs]);
892fix_relocs([Byte|Bytes], Offset, Code, Relocs) ->
893    fix_relocs(Bytes, Offset+1, [Byte|Code], Relocs);
894fix_relocs([], _Offset, Code, Relocs) ->
895    {lists:reverse(Code), lists:reverse(Relocs)}.
896
897insn_encode_internal(Op, Opnds) ->
898    case Op of
899	'adc' -> arith_binop_encode(2#010, Opnds);
900	'add' -> arith_binop_encode(2#000, Opnds);
901	'and' -> arith_binop_encode(2#100, Opnds);
902	'bsf' -> bs_op_encode(16#BC, Opnds);
903	'bsr' -> bs_op_encode(16#BD, Opnds);
904	'bswap' -> bswap_encode(Opnds);
905	'bt' -> bt_op_encode(2#100, Opnds);
906	'btc' -> bt_op_encode(2#111, Opnds);
907	'btr' -> bt_op_encode(2#110, Opnds);
908	'bts' -> bt_op_encode(2#101, Opnds);
909	'call' -> call_encode(Opnds);
910	'cbw' -> cbw_encode(Opnds);
911	'cdq' -> nullary_op_encode(16#99, Opnds);
912	'clc' -> nullary_op_encode(16#F8, Opnds);
913	'cld' -> nullary_op_encode(16#FC, Opnds);
914	'cmc' -> nullary_op_encode(16#F5, Opnds);
915	'cmovcc' -> cmovcc_encode(Opnds);
916	'cmp' -> arith_binop_encode(2#111, Opnds);
917	'cwde' -> nullary_op_encode(16#98, Opnds);
918	'dec' -> incdec_encode(2#001, Opnds);
919	'div' -> arith_unop_encode(2#110, Opnds);
920	'enter' -> enter_encode(Opnds);
921	'fadd' -> fp_comm_arith_encode(2#000, Opnds);
922	'faddp' -> fp_comm_arith_pop_encode(2#000, Opnds);
923	'fchs' -> fchs_encode();
924	'fdiv' -> fp_arith_encode(2#110, Opnds);
925	'fdivp' -> fp_arith_pop_encode(2#110, Opnds);
926	'fdivr' -> fp_arith_rev_encode(2#111, Opnds);
927	'fdivrp' -> fp_arith_rev_pop_encode(2#111, Opnds);
928	'ffree' -> ffree_encode(Opnds);
929	'fild' -> fild_encode(Opnds);
930	'fld' -> fld_encode(Opnds);
931	'fmul' -> fp_comm_arith_encode(2#001, Opnds);
932	'fmulp' -> fp_comm_arith_pop_encode(2#001, Opnds);
933	'fst' -> fst_encode(2#010, Opnds);
934	'fstp' -> fst_encode(2#011, Opnds);
935	'fsub' -> fp_arith_encode(2#100, Opnds);
936	'fsubp' -> fp_arith_pop_encode(2#100, Opnds);
937	'fsubr' -> fp_arith_rev_encode(2#101, Opnds);
938	'fsubrp' -> fp_arith_rev_pop_encode(2#101, Opnds);
939	'fwait' -> fwait_encode();
940	'fxch' -> fxch_encode(Opnds);
941	'idiv' -> arith_unop_encode(2#111, Opnds);
942	'imul' -> imul_encode(Opnds);
943	'inc' -> incdec_encode(2#000, Opnds);
944	'into' -> nullary_op_encode(16#CE, Opnds);
945	'jcc' -> jcc_encode(Opnds);
946	'jecxz' -> jmp8_op_encode(16#E3, Opnds);
947	'jmp' -> jmp_encode(Opnds);
948	'lea' -> lea_encode(Opnds);
949	'leave' -> nullary_op_encode(16#C9, Opnds);
950	'loop' -> jmp8_op_encode(16#E2, Opnds);
951	'loope' -> jmp8_op_encode(16#E1, Opnds);
952	'loopne' -> jmp8_op_encode(16#E0, Opnds);
953	'mov' -> mov_encode(Opnds);
954	'movsx' -> movx_op_encode(16#BE, Opnds);
955	'movzx' -> movx_op_encode(16#B6, Opnds);
956	'mul' -> arith_unop_encode(2#100, Opnds);
957	'neg' -> arith_unop_encode(2#011, Opnds);
958	'nop' -> nullary_op_encode(16#90, Opnds);
959	'not' -> arith_unop_encode(2#010, Opnds);
960	'or' -> arith_binop_encode(2#001, Opnds);
961	'pop' -> pop_encode(Opnds);
962	'prefix_fs' -> nullary_op_encode(16#64, Opnds);
963	'push' -> push_encode(Opnds);
964	'rcl' -> shift_op_encode(2#010, Opnds);
965	'rcr' -> shift_op_encode(2#011, Opnds);
966	'ret' -> ret_encode(Opnds);
967	'rol' -> shift_op_encode(2#000, Opnds);
968	'ror' -> shift_op_encode(2#001, Opnds);
969	'sar' -> shift_op_encode(2#111, Opnds);
970	'sbb' -> arith_binop_encode(2#011, Opnds);
971	'setcc' -> setcc_encode(Opnds);
972	'shl' -> shift_op_encode(2#100, Opnds);
973	'shld' -> shd_op_encode(16#A4, Opnds);
974	'shr' -> shift_op_encode(2#101, Opnds);
975	'shrd' -> shd_op_encode(16#AC, Opnds);
976	'stc' -> nullary_op_encode(16#F9, Opnds);
977	'std' -> nullary_op_encode(16#FD, Opnds);
978	'sub' -> arith_binop_encode(2#101, Opnds);
979	'test' -> test_encode(Opnds);
980	'xor' -> arith_binop_encode(2#110, Opnds);
981	_ -> exit({?MODULE,insn_encode,Op})
982    end.
983
984insn_sizeof(Op, Opnds) ->
985    case Op of
986	'adc' -> arith_binop_sizeof(Opnds);
987	'add' -> arith_binop_sizeof(Opnds);
988	'and' -> arith_binop_sizeof(Opnds);
989	'bsf' -> bs_op_sizeof(Opnds);
990	'bsr' -> bs_op_sizeof(Opnds);
991	'bswap' -> bswap_sizeof(Opnds);
992	'bt' -> bt_op_sizeof(Opnds);
993	'btc' -> bt_op_sizeof(Opnds);
994	'btr' -> bt_op_sizeof(Opnds);
995	'bts' -> bt_op_sizeof(Opnds);
996	'call' -> call_sizeof(Opnds);
997	'cbw' -> cbw_sizeof(Opnds);
998	'cdq' -> nullary_op_sizeof(Opnds);
999	'clc' -> nullary_op_sizeof(Opnds);
1000	'cld' -> nullary_op_sizeof(Opnds);
1001	'cmc' -> nullary_op_sizeof(Opnds);
1002	'cmovcc' -> cmovcc_sizeof(Opnds);
1003	'cmp' -> arith_binop_sizeof(Opnds);
1004	'cwde' -> nullary_op_sizeof(Opnds);
1005	'dec' -> incdec_sizeof(Opnds);
1006	'div' -> arith_unop_sizeof(Opnds);
1007	'enter' -> enter_sizeof(Opnds);
1008	'fadd' -> fp_arith_sizeof(Opnds);
1009	'faddp' -> fp_arith_sizeof(Opnds);
1010	'fchs' -> fchs_sizeof();
1011	'fdiv' -> fp_arith_sizeof(Opnds);
1012	'fdivp' -> fp_arith_sizeof(Opnds);
1013	'fdivr' -> fp_arith_sizeof(Opnds);
1014	'fdivrp' -> fp_arith_sizeof(Opnds);
1015	'ffree' -> ffree_sizeof();
1016	'fild' -> fild_sizeof(Opnds);
1017	'fld' -> fld_sizeof(Opnds);
1018	'fmul' -> fp_arith_sizeof(Opnds);
1019	'fmulp' -> fp_arith_sizeof(Opnds);
1020	'fst' -> fst_sizeof(Opnds);
1021	'fstp' -> fst_sizeof(Opnds);
1022	'fsub' -> fp_arith_sizeof(Opnds);
1023	'fsubp' -> fp_arith_sizeof(Opnds);
1024	'fsubr' -> fp_arith_sizeof(Opnds);
1025	'fsubrp' -> fp_arith_sizeof(Opnds);
1026	'fwait' -> fwait_sizeof();
1027	'fxch' -> fxch_sizeof();
1028	'idiv' -> arith_unop_sizeof(Opnds);
1029	'imul' -> imul_sizeof(Opnds);
1030	'inc' -> incdec_sizeof(Opnds);
1031	'into' -> nullary_op_sizeof(Opnds);
1032	'jcc' -> jcc_sizeof(Opnds);
1033	'jecxz' -> jmp8_op_sizeof(Opnds);
1034	'jmp' -> jmp_sizeof(Opnds);
1035	'lea' -> lea_sizeof(Opnds);
1036	'leave' -> nullary_op_sizeof(Opnds);
1037	'loop' -> jmp8_op_sizeof(Opnds);
1038	'loope' -> jmp8_op_sizeof(Opnds);
1039	'loopne' -> jmp8_op_sizeof(Opnds);
1040	'mov' -> mov_sizeof(Opnds);
1041	'movsx' -> movx_op_sizeof(Opnds);
1042	'movzx' -> movx_op_sizeof(Opnds);
1043	'mul' -> arith_unop_sizeof(Opnds);
1044	'neg' -> arith_unop_sizeof(Opnds);
1045	'nop' -> nullary_op_sizeof(Opnds);
1046	'not' -> arith_unop_sizeof(Opnds);
1047	'or' -> arith_binop_sizeof(Opnds);
1048	'pop' -> pop_sizeof(Opnds);
1049	'prefix_fs' -> nullary_op_sizeof(Opnds);
1050	'push' -> push_sizeof(Opnds);
1051	'rcl' -> shift_op_sizeof(Opnds);
1052	'rcr' -> shift_op_sizeof(Opnds);
1053	'ret' -> ret_sizeof(Opnds);
1054	'rol' -> shift_op_sizeof(Opnds);
1055	'ror' -> shift_op_sizeof(Opnds);
1056	'sar' -> shift_op_sizeof(Opnds);
1057	'sbb' -> arith_binop_sizeof(Opnds);
1058	'setcc' -> setcc_sizeof(Opnds);
1059	'shl' -> shift_op_sizeof(Opnds);
1060	'shld' -> shd_op_sizeof(Opnds);
1061	'shr' -> shift_op_sizeof(Opnds);
1062	'shrd' -> shd_op_sizeof(Opnds);
1063	'stc' -> nullary_op_sizeof(Opnds);
1064	'std' -> nullary_op_sizeof(Opnds);
1065	'sub' -> arith_binop_sizeof(Opnds);
1066	'test' -> test_sizeof(Opnds);
1067	'xor' -> arith_binop_sizeof(Opnds);
1068	_ -> exit({?MODULE,insn_sizeof,Op})
1069    end.
1070
1071%%=====================================================================
1072%% testing interface
1073%%=====================================================================
1074
1075-ifdef(DO_HIPE_X86_ENCODE_TEST).
1076
1077say(OS, Str) ->
1078    file:write(OS, Str).
1079
1080digit16(Dig0) ->
1081    Dig = Dig0 band 16#F,
1082    if Dig >= 16#A -> $A + (Dig - 16#A);
1083       true -> $0 + Dig
1084    end.
1085
1086say_byte(OS, Byte) ->
1087    say(OS, "0x"),
1088    say(OS, [digit16(Byte bsr 4)]),
1089    say(OS, [digit16(Byte)]).
1090
1091init(OS) ->
1092    say(OS, "\t.text\n").
1093
1094say_bytes(OS, Byte0, Bytes0) ->
1095    say_byte(OS, Byte0),
1096    case Bytes0 of
1097	[] ->
1098	    say(OS, "\n");
1099	[Byte1|Bytes1] ->
1100	    say(OS, ","),
1101	    say_bytes(OS, Byte1, Bytes1)
1102    end.
1103
1104t(OS, Op, Opnds) ->
1105    insn_sizeof(Op, Opnds),
1106    {[Byte|Bytes],[]} = insn_encode(Op, Opnds, 0),
1107    say(OS, "\t.byte "),
1108    say_bytes(OS, Byte, Bytes).
1109
1110dotest1(OS) ->
1111    init(OS),
1112    % exercise all rm32 types
1113    t(OS,lea,{{reg32,?EAX},{ea,ea_disp32(16#87654321)}}),
1114    t(OS,lea,{{reg32,?EAX},{ea,ea_sib(sib(?ECX))}}),
1115    t(OS,lea,{{reg32,?EAX},{ea,ea_sib(sib(?ECX,sindex(2#10,?EDI)))}}),
1116    t(OS,lea,{{reg32,?EAX},{ea,ea_disp32_sindex(16#87654321)}}),
1117    t(OS,lea,{{reg32,?EAX},{ea,ea_disp32_sindex(16#87654321,sindex(2#10,?EDI))}}),
1118    t(OS,lea,{{reg32,?EAX},{ea,ea_base(?ECX)}}),
1119    t(OS,lea,{{reg32,?EAX},{ea,ea_disp8_sib(16#03,sib(?ECX))}}),
1120    t(OS,lea,{{reg32,?EAX},{ea,ea_disp8_sib(16#03,sib(?ECX,sindex(2#10,?EDI)))}}),
1121    t(OS,lea,{{reg32,?EAX},{ea,ea_disp8_base(16#3,?ECX)}}),
1122    t(OS,lea,{{reg32,?EAX},{ea,ea_disp32_sib(16#87654321,sib(?ECX))}}),
1123    t(OS,lea,{{reg32,?EAX},{ea,ea_disp32_sib(16#87654321,sib(?ECX,sindex(2#10,?EDI)))}}),
1124    t(OS,lea,{{reg32,?EAX},{ea,ea_disp32_base(16#87654321,?EBP)}}),
1125    t(OS,call,{{rm32,rm_reg(?EAX)}}),
1126    t(OS,call,{{rm32,rm_mem(ea_disp32_sindex(16#87654321,sindex(2#10,?EDI)))}}),
1127    t(OS,call,{{rel32,-5}}),
1128    % default parameters for the tests below
1129    Word32 = 16#87654321,
1130    Word16 = 16#F00F,
1131    Word8 = 16#80,
1132    Imm32 = {imm32,Word32},
1133    Imm16 = {imm16,Word16},
1134    Imm8 = {imm8,Word8},
1135    RM32 = {rm32,rm_reg(?EDX)},
1136    RM16 = {rm16,rm_reg(?EDX)},
1137    RM8 = {rm8,rm_reg(?EDX)},
1138    Rel32 = {rel32,Word32},
1139    Rel8 = {rel8,Word8},
1140    Moffs32 = {moffs32,Word32},
1141    Moffs16 = {moffs16,Word32},
1142    Moffs8 = {moffs8,Word32},
1143    CC = {cc,?CC_G},
1144    Reg32 = {reg32,?EAX},
1145    Reg16 = {reg16,?EAX},
1146    Reg8 = {reg8,?AH},
1147    EA = {ea,ea_base(?ECX)},
1148    % exercise each instruction definition
1149    t(OS,'adc',{eax,Imm32}),
1150    t(OS,'adc',{RM32,Imm32}),
1151    t(OS,'adc',{RM32,Imm8}),
1152    t(OS,'adc',{RM32,Reg32}),
1153    t(OS,'adc',{Reg32,RM32}),
1154    t(OS,'add',{eax,Imm32}),
1155    t(OS,'add',{RM32,Imm32}),
1156    t(OS,'add',{RM32,Imm8}),
1157    t(OS,'add',{RM32,Reg32}),
1158    t(OS,'add',{Reg32,RM32}),
1159    t(OS,'and',{eax,Imm32}),
1160    t(OS,'and',{RM32,Imm32}),
1161    t(OS,'and',{RM32,Imm8}),
1162    t(OS,'and',{RM32,Reg32}),
1163    t(OS,'and',{Reg32,RM32}),
1164    t(OS,'bsf',{Reg32,RM32}),
1165    t(OS,'bsr',{Reg32,RM32}),
1166    t(OS,'bswap',{Reg32}),
1167    t(OS,'bt',{RM32,Reg32}),
1168    t(OS,'bt',{RM32,Imm8}),
1169    t(OS,'btc',{RM32,Reg32}),
1170    t(OS,'btc',{RM32,Imm8}),
1171    t(OS,'btr',{RM32,Reg32}),
1172    t(OS,'btr',{RM32,Imm8}),
1173    t(OS,'bts',{RM32,Reg32}),
1174    t(OS,'bts',{RM32,Imm8}),
1175    t(OS,'call',{Rel32}),
1176    t(OS,'call',{RM32}),
1177    t(OS,'cbw',{}),
1178    t(OS,'cdq',{}),
1179    t(OS,'clc',{}),
1180    t(OS,'cld',{}),
1181    t(OS,'cmc',{}),
1182    t(OS,'cmovcc',{CC,Reg32,RM32}),
1183    t(OS,'cmp',{eax,Imm32}),
1184    t(OS,'cmp',{RM32,Imm32}),
1185    t(OS,'cmp',{RM32,Imm8}),
1186    t(OS,'cmp',{RM32,Reg32}),
1187    t(OS,'cmp',{Reg32,RM32}),
1188    t(OS,'cwde',{}),
1189    t(OS,'dec',{RM32}),
1190    t(OS,'dec',{Reg32}),
1191    t(OS,'div',{RM32}),
1192    t(OS,'enter',{Imm16,{imm8,3}}),
1193    t(OS,'idiv',{RM32}),
1194    t(OS,'imul',{RM32}),
1195    t(OS,'imul',{Reg32,RM32}),
1196    t(OS,'imul',{Reg32,RM32,Imm8}),
1197    t(OS,'imul',{Reg32,RM32,Imm32}),
1198    t(OS,'inc',{RM32}),
1199    t(OS,'inc',{Reg32}),
1200    t(OS,'into',{}),
1201    t(OS,'jcc',{CC,Rel8}),
1202    t(OS,'jcc',{CC,Rel32}),
1203    t(OS,'jecxz',{Rel8}),
1204    t(OS,'jmp',{Rel8}),
1205    t(OS,'jmp',{Rel32}),
1206    t(OS,'jmp',{RM32}),
1207    t(OS,'lea',{Reg32,EA}),
1208    t(OS,'leave',{}),
1209    t(OS,'loop',{Rel8}),
1210    t(OS,'loope',{Rel8}),
1211    t(OS,'loopne',{Rel8}),
1212    t(OS,'mov',{RM8,Reg8}),
1213    t(OS,'mov',{RM16,Reg16}),
1214    t(OS,'mov',{RM32,Reg32}),
1215    t(OS,'mov',{Reg8,RM8}),
1216    t(OS,'mov',{Reg16,RM16}),
1217    t(OS,'mov',{Reg32,RM32}),
1218    t(OS,'mov',{al,Moffs8}),
1219    t(OS,'mov',{ax,Moffs16}),
1220    t(OS,'mov',{eax,Moffs32}),
1221    t(OS,'mov',{Moffs8,al}),
1222    t(OS,'mov',{Moffs16,ax}),
1223    t(OS,'mov',{Moffs32,eax}),
1224    t(OS,'mov',{Reg8,Imm8}),
1225    t(OS,'mov',{Reg16,Imm16}),
1226    t(OS,'mov',{Reg32,Imm32}),
1227    t(OS,'mov',{RM8,Imm8}),
1228    t(OS,'mov',{RM16,Imm16}),
1229    t(OS,'mov',{RM32,Imm32}),
1230    t(OS,'movsx',{Reg16,RM8}),
1231    t(OS,'movsx',{Reg32,RM8}),
1232    t(OS,'movsx',{Reg32,RM16}),
1233    t(OS,'movzx',{Reg16,RM8}),
1234    t(OS,'movzx',{Reg32,RM8}),
1235    t(OS,'movzx',{Reg32,RM16}),
1236    t(OS,'mul',{RM32}),
1237    t(OS,'neg',{RM32}),
1238    t(OS,'nop',{}),
1239    t(OS,'not',{RM32}),
1240    t(OS,'or',{eax,Imm32}),
1241    t(OS,'or',{RM32,Imm32}),
1242    t(OS,'or',{RM32,Imm8}),
1243    t(OS,'or',{RM32,Reg32}),
1244    t(OS,'or',{Reg32,RM32}),
1245    t(OS,'pop',{RM32}),
1246    t(OS,'pop',{Reg32}),
1247    t(OS,'push',{RM32}),
1248    t(OS,'push',{Reg32}),
1249    t(OS,'push',{Imm8}),
1250    t(OS,'push',{Imm32}),
1251    t(OS,'rcl',{RM32,1}),
1252    t(OS,'rcl',{RM32,cl}),
1253    t(OS,'rcl',{RM32,Imm8}),
1254    t(OS,'rcl',{RM16,Imm8}),
1255    t(OS,'rcr',{RM32,1}),
1256    t(OS,'rcr',{RM32,cl}),
1257    t(OS,'rcr',{RM32,Imm8}),
1258    t(OS,'rcr',{RM16,Imm8}),
1259    t(OS,'ret',{}),
1260    t(OS,'ret',{Imm16}),
1261    t(OS,'rol',{RM32,1}),
1262    t(OS,'rol',{RM32,cl}),
1263    t(OS,'rol',{RM32,Imm8}),
1264    t(OS,'rol',{RM16,Imm8}),
1265    t(OS,'ror',{RM32,1}),
1266    t(OS,'ror',{RM32,cl}),
1267    t(OS,'ror',{RM32,Imm8}),
1268    t(OS,'ror',{RM16,Imm8}),
1269    t(OS,'sar',{RM32,1}),
1270    t(OS,'sar',{RM32,cl}),
1271    t(OS,'sar',{RM32,Imm8}),
1272    t(OS,'sar',{RM16,Imm8}),
1273    t(OS,'sbb',{eax,Imm32}),
1274    t(OS,'sbb',{RM32,Imm32}),
1275    t(OS,'sbb',{RM32,Imm8}),
1276    t(OS,'sbb',{RM32,Reg32}),
1277    t(OS,'sbb',{Reg32,RM32}),
1278    t(OS,'setcc',{CC,RM8}),
1279    t(OS,'shl',{RM32,1}),
1280    t(OS,'shl',{RM32,cl}),
1281    t(OS,'shl',{RM32,Imm8}),
1282    t(OS,'shl',{RM16,Imm8}),
1283    t(OS,'shld',{RM32,Reg32,Imm8}),
1284    t(OS,'shld',{RM32,Reg32,cl}),
1285    t(OS,'shr',{RM32,1}),
1286    t(OS,'shr',{RM32,cl}),
1287    t(OS,'shr',{RM32,Imm8}),
1288    t(OS,'shr',{RM16,Imm8}),
1289    t(OS,'shrd',{RM32,Reg32,Imm8}),
1290    t(OS,'shrd',{RM32,Reg32,cl}),
1291    t(OS,'stc',{}),
1292    t(OS,'std',{}),
1293    t(OS,'sub',{eax,Imm32}),
1294    t(OS,'sub',{RM32,Imm32}),
1295    t(OS,'sub',{RM32,Imm8}),
1296    t(OS,'sub',{RM32,Reg32}),
1297    t(OS,'sub',{Reg32,RM32}),
1298    t(OS,'test',{al,Imm8}),
1299    t(OS,'test',{ax,Imm16}),
1300    t(OS,'test',{eax,Imm32}),
1301    t(OS,'test',{RM8,Imm8}),
1302    t(OS,'test',{RM16,Imm16}),
1303    t(OS,'test',{RM32,Imm32}),
1304    t(OS,'test',{RM32,Reg32}),
1305    t(OS,'xor',{eax,Imm32}),
1306    t(OS,'xor',{RM32,Imm32}),
1307    t(OS,'xor',{RM32,Imm8}),
1308    t(OS,'xor',{RM32,Reg32}),
1309    t(OS,'xor',{Reg32,RM32}),
1310    t(OS,'prefix_fs',{}), t(OS,'add',{{reg32,?EAX},{rm32,rm_mem(ea_disp32(16#20))}}),
1311    [].
1312
1313dotest() -> dotest1(group_leader()).	% stdout == group_leader
1314
1315dotest(File) ->
1316    {ok,OS} = file:open(File, [write]),
1317    dotest1(OS),
1318    file:close(OS).
1319-endif.
1320