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