< "str" enterSubScope < # allocate an uninitialized string # 0 -> number of data bytes to allocate # 0 <- the string [[ /rbx :popqReg /rdi :popqReg /rdi :pushqReg /rdi ::unboxInteger 24 /rdi :addqImm8Reg ::internalAllocate /rax :movqImmReg /rax :callqReg # set type %10 7 /rax :orbImmMemDisp8 # clear hash value /rdx /rdx :xorqRegReg /rdx 8 /rax :movqRegMemDisp8 # set exact length /rdi :popqReg /rdi ::unboxInteger /rdi 16 /rax :movqRegMemDisp8 /rax :pushqReg /rbx :pushqReg :retn ]] /eyalloc defv # reduce exact string length in place # 0 -> string to shorten # 1 -> length of prefix # 0 <- the same string (but now with exact length field overwritten) # this effectively creates a prefix of the string [[ /rbx :popqReg /rax :popqReg /rcx :popqReg /rcx ::unboxInteger 16 /rax /rcx :cmpqMemDisp8Reg /ok :jbeLbl8 "prefix length above string length in inplacePrefix" ::outputError :ud2 @ok /rcx 16 /rax :movqRegMemDisp8 /rcx /rcx :xorqRegReg /rcx 8 /rax :movqRegMemDisp8 # reset hash value /rax :pushqReg /rbx :pushqReg :retn ]] /eyinplacePrefix defv # calculate a string infix # 0 -> string to shorten # 1 -> first position after the infix # 2 -> first position in the infix [[ /rbx :popqReg /rcx :popqReg # rcx == string 16 /rcx /rbp :movqMemDisp8Reg /rdi :popqReg /rdi ::unboxInteger 0 /rdi :cmpqImm8Reg /positiveEndOffset :jgeLbl8 /rbp /rdi :addqRegReg @positiveEndOffset /rsi :popqReg /rsi ::unboxInteger 0 /rsi :cmpqImm8Reg /positiveStartOffset :jgeLbl8 /rbp /rsi :addqRegReg @positiveStartOffset # rdi == end offset # rsi == start offset /rcx :pushqReg /rsi :pushqReg /rsi /rdi :subqRegReg /negativeLengthInfix :jsLbl8 @negativeLengthInfixFixed /rdi :pushqReg ::internalAllocateString /rax :movqImmReg /rax :callqReg /rcx :popqReg # rcx == count of bytes to copy /rsi :popqReg # rsi == start offset /rdx :popqReg # rdx == source string /rax :pushqReg :cld 24 1 /rsi /rdx /rsi :leaqMemIndexScaleDisp8Reg 24 /rax /rdi :leaqMemDisp8Reg :reprcx :movsb /rbx :pushqReg :retn @negativeLengthInfix /rdi /rdi :xorqRegReg /negativeLengthInfixFixed :jmpLbl8 ]] /eyinfix defv # calculate a string prefix # 0 -> string to shorten # 1 -> first position after the prefix [[ /rbx :popqReg /rcx :popqReg # rcx == string 16 /rcx /rbp :movqMemDisp8Reg /rdi :popqReg /rdi ::unboxInteger 0 /rdi :cmpqImm8Reg /positiveEndOffset :jgeLbl8 /rbp /rdi :addqRegReg @positiveEndOffset /rsi /rsi :xorqRegReg # rdi == end offset # rsi == start offset /rcx :pushqReg /rsi :pushqReg /rsi /rdi :subqRegReg /negativeLengthInfix :jsLbl8 @negativeLengthInfixFixed /rdi :pushqReg ::internalAllocateString /rax :movqImmReg /rax :callqReg /rcx :popqReg # rcx == count of bytes to copy /rsi :popqReg # rsi == start offset /rdx :popqReg # rdx == source string /rax :pushqReg :cld 24 1 /rsi /rdx /rsi :leaqMemIndexScaleDisp8Reg 24 /rax /rdi :leaqMemDisp8Reg :reprcx :movsb /rbx :pushqReg :retn @negativeLengthInfix /rdi /rdi :xorqRegReg /negativeLengthInfixFixed :jmpLbl8 ]] /eyprefix defv # calculate a string postfix # 0 -> string to shorten # 1 -> position of string where to start the postfix # 0 <- the requested postfix of the string [[ /rbx :popqReg /rcx :popqReg # rcx == string 16 /rcx /rbp :movqMemDisp8Reg /rbp /rdi :movqRegReg /rsi :popqReg /rsi ::unboxInteger 0 /rsi :cmpqImm8Reg /positiveStartOffset :jgeLbl8 /rbp /rsi :addqRegReg @positiveStartOffset # rdi == end offset # rsi == start offset /rcx :pushqReg /rsi :pushqReg /rsi /rdi :subqRegReg /negativeLengthInfix :jsLbl8 @negativeLengthInfixFixed /rdi :pushqReg ::internalAllocateString /rax :movqImmReg /rax :callqReg /rcx :popqReg # rcx == count of bytes to copy /rsi :popqReg # rsi == start offset /rdx :popqReg # rdx == source string /rax :pushqReg :cld 24 1 /rsi /rdx /rsi :leaqMemIndexScaleDisp8Reg 24 /rax /rdi :leaqMemDisp8Reg :reprcx :movsb /rbx :pushqReg :retn @negativeLengthInfix /rdi /rdi :xorqRegReg /negativeLengthInfixFixed :jmpLbl8 ]] /eypostfix defv # produce a string from an integer array specifying its bytes # 0 -> array of integers # 0 <- the same bytes as a string [[ /rbx :popqReg /rsi :popqReg /rsi :pushqReg /rsi /edi :movlMemReg # load array length 3 /rdi :shrqImm8Reg /rdi :decqReg /rdi :pushqReg ::internalAllocateString /rax :movqImmReg /rax :callqReg /rcx :popqReg # number of characters to copy /rsi :popqReg /rax :pushqReg # store target string on stack /rcx /rcx :testqRegReg /emptyArray :jzLbl8 8 /rsi :addqImm8Reg # move rsi to first array entry 24 /rax :addqImm8Reg # move rax to first string byte @copyByte /rsi /rdx :movqMemReg # load object pointer /rdx ::unboxInteger /dl /rax :movbRegMem 8 /rsi :addqImm8Reg /rax :incqReg /copyByte :loopLbl8 @emptyArray /rbx :pushqReg :retn ]] /eyfromArray defv # split a string on a given character # 0 -> single letter separator string # 1 -> string to split # 0 <- array of string fragments # Examples: # "" ";" str .split -> [ "" ] # "foo;bar" ";" str .split -> [ "foo" "bar" ] # "foo;bar;quux;" ";" str .split -> [ "foo" "bar" "quux" "" ] [[ /rbx :popqReg /rax :popqReg 1 16 /rax :cmpqImm8MemDisp8 /notSingleCharacter :jnzLbl32 24 /rax /rax :movqMemDisp8Reg # al == the separator char /rdx :popqReg 16 /rdx /rcx :movqMemDisp8Reg 24 /rdx /rdi :leaqMemDisp8Reg /rcx /rcx :testqRegReg /nonEmptyInitialString :jnzLbl8 /rdi :pushqReg /rdi :incqReg /rdi :pushqReg 1 /rbp :movqImmReg /finalCharacterNotSeparator :jmpLbl8 @nonEmptyInitialString /rbp /rbp :xorqRegReg /rdi :pushqReg # push (effect of) virtual separator before string data @searchFragmentLoop :repnz :scasb /rdi :pushqReg /rbp :incqReg /rcx /rcx :testqRegReg /searchFragmentLoop :jnzLbl8 /al 1 neg /rdi :cmpbRegMemDisp8 /finalCharacterNotSeparator :jnzLbl8 /rdi :incqReg /rdi :pushqReg /rbp :incqReg /finalCharacterSeparator :jmpLbl8 @finalCharacterNotSeparator 1 0 /rsp :addqImm8MemDisp8 @finalCharacterSeparator # the stack now holds rbp many pointers to fragment starts (from bottom to top) 24 /r15 :subqImm8Reg /rbp 8 /r15 :movqRegMemDisp8 /rbp /rdi :movqRegReg 3 /rdi :shlqImm8Reg ::internalAllocateArray /rax :movqImmReg /rax :callqReg 8 /r15 /rbp :movqMemDisp8Reg # rbp == count of fragments /rax 16 /r15 :movqRegMemDisp8 # 16 /r15 == result array object 8 /rbp /rax /rdi :leaqMemIndexScaleReg # rdi == last array cell /rdi /r15 :movqRegMem # 0 /r15 == target array cell # 8 /r15 == remaining fragments to generate # 16 /r15 == result array object @generateFragmentLoop 0 /rsp /rdi :movqMemDisp8Reg 8 /rsp /rdi :subqMemDisp8Reg /rdi :decqReg ::internalAllocateString /rax :movqImmReg /rax :callqReg /r15 /rdi :movqMemReg /rax /rdi :movqRegMem # new string object into array cell 8 /r15 :subqImm8Mem # move to array cell 8 bytes before 24 /rax /rdi :leaqMemDisp8Reg # new string object data section to rdi 8 /rsp /rsi :movqMemDisp8Reg # fragment data to rsi 0 /rsp /rcx :movqMemDisp8Reg 8 /rsp /rcx :subqMemDisp8Reg /rcx :decqReg :reprcx :movsb 8 /rsp :addqImm8Reg # drop fragment data 1 8 /r15 :subqImm8MemDisp8 /generateFragmentLoop :jnzLbl8 16 /r15 /rax :movqMemDisp8Reg /rax 0 /rsp :movqRegMemDisp8 # replace last fragment data by array object 24 /r15 :addqImm8Reg /rbx :pushqReg :retn @notSingleCharacter "separator string not single character" ::outputError :ud2 ]] /eysplit defv ## Bitfield style functions # reset a string to all-zero # 0 -> string to reset [[ /rbx :popqReg /rdi :popqReg /rax /rax :xorqRegReg 16 /rdi /rcx :movqMemDisp8Reg 24 /rdi :addqImm8Reg /rcx :decqReg 3 /rcx :shrqImm8Reg /rcx :incqReg :reprcx :stosq /rbx :pushqReg :retn ]] /eyzero defv # bit test # 0 -> string to extract bit from # 1 -> bit index to extract [[ /rbx :popqReg /rdi :popqReg /rax :popqReg /rax ::unboxInteger /rcx /rcx :xorqRegReg /rax 24 /rdi :btqRegMemDisp8 /cl :setcbReg 63 /rcx :btsqImm8Reg /rcx :pushqReg /rbx :pushqReg :retn ]] /eybitTest defv # bit set # 0 -> string to extract bit from # 1 -> bit index to set [[ /rbx :popqReg /rdi :popqReg /rax :popqReg /rax ::unboxInteger /rax 24 /rdi :btsqRegMemDisp8 /rbx :pushqReg :retn ]] /eybitSet defv # bit reset # 0 -> string to extract bit from # 1 -> bit index to set [[ /rbx :popqReg /rdi :popqReg /rax :popqReg /rax ::unboxInteger /rax 24 /rdi :btrqRegMemDisp8 /rbx :pushqReg :retn ]] /eybitReset defv > _ ==globalFunctions { defv }' ::allocateOffsetStruct [ globalFunctions keys eydeff { | }' createScopeEntries createScopeExtensionEntries ] :execute leaveSubScope > -- # vim: syn=elymas