< 4096 ==PAGESIZE 4096 16 mul 8 mul ==STACKSIZE 65536 ==GLOBALALLOCSSIZE 16 ==STACKSTART 6148914691236517205 ==STACKBOTTOMMARKER 4 ==ERRORMARKER # hex decoding { "(.)(.)" regex { } { "not a valid hex-string" die } ? * { { eq }_ [ "0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F" ] -01 index } -20*10* 16 mul add } "%" defq "elymasAsmOps.ey" include # map "anonymous" allocations away from interpreter heap 52776558133248 ==miscAllocBase # 0x300000000000 { ==size size miscAllocBase sys .asm .allocAt size miscAllocBase add =miscAllocBase } /alloc deff # 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 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 # stack layout # %0 : stack size # %8 : current stack pointer # ... : real stack # : stack bottom marker [ /bootStack /bootCallStack ] { < PAGESIZE alloc _ globalAllocations .register ==stack stack .base ==i [ PAGESIZE imm64 stack .base PAGESIZE add 8 sub imm64 ] { i sys .asm .poke i 1 add =i } each stack .base PAGESIZE add 8 sub =i [ STACKBOTTOMMARKER imm64 ] { i sys .asm .poke i 1 add =i } each stack > -12 == }' each PAGESIZE alloc _ globalAllocations .register ==:initialCoroutine # TODO create a heap-based initial coroutine < initialCoroutine .base ==i [ 40 0 0 0 0 0 0 %C8 0 imm64 # no instruction pointer, will be driven via executeOn 0 imm64 # no scope pointer, will be installed by elymalGlobal into r14 bootCallStack .base imm64 bootStack .base imm64 # 40 bytes so far, coroutine image stops here # 40-47: original rsp value 0 imm64 # 48-55: currently running co-routine (so elymasGlobal can switch to heap allocated one) initialCoroutine .base imm64 ] { i sys .asm .poke i 1 add =i } each > -- STACKSIZE alloc _ globalAllocations .register .base ==:quoteEncodingBufferCode STACKSIZE alloc _ globalAllocations .register .base ==:quoteEncodingBufferObjects { ==opcodes opcodes len 1 sub PAGESIZE udiv 1 add PAGESIZE mul 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 in the given coroutine context { ==opcodes [ /rbx pushqReg /rbp pushqReg /r12 pushqReg /r13 pushqReg /r14 pushqReg /r15 pushqReg initialCoroutine .base 40 add /rbx movqImmReg /rsp /rbx movqRegMem initialCoroutine .base 48 add /rbx movqImmReg /rbx /r13 movqMemReg 16 /r13 /r14 movqMemDisp8Reg 24 /r13 /rbx movqMemDisp8Reg 8 /rbx /r15 movqMemDisp8Reg 32 /r13 /rbx movqMemDisp8Reg 8 /rbx /rsp movqMemDisp8Reg opcodes _ len dearray /r14 16 /r13 movqRegMemDisp8 24 /r13 /rbx movqMemDisp8Reg /r15 8 /rbx movqRegMemDisp8 32 /r13 /rbx movqMemDisp8Reg /rsp 8 /rbx movqRegMemDisp8 initialCoroutine .base 48 add /rbx movqImmReg /r13 /rbx movqRegMem initialCoroutine .base 40 add /rbx movqImmReg /rbx /rsp movqMemReg /r15 popqReg /r14 popqReg /r13 popqReg /r12 popqReg /rbp popqReg /rbx popqReg retn ] } /compile deff { compile arrayToCode _ .base sys .asm .execute .free } /execute deff > /assembler defv # vim: syn=elymas