< 4096 ==PAGESIZE 4096 16 mul 8 mul ==STACKSIZE 65536 ==GLOBALALLOCSSIZE 128 ==STACKSTART # hex decoding { "(.)(.)" regex { } { "not a valid hex-string" die } ? * { { streq }_ [ "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F" ] -01 index } -20*10* 16 mul add } "%" defq # 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 not assert %40 mem regno %07 band add reg regno 8 mul %38 band add } /modrm01 deff { =mem =reg mem [ /spl /sp /esp /rsp ] streq any not assert %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 not assert base [ /bpl /bp /ebp /rbp ] streq any not assert scale _ 0 gt assert 8 le assert scale [ 1 %00 %40 1 %80 1 1 1 %C0 ] * _ 1 neq assert %C0 band %38 idx regno 8 mul band add %07 base regno band add } /sib deff { _ 0 ge assert 8 { _ 256 mod -01 256 div } rep -- } /imm64 deff { _ 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 assert offset 128 lt assert 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 assert offset 2147483648 lt assert %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 _ 128 lt assert ==disp /none ==idx { ==r r base modrm01 disp imm8 } /encode deff > } ==MemDisp8 # base register plus 32 bit displacement { < _ bit64assert ==base ==disp /none ==idx { ==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 assert ==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 assert 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 assert 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 assert 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 256 lt assert 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 { %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 } /cmovaeqRegReg deff { ==dst ==src src bit64assert dst bit64assert 1 dst /none src rex %0F %4F dst src modrm11 } /cmovgqRegReg 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 /jle _ %7E defJmpRel8 %8E defJmpRel32 /jnb _ %73 defJmpRel8 %83 defJmpRel32 /jnc _ %73 defJmpRel8 %83 defJmpRel32 /jne _ %75 defJmpRel8 %85 defJmpRel32 /jnl _ %7D defJmpRel8 %8D 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 { ==reg ==mem ==idx ==scale ==disp reg bit32assert mem bit64assert idx bit64assert disp 128 lt assert 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 assert 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 assert i 256 lt assert 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 assert mem regno %07 gt { 0 /none /none mem rex } rep width16 %C7 /zero mem modrm00 i imm16 } /movwImmMem deff { ==mem ==i mem bit64assert i 65536 65536 mul lt assert 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 assert i 65536 65536 mul lt assert 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 assert i 2147483648 neg ge assert 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 { ==reg ==mem reg bit64assert mem bit64assert 1 reg /none mem rex %0F %B6 reg mem modrm00 } /movzxMem8Reg64 deff { ==reg ==mem ==disp reg bit64assert mem bit64assert disp 128 lt assert 1 reg /none mem rex %0F %B6 reg mem modrm01 disp imm8 } /movzxMem8Disp8Reg64 deff { ==reg ==mem ==idx ==scale ==disp reg bit64assert mem bit64assert idx bit64assert disp 128 lt assert 1 reg idx mem rex %0F %B6 reg /sib modrm01 scale idx mem sib disp imm8 } /movzxMem8IndexScaleDisp8Reg64 deff { ==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 { %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 { ==reg reg bit64assert 1 /none /none reg rex %D3 /four reg modrm11 } /shlqClReg deff { ==reg ==i reg bit64assert i 64 lt assert 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 assert 1 /none /none reg rex %C1 /five reg modrm11 i imm8 } /shrqImm8Reg 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 assert 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 { %0F %0B } /ud2 deff { ==mem ==reg reg bit64assert mem bit64assert 1 reg /none mem rex %87 reg mem modrm00 } /xchgqRegMem deff { ==dst ==src dst bit64assert src bit64assert 1 src /none dst rex %87 src dst modrm11 } /xchgqRegReg deff /xor %31 defAsmAddq # global alloc list layout # %0 : next unused byte of global alloc list as an offset from beginning of list # %8 : # %10 : base of this very alloc # %18 : size of this very alloc # %20... : of next allocs < { # ==addr [ -01 7 add 8 { _ sys .asm .peek -01 1 sub } rep -- ] { -01 256 mul add } fold } /peekImm64 deff { ==addr ==value [ value imm64 ] { addr sys .asm .poke addr 1 add =addr } each } /pokeImm64 deff GLOBALALLOCSSIZE sys .asm .alloc ==allocs allocs .base ==i [ %20 imm64 0 imm64 allocs .base imm64 allocs .size imm64 ] { i sys .asm .poke i 1 add =i } each { ==block allocs .base peekImm64 ==nextOffset nextOffset 16 add _ GLOBALALLOCSSIZE gt { "Global allocation list full." die } rep allocs .base pokeImm64 allocs .base nextOffset add =nextOffset block .base nextOffset pokeImm64 block .size nextOffset 8 add pokeImm64 } /register deff { allocs .base } /base deff > ==globalAllocations # global stack layout # 0 - STACKSTART : global variables # %0 : current stack pointer # STACKSTART - ...: real stack [ /mainStack /mainCallStack ] { < STACKSIZE sys .asm .alloc _ globalAllocations .register ==stack stack .base ==i [ stack .base STACKSIZE add imm64 ] { i sys .asm .poke i 1 add =i } each stack > -12 == }' each STACKSIZE sys .asm .alloc _ globalAllocations .register .base ==quoteEncodingBuffer { ==opcodes opcodes len 1 sub PAGESIZE div 1 add PAGESIZE mul sys .asm .alloc /codearea defv sys .asm .|poke =*poke codearea .base opcodes { -101 poke 1 add } each -- codearea } /arrayToCode deff # take an array of instruction bytes and execute it on the given stack { ==callStack ==valueStack ==opcodes [ /rbx pushqReg /r15 pushqReg valueStack /rbx movqImmReg /rsp /rbx xchgqRegMem callStack /rbx movqImmReg /r15 /rbx xchgqRegMem opcodes _ len dearray callStack /rbx movqImmReg /r15 /rbx xchgqRegMem valueStack /rbx movqImmReg /rsp /rbx xchgqRegMem /r15 popqReg /rbx popqReg retn ] } /compileOn deff { compileOn arrayToCode _ .base sys .asm .execute .free } /executeOn deff { mainStack .base mainCallStack .base executeOn } /execute deff { mainStack .base mainCallStack .base compileOn } /compile deff > /assembler defv # vim: syn=elymas