📄 x86-defs.m4
字号:
define(x86_opcode_reg32_p,m4_assert_onearg()`x86_lookup_p(`$1',x86_opcode_reg32_list)')define(x86_opcode_reg32_list,``%eax',0,`%ecx',1,`%edx',2,`%ebx',3,`%esp',4,`%ebp',5,`%esi',6,`%edi',7')dnl Usage: x86_opcode_tttn(cond)dnldnl Expand to the 4-bit "tttn" field value for the given x86 branchdnl condition (like `c', `ae', etc).define(x86_opcode_tttn,m4_assert_numargs(1)`x86_lookup(`$1',x86_opcode_ttn_list)')define(x86_opcode_tttn_list,``o', 0,`no', 1,`b', 2, `c', 2, `nae',2,`nb', 3, `nc', 3, `ae', 3,`e', 4, `z', 4,`ne', 5, `nz', 5,`be', 6, `na', 6,`nbe', 7, `a', 7,`s', 8,`ns', 9,`p', 10, `pe', 10, `npo',10,`np', 11, `npe',11, `po', 11,`l', 12, `nge',12,`nl', 13, `ge', 13,`le', 14, `ng', 14,`nle',15, `g', 15')dnl Usage: cmovCC(srcreg,dstreg)dnldnl Emit a cmov instruction, using a .byte sequence, since various pastdnl versions of gas don't know cmov. For example,dnldnl cmovz( %eax, %ebx)dnldnl The source operand can only be a plain register. (m4 code implementingdnl full memory addressing modes exists, believe it or not, but isn'tdnl currently needed and isn't included.)dnldnl All the standard conditions are defined. Attempting to use one withoutdnl the macro parentheses, such as just "cmovbe %eax, %ebx", will provokednl an error. This protects against writing something old gas wouldn'tdnl understand.dnl Called: define_cmov_many(cond,tttn,cond,tttn,...)define(define_cmov_many,`ifelse(m4_length(`$1'),0,,`define_cmov(`$1',`$2')define_cmov_many(shift(shift($@)))')')dnl Called: define_cmov(cond,tttn)dnl Emit basically define(cmov<cond>,`cmov_internal(<cond>,<ttn>,`$1',`$2')')define(define_cmov,m4_assert_numargs(2)`define(`cmov$1',m4_instruction_wrapper()m4_assert_numargs(2)`cmov_internal'(m4_doublequote($`'0),``$2'',dnlm4_doublequote($`'1),m4_doublequote($`'2)))')define_cmov_many(x86_opcode_tttn_list)dnl Called: cmov_internal(name,tttn,src,dst)define(cmov_internal,m4_assert_numargs(4)`.byte dnl15, dnleval(64+$2), dnleval(192+8*x86_opcode_reg32(`$4')+x86_opcode_reg32(`$3')) dnl C `$1 $3, $4'')dnl Usage: x86_opcode_regmmx(reg)dnldnl Validate the given mmx register, and return its number, 0 to 7.define(x86_opcode_regmmx,m4_assert_numargs(1)`x86_lookup(`$1',x86_opcode_regmmx_list)')define(x86_opcode_regmmx_list,``%mm0',0,`%mm1',1,`%mm2',2,`%mm3',3,`%mm4',4,`%mm5',5,`%mm6',6,`%mm7',7')dnl Usage: psadbw(src,dst)dnldnl Oldish versions of gas don't know psadbw, in particular gas 2.9.1 ondnl FreeBSD 3.3 and 3.4 doesn't, so instead emit .byte sequences. Fordnl example,dnldnl psadbw( %mm1, %mm2)dnldnl Only register->register forms are supported here, which suffices fordnl the current code.define(psadbw,m4_instruction_wrapper()m4_assert_numargs(2)`.byte 0x0f,0xf6,dnleval(192+x86_opcode_regmmx(`$2')*8+x86_opcode_regmmx(`$1')) dnl C `psadbw $1, $2'')dnl Usage: loop_or_decljnz labeldnldnl Generate either a "loop" instruction or a "decl %ecx / jnz", whicheverdnl is better. "loop" is better on K6 and probably on 386, on other chipsdnl separate decl/jnz is better.dnldnl This macro is just for mpn/x86/divrem_1.asm and mpn/x86/mod_1.asm wherednl this loop_or_decljnz variation is enough to let the code be shared bydnl all chips.define(loop_or_decljnz,m4_assert_numargs(-1)`ifelse(loop_is_better_p,1, `loop', `decl %ecx jnz')')define(loop_is_better_p,m4_assert_numargs(-1)`m4_ifdef_anyof_p(`HAVE_HOST_CPU_k6', `HAVE_HOST_CPU_k62', `HAVE_HOST_CPU_k63', `HAVE_HOST_CPU_i386')')dnl Usage: Zdisp(inst,op,op,op)dnldnl Generate explicit .byte sequences if necessary to force a byte-sizeddnl zero displacement on an instruction. For example,dnldnl Zdisp( movl, 0,(%esi), %eax)dnldnl expands todnldnl .byte 139,70,0 C movl 0(%esi), %eaxdnldnl If the displacement given isn't 0, then normal assembler code isdnl generated. For example,dnldnl Zdisp( movl, 4,(%esi), %eax)dnldnl expands todnldnl movl 4(%esi), %eaxdnldnl This means a single Zdisp() form can be used with an expression for thednl displacement, and .byte will be used only if necessary. Thednl displacement argument is eval()ed.dnldnl Because there aren't many places a 0(reg) form is wanted, Zdisp isdnl implemented with a table of instructions and encodings. A new entry isdnl needed for any different operation or registers. The table is splitdnl into separate macros to avoid overflowing BSD m4 macro expansion space.define(Zdisp,m4_assert_numargs(4)`define(`Zdisp_found',0)dnlZdisp_1($@)dnlZdisp_2($@)dnlZdisp_3($@)dnlZdisp_4($@)dnlifelse(Zdisp_found,0,`m4_error(`unrecognised instruction in Zdisp: $1 $2 $3 $4')')')define(Zdisp_1,`dnlZdisp_match( adcl, 0,(%edx), %eax, `0x13,0x42,0x00', $@)`'dnlZdisp_match( adcl, 0,(%edx), %ebx, `0x13,0x5a,0x00', $@)`'dnlZdisp_match( adcl, 0,(%edx), %esi, `0x13,0x72,0x00', $@)`'dnlZdisp_match( addl, %ebx, 0,(%edi), `0x01,0x5f,0x00', $@)`'dnlZdisp_match( addl, %ecx, 0,(%edi), `0x01,0x4f,0x00', $@)`'dnlZdisp_match( addl, %esi, 0,(%edi), `0x01,0x77,0x00', $@)`'dnlZdisp_match( sbbl, 0,(%edx), %eax, `0x1b,0x42,0x00', $@)`'dnlZdisp_match( sbbl, 0,(%edx), %esi, `0x1b,0x72,0x00', $@)`'dnlZdisp_match( subl, %ecx, 0,(%edi), `0x29,0x4f,0x00', $@)`'dnlZdisp_match( movzbl, 0,(%eax,%ebp), %eax, `0x0f,0xb6,0x44,0x28,0x00', $@)`'dnlZdisp_match( movzbl, 0,(%ecx,%edi), %edi, `0x0f,0xb6,0x7c,0x39,0x00', $@)`'dnl')define(Zdisp_2,`dnlZdisp_match( movl, %eax, 0,(%edi), `0x89,0x47,0x00', $@)`'dnlZdisp_match( movl, %ebx, 0,(%edi), `0x89,0x5f,0x00', $@)`'dnlZdisp_match( movl, %esi, 0,(%edi), `0x89,0x77,0x00', $@)`'dnlZdisp_match( movl, 0,(%ebx), %eax, `0x8b,0x43,0x00', $@)`'dnlZdisp_match( movl, 0,(%ebx), %esi, `0x8b,0x73,0x00', $@)`'dnlZdisp_match( movl, 0,(%edx), %eax, `0x8b,0x42,0x00', $@)`'dnlZdisp_match( movl, 0,(%esi), %eax, `0x8b,0x46,0x00', $@)`'dnlZdisp_match( movl, 0,(%esi,%ecx,4), %eax, `0x8b,0x44,0x8e,0x00', $@)`'dnl')define(Zdisp_3,`dnlZdisp_match( movq, 0,(%eax,%ecx,8), %mm0, `0x0f,0x6f,0x44,0xc8,0x00', $@)`'dnlZdisp_match( movq, 0,(%ebx,%eax,4), %mm0, `0x0f,0x6f,0x44,0x83,0x00', $@)`'dnlZdisp_match( movq, 0,(%ebx,%eax,4), %mm2, `0x0f,0x6f,0x54,0x83,0x00', $@)`'dnlZdisp_match( movq, 0,(%ebx,%ecx,4), %mm0, `0x0f,0x6f,0x44,0x8b,0x00', $@)`'dnlZdisp_match( movq, 0,(%edx), %mm0, `0x0f,0x6f,0x42,0x00', $@)`'dnlZdisp_match( movq, 0,(%esi), %mm0, `0x0f,0x6f,0x46,0x00', $@)`'dnlZdisp_match( movq, %mm0, 0,(%edi), `0x0f,0x7f,0x47,0x00', $@)`'dnlZdisp_match( movq, %mm2, 0,(%ecx,%eax,4), `0x0f,0x7f,0x54,0x81,0x00', $@)`'dnlZdisp_match( movq, %mm2, 0,(%edx,%eax,4), `0x0f,0x7f,0x54,0x82,0x00', $@)`'dnlZdisp_match( movq, %mm0, 0,(%edx,%ecx,8), `0x0f,0x7f,0x44,0xca,0x00', $@)`'dnl')define(Zdisp_4,`dnlZdisp_match( movd, 0,(%eax,%ecx,4), %mm0, `0x0f,0x6e,0x44,0x88,0x00', $@)`'dnlZdisp_match( movd, 0,(%eax,%ecx,8), %mm1, `0x0f,0x6e,0x4c,0xc8,0x00', $@)`'dnlZdisp_match( movd, 0,(%edx,%ecx,8), %mm0, `0x0f,0x6e,0x44,0xca,0x00', $@)`'dnlZdisp_match( movd, %mm0, 0,(%eax,%ecx,4), `0x0f,0x7e,0x44,0x88,0x00', $@)`'dnlZdisp_match( movd, %mm0, 0,(%ecx,%eax,4), `0x0f,0x7e,0x44,0x81,0x00', $@)`'dnlZdisp_match( movd, %mm2, 0,(%ecx,%eax,4), `0x0f,0x7e,0x54,0x81,0x00', $@)`'dnlZdisp_match( movd, %mm0, 0,(%edx,%ecx,4), `0x0f,0x7e,0x44,0x8a,0x00', $@)`'dnl')define(Zdisp_match,m4_assert_numargs(9)`ifelse(eval(m4_stringequal_p(`$1',`$6') && m4_stringequal_p(`$2',0) && m4_stringequal_p(`$3',`$8') && m4_stringequal_p(`$4',`$9')),1,`define(`Zdisp_found',1)dnlifelse(eval(`$7'),0,` .byte $5 C `$1 0$3, $4'',` $6 $7$8, $9')',`ifelse(eval(m4_stringequal_p(`$1',`$6') && m4_stringequal_p(`$2',`$7') && m4_stringequal_p(`$3',0) && m4_stringequal_p(`$4',`$9')),1,`define(`Zdisp_found',1)dnlifelse(eval(`$8'),0,` .byte $5 C `$1 $2, 0$4'',` $6 $7, $8$9')')')')dnl Usage: shldl(count,src,dst)dnl shrdl(count,src,dst)dnl shldw(count,src,dst)dnl shrdw(count,src,dst)dnldnl Generate a double-shift instruction, possibly omitting a %cl countdnl parameter if that's what the assembler requires, as indicated bydnl WANT_SHLDL_CL in config.m4. For example,dnldnl shldl( %cl, %eax, %ebx)dnldnl turns into eitherdnldnl shldl %cl, %eax, %ebxdnl ordnl shldl %eax, %ebxdnldnl Immediate counts are always passed through unchanged. For example,dnldnl shrdl( $2, %esi, %edi)dnl becomesdnl shrdl $2, %esi, %edidnldnldnl If you forget to use the macro form "shldl( ...)" and instead writednl just a plain "shldl ...", an error results. This ensures the necessarydnl variant treatment of %cl isn't accidentally bypassed.define(define_shd_instruction,m4_assert_numargs(1)`define($1,m4_instruction_wrapper()m4_assert_numargs(3)`shd_instruction'(m4_doublequote($`'0),m4_doublequote($`'1),dnlm4_doublequote($`'2),m4_doublequote($`'3)))')dnl Effectively: define(shldl,`shd_instruction(`$0',`$1',`$2',`$3')') etcdefine_shd_instruction(shldl)define_shd_instruction(shrdl)define_shd_instruction(shldw)define_shd_instruction(shrdw)dnl Called: shd_instruction(op,count,src,dst)define(shd_instruction,m4_assert_numargs(4)m4_assert_defined(`WANT_SHLDL_CL')`ifelse(eval(m4_stringequal_p(`$2',`%cl') && !WANT_SHLDL_CL),1,``$1' `$3', `$4'',``$1' `$2', `$3', `$4'')')dnl Usage: ASSERT([cond][,instructions])dnldnl If WANT_ASSERT is 1, output the given instructions and expect the givendnl flags condition to then be satisfied. For example,dnldnl ASSERT(ne, `cmpl %eax, %ebx')dnldnl The instructions can be omitted to just assert a flags condition withdnl no extra calculation. For example,dnldnl ASSERT(nc)dnldnl When `instructions' is not empty, a pushf/popf is added to preserve thednl flags, but the instructions themselves must preserve any registers thatdnl matter. FRAME is adjusted for the push and pop, so the instructionsdnl given can use defframe() stack variables.dnldnl The condition can be omitted to just output the given instructions whendnl assertion checking is wanted. In this case the pushf/popf is omitted.dnl For example,dnldnl ASSERT(, `movl %eax, VAR_KEEPVAL')define(ASSERT,m4_assert_numargs_range(1,2)`ifelse(WANT_ASSERT,1,`ifelse(`$1',, `$2', `C ASSERTifelse(`$2',,,` pushf ifdef(`FRAME',`FRAME_pushl()')') $2 j`$1' L(ASSERT_ok`'ASSERT_counter) ud2 C assertion failedL(ASSERT_ok`'ASSERT_counter):ifelse(`$2',,,` popf ifdef(`FRAME',`FRAME_popl()')')define(`ASSERT_counter',incr(ASSERT_counter))')')')define(ASSERT_counter,1)dnl Usage: movl_text_address(label,register)dnldnl Get the address of a text segment label, using either a plain movl or adnl position-independent calculation, as necessary. For example,dnldnl movl_code_address(L(foo),%eax)dnldnl This macro is only meant for use in ASSERT()s or when testing, sincednl the PIC sequence it generates will want to be done with a ret balancingdnl the call on CPUs with return address branch predition.dnldnl The addl generated here has a backward reference to the label, and sodnl won't suffer from the two forwards references bug in old gas (describeddnl in mpn/x86/README).define(movl_text_address,m4_assert_numargs(2)`ifdef(`PIC', `call L(movl_text_address_`'movl_text_address_counter)L(movl_text_address_`'movl_text_address_counter): popl $2 C %eip addl `$'$1-L(movl_text_address_`'movl_text_address_counter), $2define(`movl_text_address_counter',incr(movl_text_address_counter))', `movl `$'$1, $2')')define(movl_text_address_counter,1)dnl Usage: notl_or_xorl_GMP_NUMB_MASK(reg)dnldnl Expand to either "notl `reg'" or "xorl $GMP_NUMB_BITS,`reg'" asdnl appropriate for nails in use or not.define(notl_or_xorl_GMP_NUMB_MASK,m4_assert_numargs(1)`ifelse(GMP_NAIL_BITS,0,`notl `$1'',`xorl $GMP_NUMB_MASK, `$1'')')divert`'dnl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -