aboutsummaryrefslogtreecommitdiff
path: root/compiler/elymasAsmOps.ey
diff options
context:
space:
mode:
authorDrahflow <drahflow@gmx.de>2013-12-31 00:55:54 +0100
committerDrahflow <drahflow@gmx.de>2013-12-31 00:55:54 +0100
commitc78a4ce84fd37064b8db7e5fc7a9b3fb23631179 (patch)
tree49ee2a5b691ea56ace2d8df9efd5530600f19a61 /compiler/elymasAsmOps.ey
parent643d6dca1e6026ebf8cfa551ae3e95cc69003c47 (diff)
Externalized actual assembly opcodes
Diffstat (limited to 'compiler/elymasAsmOps.ey')
-rw-r--r--compiler/elymasAsmOps.ey1252
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