diff options
| author | Drahflow <drahflow@gmx.de> | 2013-12-31 00:55:54 +0100 |
|---|---|---|
| committer | Drahflow <drahflow@gmx.de> | 2013-12-31 00:55:54 +0100 |
| commit | c78a4ce84fd37064b8db7e5fc7a9b3fb23631179 (patch) | |
| tree | 49ee2a5b691ea56ace2d8df9efd5530600f19a61 /compiler/elymasAsmOps.ey | |
| parent | 643d6dca1e6026ebf8cfa551ae3e95cc69003c47 (diff) | |
Externalized actual assembly opcodes
Diffstat (limited to 'compiler/elymasAsmOps.ey')
| -rw-r--r-- | compiler/elymasAsmOps.ey | 1252 |
1 files changed, 1252 insertions, 0 deletions
diff --git a/compiler/elymasAsmOps.ey b/compiler/elymasAsmOps.ey new file mode 100644 index 0000000..0d24dd5 --- /dev/null +++ b/compiler/elymasAsmOps.ey @@ -0,0 +1,1252 @@ +# this file is included both by the bootstrapping compiler and by the later optimization library + +# registers +< [ /rax /rcx /rdx /rbx /rsp /rbp /rsi /rdi /r8 /r9 /r10 /r11 /r12 /r13 /r14 /r15 ] { 1 -01 defv }' each > ==:bit64table +{ bit64table -01 . -- } /bit64assert deff + +< [ /eax /ecx /edx /ebx /esp /ebp /esi /edi /r8d /r9d /r10d /r11d /r12d /r13d /r14d /r15d ] { 1 -01 defv }' each > ==:bit32table +{ bit32table -01 . -- } /bit32assert deff + +< [ /ax /cx /dx /bx /sp /bp /si /di /r8w /r9w /r10w /r11w /r12w /r13w /r14w /r15w ] { 1 -01 defv }' each > ==:bit16table +{ bit16table -01 . -- } /bit16assert deff + +< [ /al /cl /dl /bl /spl /ah /bpl /ch /sil /dh /dil /bh /r8b /r9b /r10b /r11b /r12b /r13b /r14b /r15b ] { 1 -01 defv }' each > ==:bit8table +{ bit8table -01 . -- } /bit8assert deff + +< + [ /zero /al /ax /eax /rax /none ] { 0 -01 defv }' each + [ /one /cl /cx /ecx /rcx ] { 1 -01 defv }' each + [ /two /dl /dx /edx /rdx ] { 2 -01 defv }' each + [ /three /bl /bx /ebx /rbx ] { 3 -01 defv }' each + [ /four /sib /spl /ah /sp /esp /rsp ] { 4 -01 defv }' each + [ /five /bpl /bp /ebp /rbp ] { 5 -01 defv }' each + [ /six /sil /si /esi /rsi ] { 6 -01 defv }' each + [ /seven /dil /di /edi /rdi ] { 7 -01 defv }' each + [ /r8b /r8w /r8d /r8 ] { 8 -01 defv }' each + [ /r9b /r9w /r9d /r9 ] { 9 -01 defv }' each + [ /r10b /r10w /r10d /r10 ] { 10 -01 defv }' each + [ /r11b /r11w /r11d /r11 ] { 11 -01 defv }' each + [ /r12b /r12w /r12d /r12 ] { 12 -01 defv }' each + [ /r13b /r13w /r13d /r13 ] { 13 -01 defv }' each + [ /r14b /r14w /r14d /r14 ] { 14 -01 defv }' each + [ /r15b /r15w /r15d /r15 ] { 15 -01 defv }' each +> ==:regnoTable + +{ regnoTable -01 . } /regno deff + +< + [ /al /cl /dl /bl ] { 0 -01 defv }' each + [ /spl /bpl /sil /dil ] { 1 -01 defv }' each + [ /r8b /r9b /r10b /r11b /r12b /r13b /r14b /r15b ] { 1 -01 defv }' each +> ==:rexreqbyteTable + +{ rexreqbyteTable -01 . } /rexreqbyte deff + +# encoding a REX prefix +{ # ==b ==x ==r ==w + %40 + -01 regno %08 band 0 gt %01 mul add + -01 regno %08 band 0 gt %02 mul add + -01 regno %08 band 0 gt %04 mul add + -01 0 gt %08 mul add +} /rex deff + +{ ==mem ==reg + mem [ /spl /sp /esp /rsp /bpl /bp /ebp /rbp ] streq any { + "modrm00 not possible on rsp / rbp and their partial registers" die + } rep + + %00 + mem regno %07 band add + reg regno 8 mul %38 band add +} /modrm00 deff + +{ ==mem ==reg + mem [ /spl /sp /esp /rsp ] streq any { + # actually encode sib with rsp index register (to get it ignored) + %40 + /sib regno %07 band add + reg regno 8 mul %38 band add + + # sib-byte + %00 # index = 1 (ignored anyway) + %38 /rsp regno 8 mul band add # (ignored) + %07 mem regno band add + } { + %40 + mem regno %07 band add + reg regno 8 mul %38 band add + } ? * +} /modrm01 deff + +{ ==mem ==reg + mem [ /spl /sp /esp /rsp ] streq any { + # actually encode sib with rsp index register (to get it ignored) + %80 + /sib regno %07 band add + reg regno 8 mul %38 band add + + # sib-byte + %00 # index = 1 (ignored anyway) + %38 /rsp regno 8 mul band add # (ignored) + %07 mem regno band add + } { + %80 + mem regno %07 band add + reg regno 8 mul %38 band add + } ? * +} /modrm10 deff + +{ ==mem ==reg + %C0 + mem regno %07 band add + reg regno 8 mul %38 band add +} /modrm11 deff + +{ ==base ==idx ==scale + idx [ /spl /sp /esp /rsp ] streq any { "sib cannot encode rsp as index" die } rep + base [ /bpl /bp /ebp /rbp ] streq any { "sib cannot encode rbp as base" die } rep + scale _ 0 gt not { "invalid scale chosen for sib" die } rep + 8 le not { "invalid scale chosen for sib" die } rep + + scale [ 1 %00 %40 1 %80 1 1 1 %C0 ] * + _ 1 eq { "invalid scale chosen for sib" die } rep + %C0 band + %38 idx regno 8 mul band add + %07 base regno band add +} /sib deff + +{ 8 { _ 256 mod -01 256 div } rep -- } /imm64 deff # div / mod unsigned +{ _ 0 lt { 4294967296 add } rep 4294967295 band 4 { _ 256 mod -01 256 div } rep -- } /imm32 deff +{ _ 0 lt { 65536 add } rep 65535 band 2 { _ 256 mod -01 256 div } rep -- } /imm16 deff +{ _ 0 lt { 256 add } rep 255 band } /imm8 deff + +{ %66 } /width16 deff + +# label handling +< { defv }' /put deff > ==labels +[ ] ==labelHoles + +{ ==l + ] _ len l labels .put [ -011 len dearray +} /label deff + +{ ==l + ] _ len ==offset + labelHoles [ { + labels l . offset 1 add sub + _ 128 lt not { "8 bit relative label out of range: " l cat die } rep + _ 128 neg ge not { "8 bit relative label out of range: " l cat die } rep + imm8 offset -102 =[] } ] cat =labelHoles + [ -011 len dearray %00 +} /labelRel8 deff + +{ ==l + ] _ len ==offset + labelHoles [ { + labels l . offset 2 add sub + _ 32768 lt not { "16 bit relative label out of range: " l cat die } rep + _ 32768 neg ge not { "16 bit relative label out of range: " l cat die } rep + imm16 offset [ 0 1 ] add 2 dearray -204314 =[] =[] } ] cat =labelHoles + [ -011 len dearray %00 %00 +} /labelRel16 deff + +{ ==l + ] _ len ==offset + labelHoles [ { + labels l . offset 4 add sub + _ 2147483648 lt not { "32 bit relative label out of range: " l cat die } rep + _ 2147483648 neg ge not { "32 bit relative label out of range" l cat die } rep + imm32 offset [ 0 1 2 3 ] add 4 dearray -408518628738 =[] =[] =[] =[] } ] cat =labelHoles + [ -011 len dearray %00 %00 %00 %00 +} /labelRel32 deff + +{ ==opcodes + labelHoles { opcodes -01 * } each + + < { defv }' /put deff > =labels + [ ] =labelHoles + + opcodes +} /labelResolve deff + +{ < ==opcode ==name + { ==offset + offset 128 neg ge not { "Rel8 offset below -128" die } rep + offset 128 lt not { "Rel8 offset above 127" die } rep + + opcode + offset imm8 + } name "Rel8" cat + + { ==lbl + + opcode + lbl labelRel8 + } name "Lbl8" cat + > -- 2 |deff rep +}' /defJmpRel8 deff + +{ "opcode only exists on AMD cpus (and has 'interesting' semantics even there)" die } /defJmpRel16 deff + +{ < ==opcode ==name + { ==offset + offset 2147483648 neg ge not { "Rel32 offset below -2147483648" die } rep + offset 2147483648 lt not { "Rel32 offset above 2147483647" die } rep + + %0F + opcode + offset imm32 + } name "Rel32" cat + + { ==lbl + + %0F + opcode + lbl labelRel32 + } name "Lbl32" cat + > -- 2 |deff rep +}' /defJmpRel32 deff + +# generalized arithmethic 8086 instructions +# { cat _ { "executing " -01 cat dump }_ -102 ; -01 deff }' /defOp deff # debugging version +{ cat deff }' /defOp deff +< + # base register only + { < _ bit64assert ==base /none ==idx { ==r + r base modrm00 + } /encode deff > + } ==Mem + # base register plus 8 bit displacement + { < _ bit64assert ==base /none ==idx _ 128 lt not { "Disp8 too large" die } rep ==disp { ==r + r base modrm01 + disp imm8 + } /encode deff > + } ==MemDisp8 + # base register plus 32 bit displacement + { < _ bit64assert ==base /none ==idx ==disp { ==r + r base modrm10 + disp imm32 + } /encode deff > + } ==MemDisp32 + # base and index register + { < _ bit64assert ==base _ bit64assert ==idx { ==r + r /sib modrm00 + 1 idx base sib + } /encode deff > + } ==MemIndex + # base and scaled index register + { < _ bit64assert ==base _ bit64assert ==idx ==scale { ==r + r /sib modrm00 + scale idx base sib + } /encode deff > + } ==MemIndexScale + # base and scaled index register plus 8 bit displacement + { < _ bit64assert ==base _ bit64assert ==idx ==scale _ 128 lt not { "Disp8 too large" die } rep ==disp { ==r + r /sib modrm01 + scale idx base sib + disp imm8 + } /encode deff > + } ==MemIndexScaleDisp8 + # base and scaled index register plus 8 bit displacement + { < _ bit64assert ==base _ bit64assert ==idx ==scale ==disp { ==r + r /sib modrm10 + scale idx base sib + disp imm32 + } /encode deff > + } ==MemIndexScaleDisp32 +> ==memoryAddressingVariants + +{ ==opcode ==mnemonic + { ==dst ==src + src bit8assert + dst bit8assert + + src regno %07 gt dst regno %07 gt src rexreqbyte dst rexreqbyte or or or { 0 src /none dst rex } rep + opcode + src dst modrm11 + } mnemonic /bRegReg defOp + + memoryAddressingVariants keys { ==variant memoryAddressingVariants variant . =*parse + { parse ==mem ==reg + reg bit8assert + + reg regno %07 gt reg rexreqbyte mem .base regno %07 gt mem .idx regno %07 gt or or or + { 0 reg mem .idx mem .base rex } rep + opcode + reg mem .encode + } mnemonic /bReg variant cat defOp + + { ==reg parse ==mem + reg bit8assert + + reg regno %07 gt reg rexreqbyte mem .base regno %07 gt mem .idx regno %07 gt or or or + { 0 reg mem .idx mem .base rex } rep + opcode %02 add + reg mem .encode + } mnemonic /b variant cat /Reg cat defOp + } each +} /defAsmAddb deff + +{ ==opcode ==mnemonic + { ==dst ==src + dst bit32assert + src bit32assert + + dst regno %07 gt src regno %07 gt or + { 0 src /none dst rex } rep + opcode + src dst modrm11 + } mnemonic /lRegReg defOp + + memoryAddressingVariants keys { ==variant memoryAddressingVariants variant . =*parse + { parse ==mem ==reg + reg bit32assert + + reg regno %07 gt mem .base regno %07 gt mem .idx regno %07 gt or or + { 0 reg mem .idx mem .base rex } rep + opcode + reg mem .encode + } mnemonic /lReg variant cat defOp + + { ==reg parse ==mem + reg bit32assert + + reg regno %07 gt mem .base regno %07 gt mem .idx regno %07 gt or or + { 0 reg mem .idx mem .base rex } rep + opcode %02 add + reg mem .encode + } mnemonic /l variant cat /Reg cat defOp + } each +} /defAsmAddl deff + +{ ==opcode ==mnemonic + { ==dst ==src + dst bit64assert + src bit64assert + + 1 src /none dst rex + opcode + src dst modrm11 + } mnemonic /qRegReg defOp + + memoryAddressingVariants keys { ==variant memoryAddressingVariants variant . =*parse + { parse ==mem ==reg + reg bit64assert + + 1 reg mem .idx mem .base rex + opcode + reg mem .encode + } mnemonic /qReg variant cat defOp + + { ==reg parse ==mem + reg bit64assert + + 1 reg mem .idx mem .base rex + opcode %02 add + reg mem .encode + } mnemonic /q variant cat /Reg cat defOp + } each +} /defAsmAddq deff + +{ ==modrmOpcode ==mnemonic + { ==reg =i + reg bit8assert + i 256 lt not { "Imm8 too large" die } rep + + reg regno %07 gt reg rexreqbyte or { 0 /none /none reg rex } rep + %80 + modrmOpcode reg modrm11 + i imm8 + } mnemonic /bImmReg defOp + + { ==reg ==i + reg bit64assert + i 256 lt not { "Imm8 too large" die } rep + + 1 /none /none reg rex + %83 + modrmOpcode reg modrm11 + i imm8 + } mnemonic /qImm8Reg defOp + + memoryAddressingVariants keys { ==variant memoryAddressingVariants variant . =*parse + { parse ==mem ==i + i 256 lt not { "Imm8 too large" die } rep + + mem .base regno %07 gt mem .idx regno %07 gt or + { 0 /none mem .idx mem .base rex } rep + %80 + modrmOpcode mem .encode + i imm8 + } mnemonic /bImm variant cat defOp + + { parse ==mem ==i + i 65536 lt not { "Imm16 too large" die } rep + + width16 + mem .base regno %07 gt mem .idx regno %07 gt or + { 0 /none mem .idx mem .base rex } rep + %81 + modrmOpcode mem .encode + i imm16 + } mnemonic /wImm variant cat defOp + + { parse ==mem ==i + i 256 lt not { "Imm8 too large" die } rep + + 1 /none mem .idx mem .base rex + %83 + modrmOpcode mem .encode + i imm8 + } mnemonic /qImm8 variant cat defOp + } each +} /defAsmAddImm deff + +# instructions +{ ==reg ==mem + reg bit32assert + mem bit64assert + + reg regno %07 gt mem regno %07 gt or { 0 reg /none mem rex } rep + %03 + reg mem modrm00 +} /addlMemReg deff + +{ ==opcode2 ==opcode1 ==mnemonic + { ==reg2 ==reg1 + reg2 bit64assert + reg1 bit64assert + + 1 reg1 /none reg2 rex + opcode1 + opcode2 + reg1 reg2 modrm11 + } mnemonic /qRegReg defOp + + memoryAddressingVariants keys { ==variant memoryAddressingVariants variant . =*parse + { parse ==mem ==reg + reg bit64assert + + 1 reg mem .idx mem .base rex + opcode1 + opcode2 + reg mem .encode + } mnemonic /qReg variant cat defOp + } each +} /defAsmBtq deff + +{ ==opcode2 ==opcode1 ==mnemonic + { ==reg1 ==reg2 + reg2 bit64assert + reg1 bit64assert + + 1 reg1 /none reg2 rex + opcode1 + opcode2 + reg1 reg2 modrm11 + } mnemonic /qRegReg defOp + + memoryAddressingVariants keys { ==variant memoryAddressingVariants variant . =*parse + { ==reg parse ==mem + reg bit64assert + + 1 reg mem .idx mem .base rex + opcode1 + opcode2 + reg mem .encode + } mnemonic /qReg variant cat defOp + } each +} /defAsmBsfq deff + +{ ==modrmOpcode ==opcode2 ==opcode1 ==mnemonic + { ==reg ==i + reg bit64assert + + 1 /none /none reg rex + opcode1 + opcode2 + modrmOpcode reg modrm11 + i imm8 + } mnemonic /qImm8Reg defOp + + memoryAddressingVariants keys { ==variant memoryAddressingVariants variant . =*parse + { parse ==mem ==imm + 1 /none mem .idx mem .base rex + opcode1 + opcode2 + modrmOpcode mem .encode + imm imm8 + } mnemonic /qImm8 variant cat defOp + } each +} /defAsmBtqImm deff + +/adc %11 defAsmAddq +/adc /two defAsmAddImm + +/add %01 defAsmAddq +/add /zero defAsmAddImm + +/and %20 defAsmAddb +/and %21 defAsmAddq +/and /four defAsmAddImm + +/bt %0F %A3 defAsmBtq +/bt %0F %BA /four defAsmBtqImm + +/btr %0F %B3 defAsmBtq +/btr %0F %BA /six defAsmBtqImm + +/bts %0F %AB defAsmBtq +/bts %0F %BA /five defAsmBtqImm + +/bsf %0F %BC defAsmBsfq + +{ ==off + %E8 + off imm32 +} /callqRel32 deff + +{ ==lbl + %E8 + lbl labelRel32 +} /callqLbl32 deff + +{ ==reg + reg bit64assert + + reg regno %07 gt { 1 /none /none reg rex } rep + %FF + /two reg modrm11 +} /callqReg deff + +memoryAddressingVariants keys { ==variant memoryAddressingVariants variant . =*parse + { parse ==mem + mem .base regno %07 gt mem .idx regno %07 gt or + { 0 /none mem .idx mem .base rex } rep + %FF + /two mem .encode + } /callq variant defOp +} each + +{ + %FC +} /cld deff + +{ ==dst ==src + src bit64assert + dst bit64assert + + 1 dst /none src rex + %0F + %47 + dst src modrm11 +} /cmovaqRegReg deff + +{ ==dst ==src + src bit64assert + dst bit64assert + + 1 dst /none src rex + %0F + %46 + dst src modrm11 +} /cmovnaqRegReg deff + +{ ==dst ==src + src bit64assert + dst bit64assert + + 1 dst /none src rex + %0F + %43 + dst src modrm11 +} /cmovaeqRegReg deff + +{ ==dst ==src + src bit64assert + dst bit64assert + + 1 dst /none src rex + %0F + %42 + dst src modrm11 +} /cmovnaeqRegReg deff + +{ ==dst ==src + src bit64assert + dst bit64assert + + 1 dst /none src rex + %0F + %42 + dst src modrm11 +} /cmovcqRegReg deff + +{ ==dst ==src + src bit64assert + dst bit64assert + + 1 dst /none src rex + %0F + %4F + dst src modrm11 +} /cmovgqRegReg deff + +{ ==reg ==mem + mem bit64assert + reg bit64assert + + 1 reg /none mem rex + %0F + %43 + reg mem modrm00 +} /cmovncqMemReg deff + +{ ==reg ==mem ==disp + disp 128 lt not { "Disp8 out of range" die } rep + mem bit64assert + reg bit64assert + + 1 reg /none mem rex + %0F + %43 + reg mem modrm01 + disp imm8 +} /cmovncqMemDisp8Reg deff + +{ ==dst ==src + src bit64assert + dst bit64assert + + 1 dst /none src rex + %0F + %4E + dst src modrm11 +} /cmovngqRegReg deff + +{ ==dst ==src + src bit64assert + dst bit64assert + + 1 dst /none src rex + %0F + %4D + dst src modrm11 +} /cmovgeqRegReg deff + +{ ==dst ==src + src bit64assert + dst bit64assert + + 1 dst /none src rex + %0F + %4C + dst src modrm11 +} /cmovngeqRegReg deff + +{ ==dst ==src + src bit64assert + dst bit64assert + + 1 dst /none src rex + %0F + %45 + dst src modrm11 +} /cmovnzqRegReg deff + +{ ==dst ==src + src bit64assert + dst bit64assert + + 1 dst /none src rex + %0F + %44 + dst src modrm11 +} /cmovzqRegReg deff + +{ + %A6 +} /cmpsb deff + +{ + 1 /none /none /none rex + %A7 +} /cmpsq deff + +{ ==mem ==reg + reg bit32assert + mem bit64assert + + reg regno %07 gt mem regno %07 gt or { 0 reg /none mem rex } rep + %39 + reg mem modrm00 +} /cmplRegMem deff + +/cmp %38 defAsmAddb +/cmp %39 defAsmAddq +/cmp /seven defAsmAddImm + +{ ==mem + mem bit64assert + + 1 /none /none mem rex + %FF + /one mem modrm00 +} /decqMem deff + +{ ==reg + reg bit64assert + + 1 /none /none reg rex + %FF + /one reg modrm11 +} /decqReg deff + +{ ==reg + reg bit64assert + + 1 /none /none reg rex + %F7 + /six reg modrm11 +} /divqReg deff + +{ ==reg + reg bit8assert + + 1 /none /none reg rex + %FE + /zero reg modrm11 +} /incbReg deff + +{ ==mem + mem bit64assert + + 1 /none /none mem rex + %FF + /zero mem modrm00 +} /incqMem deff + +{ ==reg + reg bit64assert + + 1 /none /none reg rex + %FF + /zero reg modrm11 +} /incqReg deff + +/loop %E2 defJmpRel8 + +/jmp %EB defJmpRel8 + +{ ==lbl + "opcode only exists on AMD cpus (and has 'interesting' semantics even there)" die + width16 + %E9 + lbl labelRel16 +} /jmpLbl16 deff + +{ ==lbl + %E9 + lbl labelRel32 +} /jmpLbl32 deff + +/ja _ %77 defJmpRel8 %87 defJmpRel32 +/jae _ %73 defJmpRel8 %83 defJmpRel32 +/jb _ %72 defJmpRel8 %82 defJmpRel32 +/jc _ %72 defJmpRel8 %82 defJmpRel32 +/jbe _ %76 defJmpRel8 %86 defJmpRel32 +/je _ %74 defJmpRel8 %84 defJmpRel32 +/jg _ %7F defJmpRel8 %8F defJmpRel32 +/jge _ %7D defJmpRel8 %8D defJmpRel32 +/jl _ %7C defJmpRel8 %8C defJmpRel32 +/jle _ %7E defJmpRel8 %8E defJmpRel32 +/jnb _ %73 defJmpRel8 %83 defJmpRel32 +/jnc _ %73 defJmpRel8 %83 defJmpRel32 +/jne _ %75 defJmpRel8 %85 defJmpRel32 +/jng _ %7E defJmpRel8 %8E defJmpRel32 +/jnl _ %7D defJmpRel8 %8D defJmpRel32 +/jnge _ %7C defJmpRel8 %8C defJmpRel32 +/jnle _ %7F defJmpRel8 %8F defJmpRel32 +/jns _ %79 defJmpRel8 %89 defJmpRel32 +/jno _ %71 defJmpRel8 %81 defJmpRel32 +/jnz _ %75 defJmpRel8 %85 defJmpRel32 +/js _ %78 defJmpRel8 %88 defJmpRel32 +/jo _ %70 defJmpRel8 %80 defJmpRel32 +/jz _ %74 defJmpRel8 %84 defJmpRel32 + +{ ==reg + reg bit64assert + + reg regno %07 gt { 1 /none /none reg rex } rep + %FF + /four reg modrm11 +} /jmpqReg deff + +memoryAddressingVariants keys { ==variant memoryAddressingVariants variant . =*parse + { parse ==mem + mem .base regno %07 gt mem .idx regno %07 gt or + { 0 /none mem .idx mem .base rex } rep + %FF + /four mem .encode + } /jmpq variant defOp +} each + +{ ==reg ==mem ==idx ==scale ==disp + reg bit32assert + mem bit64assert + idx bit64assert + disp 128 lt not { "Disp8 out of range" die } rep + + reg regno %07 gt mem regno %07 gt idx regno %07 gt or or { 0 reg idx mem rex } rep + %8D + reg /sib modrm01 + scale idx mem sib + disp imm8 +} /lealMemIndexScaleDisp8Reg deff + +memoryAddressingVariants keys { ==variant memoryAddressingVariants variant . =*parse + { ==reg parse ==mem + reg bit64assert + + 1 reg mem .idx mem .base rex + %8D + reg mem .encode + } /leaq variant /Reg cat defOp +} each + +{ ==mem ==i + mem bit64assert + i 256 lt not { "Imm8 too large" die } rep + + mem regno %07 gt { 0 /none /none mem rex } rep + %C6 + /zero mem modrm00 + i imm8 +} /movbImmMem deff + +{ ==mem ==disp ==i + mem bit64assert + disp 128 lt not { "Disp8 out of range" die } rep + i 256 lt not { "Imm8 too large" die } rep + + mem regno %07 gt { 0 /none /none mem rex } rep + %C6 + /zero mem modrm01 + disp imm8 + i imm8 +} /movbImmMemDisp8 deff + +{ ==mem ==i + mem bit64assert + i 65536 lt not { "Imm16 too large" die } rep + + width16 + mem regno %07 gt { 0 /none /none mem rex } rep + %C7 + /zero mem modrm00 + i imm16 +} /movwImmMem deff + +{ ==mem ==i + mem bit64assert + i 65536 65536 mul lt not { "Imm32 too large" die } rep + + mem regno %07 gt { 0 /none /none mem rex } rep + %C7 + /zero mem modrm00 + i imm32 +} /movlImmMem deff + +{ ==mem ==disp ==i + mem bit64assert + disp 128 lt not { "Disp8 out of range" die } rep + i 65536 65536 mul lt not { "Imm32 too large" die } rep + + mem regno %07 gt { 0 /none /none mem rex } rep + %C7 + /zero mem modrm01 + disp imm8 + i imm32 +} /movlImmMemDisp8 deff + +{ ==reg ==i + reg bit64assert + + 1 /none /none reg rex + %B8 reg regno %07 band add + i imm64 +} /movqImmReg deff + +{ ==mem ==disp ==i + mem bit64assert + i 2147483648 lt not { "Imm32 too small" die } rep + i 2147483648 neg ge not { "Imm32 too large" die } rep + + 1 /none /none mem rex + %C7 + /zero mem modrm01 + disp imm8 + i imm32 +} /movqImm32MemDisp8 deff + +{ ==reg + reg bit64assert + + 1 /none /none reg rex + %B8 reg regno %07 band add +} /movqImmOOBReg deff + +/mov %88 defAsmAddb +/mov %89 defAsmAddl +/mov %89 defAsmAddq + +{ + %A4 +} /movsb deff + +{ + width16 + %A5 +} /movsw deff + +{ + %A5 +} /movsl deff + +{ + 1 /none /none /none rex + %A5 +} /movsq deff + +{ ==dst ==src + dst bit64assert + src bit8assert + + 1 dst /none src rex + %0F + %BE + dst src modrm11 +} /movsxbqRegReg deff + +{ ==dst ==src + dst bit64assert + src bit16assert + + 1 dst /none src rex + %0F + %BF + dst src modrm11 +} /movsxwqRegReg deff + +{ ==dst ==src + dst bit64assert + src bit32assert + + 1 dst /none src rex + %63 + dst src modrm11 +} /movsxlqRegReg deff + +{ ==dst ==src + dst bit64assert + src bit8assert + + 1 dst /none src rex + %0F + %B6 + dst src modrm11 +} /movzxbqRegReg deff + +{ ==dst ==src + dst bit64assert + src bit16assert + + 1 dst /none src rex + %0F + %B7 + dst src modrm11 +} /movzxwqRegReg deff + +{ ==reg ==mem + reg bit64assert + mem bit64assert + + 1 reg /none mem rex + %0F + %B6 + reg mem modrm00 +} /movzxMem8Reg64 deff # TODO: this is a weird name, should be movzxbqMemReg + +{ ==reg ==mem ==disp + reg bit64assert + mem bit64assert + disp 128 lt not { "Disp8 out of range" die } rep + + 1 reg /none mem rex + %0F + %B6 + reg mem modrm01 + disp imm8 +} /movzxMem8Disp8Reg64 deff # TODO: this is a weird name, should be movzxbqMemDisp8Reg + +{ ==reg ==mem ==idx ==scale ==disp + reg bit64assert + mem bit64assert + idx bit64assert + disp 128 lt not { "Disp8 out of range" die } rep + + 1 reg idx mem rex + %0F + %B6 + reg /sib modrm01 + scale idx mem sib + disp imm8 +} /movzxMem8IndexScaleDisp8Reg64 deff # TODO: this is a weird name, should be movzxbqMemIndexScaleDisp8Reg + +{ ==reg + reg bit64assert + + 1 /none /none reg rex + %F7 + /four reg modrm11 +} /mulqReg deff + +{ ==reg + reg bit64assert + + 1 /none /none reg rex + %F7 + /three reg modrm11 +} /negqReg deff + +{ + %90 +} /nop deff + +{ ==reg + reg bit64assert + + 1 /none /none reg rex + %F7 + /two reg modrm11 +} /notqReg deff + +/or %08 defAsmAddb +/or %09 defAsmAddq +/or /one defAsmAddImm + +{ ==reg + reg regno %07 gt { 1 /none /none reg rex } rep + %58 reg regno %07 band add +} /popqReg deff + +{ ==reg + reg regno %07 gt { 1 /none /none reg rex } rep + %50 reg regno %07 band add +} /pushqReg deff + +memoryAddressingVariants keys { ==variant memoryAddressingVariants variant . =*parse + { parse ==mem + mem .base regno %07 gt mem .idx regno %07 gt or { 1 /none mem .idx mem .base rex } rep + %8F + /zero mem .encode + } /popq variant defOp + + { parse ==mem + mem .base regno %07 gt mem .idx regno %07 gt or { 1 /none mem .idx mem .base rex } rep + %FF + /six mem .encode + } /pushq variant defOp +} each + +{ ==imm + %68 + imm imm32 +} /pushqImm32 deff + +{ + %F3 +} /reprcx deff + +{ + %F2 +} /repnz deff + +{ + %F3 +} /repz deff + +{ + %C3 +} /retn deff + +{ ==reg + reg bit8assert + + reg regno %07 gt reg rexreqbyte or { 0 reg /none /none rex } rep + %D2 + /zero reg modrm11 +} /rolbClReg deff + +{ ==reg + reg bit64assert + + 1 /none /none reg rex + %D3 + /zero reg modrm11 +} /rolqClReg deff + +{ + %AE +} /scasb deff + +{ + 1 /none /none /none rex + %AF +} /scasq deff + +{ ==reg + reg regno %07 gt reg rexreqbyte or { 0 reg /none /none rex } rep + %0F + %92 + /zero reg modrm11 +} /setcbReg deff + +{ ==reg + reg bit64assert + + 1 /none /none reg rex + %D3 + /four reg modrm11 +} /shlqClReg deff + +{ ==reg ==i + reg bit64assert + i 64 lt not { "Shift immediate too large" die } rep + + 1 /none /none reg rex + %C1 + /four reg modrm11 + i imm8 +} /shlqImm8Reg deff + +{ ==reg + reg bit64assert + + 1 /none /none reg rex + %D1 + /five reg modrm11 +} /shrq1Reg deff + +{ ==reg + reg bit64assert + + 1 /none /none reg rex + %D3 + /five reg modrm11 +} /shrqClReg deff + +{ ==reg ==i + reg bit64assert + i 64 lt not { "Shift immediate too large" die } rep + + 1 /none /none reg rex + %C1 + /five reg modrm11 + i imm8 +} /shrqImm8Reg deff + +{ + %AA +} /stosb deff + +{ + 1 /none /none /none rex + %AB +} /stosq deff + +{ ==reg ==mem + reg bit32assert + mem bit64assert + + reg regno %07 gt mem regno %07 gt or { 0 reg /none mem rex } rep + %2B + reg mem modrm00 +} /sublMemReg deff + +/sub %29 defAsmAddq +/sub /five defAsmAddImm + +{ + %0F %05 +} /syscall deff + +{ ==mem ==idx ==scale ==reg + reg bit8assert + mem bit64assert + idx bit64assert + + reg regno %07 gt reg rexreqbyte mem regno %07 gt idx regno %07 gt or or or { 0 reg idx mem rex } rep + %84 + reg /sib modrm00 + scale idx mem sib +} /testbRegMemIndexScale deff + +{ ==reg ==i + reg bit8assert + i 256 lt not { "Imm8 too large" die } rep + + reg regno %07 gt reg rexreqbyte or { 0 /none /none reg rex } rep + %F6 + /zero reg modrm11 + i imm8 +} /testbImmReg deff + +{ ==dst ==src + dst bit64assert + src bit64assert + + 1 src /none dst rex + %85 + src dst modrm11 +} /testqRegReg deff + +{ ==mem ==idx ==scale ==reg + reg bit64assert + mem bit64assert + idx bit64assert + + 1 reg idx mem rex + %85 + reg /sib modrm00 + scale idx mem sib +} /testqRegMemIndexScale deff + +{ + %0F + %0B +} /ud2 deff + +{ ==dst ==src + dst bit64assert + src bit64assert + + 1 src /none dst rex + %87 + src dst modrm11 +} /xchgqRegReg deff + +memoryAddressingVariants keys { ==variant memoryAddressingVariants variant . =*parse + { parse ==mem ==reg + reg bit64assert + + 1 reg mem .idx mem .base rex + %87 + reg mem .encode + } /xchgqReg variant defOp +} each + +/xor %31 defAsmAddq + +# vim: syn=elymas |
