aboutsummaryrefslogtreecommitdiff
path: root/elymas/lib/sys/asmroutines.ey
blob: d0df72eed0a456573a32159d4f38e9bbf1327a0f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# assembly-optimized routines for various use cases

<
  sys .asm "::" via
  sys .asm .ops ":" via
  sys .asm .ops .|label "@" deff
  sys .asm .|peek =*:peek
  sys .asm .|poke =*:poke

  { :labelRecord [ } "[[" deff
  { ] :labelResolve } "]]" deff


  # concatenate an array full of strings into one, i.e. { |cat fold }"
  # 0 -> array of strings
  # 0 <- string obtained by concatenating all strings from the array
  [[
    /rbx :popqReg

    # sum individual lengths
    0 /rsp /rax :movqMemDisp8Reg
    /rax /esi :movlMemReg
    /rax /rsi :addqRegReg

    /rdi /rdi :xorqRegReg
    8 /rsi :subqImm8Reg
    @countLoop
    /rsi /rdx :movqMemReg
    16 /rdx /rdi :addqMemDisp8Reg
    8 /rsi :subqImm8Reg
    /rsi /rax :cmpqRegReg
    /countLoop :jnzLbl8

    ::internalAllocateString /rax :movqImmReg
    /rax :callqReg

    /rdx :popqReg # pop source array
    /rax :pushqReg # push target string

    24 /rax /rdi :leaqMemDisp8Reg
    /rdx /eax :movlMemReg
    /rdx /rax :addqRegReg

    8 /rdx :addqImm8Reg
    @copyLoop
    /rdx /rsi :movqMemReg
    16 /rsi /rcx :movqMemDisp8Reg
    24 /rsi :addqImm8Reg
    :reprcx :movsb

    8 /rdx :addqImm8Reg
    /rdx /rax :cmpqRegReg
    /copyLoop :jnzLbl8

    /rbx :pushqReg
    :retn
  ]] [ ] ::createFunction /catstrarray deffd

  # concatenate strings from topmost array marker to top of stack
  # into one, i.e. { ] |cat fold }"
  # n -> array start marker
  # 0... -> strings on the stack
  # 0 <- string obtained by concatenating all strings
  [[
    /rbx :popqReg

    /rsp /rdx :movqRegReg

    # sum individual lengths
    /rdi /rdi :xorqRegReg
    /rdx /rsi :movqMemReg
    1 /rsi :cmpqImm8Reg
    /nothingToCount :jzLbl8

    @countLoop
    16 /rsi /rdi :addqMemDisp8Reg
    8 /rdx :addqImm8Reg
    /rdx /rsi :movqMemReg
    1 /rsi :cmpqImm8Reg
    /countLoop :jnzLbl8

    @nothingToCount
    # rdi == total number of characters
    # rdx == pointer to array start marker
    /rdx :pushqReg

    ::internalAllocateString /rax :movqImmReg
    /rax :callqReg
    # rax == target string of correct length

    /rdx :popqReg
    /rdx /rbp :movqRegReg # rbp == pointer to array start marker
    24 /rax /rdi :leaqMemDisp8Reg

    /rdx /rsp :cmpqRegReg
    /nothingToCopy :jzLbl8

    @copyLoop
    8 /rdx :subqImm8Reg
    /rdx /rsi :movqMemReg
    16 /rsi /rcx :movqMemDisp8Reg
    24 /rsi :addqImm8Reg
    :reprcx :movsb
    /rdx /rsp :cmpqRegReg
    /copyLoop :jnzLbl8

    @nothingToCopy
    /rax 0 /rbp :movqRegMemDisp8 # save new string
    /rbp /rsp :movqRegReg # drop string fragments from stack

    /rbx :pushqReg
    :retn
  ]] [ ] ::createFunction /assemblestr deffd
> /asmroutines sys .defv

# vim: syn=elymas