Subversion Repositories Kolibri OS

Rev

Rev 8978 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 8978 Rev 8979
1
; Macroinstructions for defining and calling procedures
1
; Macroinstructions for defining and calling procedures
2
 
2
 
3
; @brief Directly call STDCALL procedure
3
; @brief Directly call STDCALL procedure
4
; @param proc Callee name
4
; @param proc Callee name
5
; @param arg Arguments to pass
5
; @param arg Arguments to pass
6
macro stdcall proc,[arg]
6
macro stdcall proc,[arg]
7
 { common
7
 { common
8
    if ~ arg eq
8
    if ~ arg eq
9
   reverse
9
   reverse
10
        pushd   arg
10
        pushd   arg
11
   common
11
   common
12
    end if
12
    end if
13
        call    proc }
13
        call    proc }
14
 
14
 
15
; @brief Indirectly call STDCALL procedure
15
; @brief Indirectly call STDCALL procedure
16
; @param proc Callee name
16
; @param proc Callee name
17
; @param arg Arguments to pass
17
; @param arg Arguments to pass
18
macro invoke proc,[arg]
18
macro invoke proc,[arg]
19
 { common
19
 { common
20
    if ~ arg eq
20
    if ~ arg eq
21
   reverse
21
   reverse
22
        pushd   arg
22
        pushd   arg
23
   common
23
   common
24
    end if
24
    end if
25
        call    [proc] }
25
        call    [proc] }
26
 
26
 
27
; @brief Directly call CDECL procedure
27
; @brief Directly call CDECL procedure
28
; @param proc Callee name
28
; @param proc Callee name
29
; @param arg Arguments to pass
29
; @param arg Arguments to pass
30
macro ccall proc,[arg]
30
macro ccall proc,[arg]
31
 { common
31
 { common
32
    size@ccall = 0
32
    size@ccall = 0
33
    if ~ arg eq
33
    if ~ arg eq
34
   reverse
34
   reverse
35
        pushd   arg
35
        pushd   arg
36
    size@ccall = size@ccall+4
36
    size@ccall = size@ccall+4
37
   common
37
   common
38
    end if
38
    end if
39
        call    proc
39
        call    proc
40
    if size@ccall
40
    if size@ccall
41
        add     esp, size@ccall
41
        add     esp, size@ccall
42
    end if }
42
    end if }
43
 
43
 
44
; @brief Indirectly call CDECL procedure
44
; @brief Indirectly call CDECL procedure
45
; @param proc Callee name
45
; @param proc Callee name
46
; @param arg Arguments to pass
46
; @param arg Arguments to pass
47
macro cinvoke proc,[arg]
47
macro cinvoke proc,[arg]
48
 { common
48
 { common
49
    size@ccall = 0
49
    size@ccall = 0
50
    if ~ arg eq
50
    if ~ arg eq
51
   reverse
51
   reverse
52
        pushd   arg
52
        pushd   arg
53
    size@ccall = size@ccall+4
53
    size@ccall = size@ccall+4
54
   common
54
   common
55
    end if
55
    end if
56
        call    [proc]
56
        call    [proc]
57
    if size@ccall
57
    if size@ccall
58
        add     esp, size@ccall
58
        add     esp, size@ccall
59
    end if }
59
    end if }
60
 
60
 
61
; @brief Define a procedure.\n
61
; @brief Define a procedure.\n
62
;        Calling convention for the procedure may be defined before parameter
62
;        Calling convention for the procedure may be defined before parameter
63
;        list using `stdcall` or `c` word like this:\n
63
;        list using `stdcall` or `c` word like this:\n
64
;        `proc name stdcall, param0, param1`\n
64
;        `proc name stdcall, param0, param1`\n
65
;        List of registers used in the procedure may be specified before
65
;        List of registers used in the procedure may be specified before
66
;        parameter list using `uses` word like this:\n
66
;        parameter list using `uses` word like this:\n
67
;        `proc name uses eax ebx ecx, param0, param1`\n
67
;        `proc name uses eax ebx ecx, param0, param1`\n
68
;        If you need to specify both calling convention and used registers
68
;        If you need to specify both calling convention and used registers
69
;        put calling convention first and then `uses` statement like this:\n
69
;        put calling convention first and then `uses` statement like this:\n
70
;        `proc name stdcall uses ebx ecx edx, param0, param1`
70
;        `proc name stdcall uses ebx ecx edx, param0, param1`\n
71
; @param args Name of the procedure and a comma-separated argument list.
71
;        The defined procedure should be ended using `endp` macro.
-
 
72
; @param args Name of the procedure and a comma-separated argument list.
72
;             Type of any parameter may be specified by semicolon after its
73
;             Type of any parameter may be specified by semicolon after its
73
;             name like this:\n
74
;             name like this:\n
74
;             `proc name param0:dword, param1:qword`.
75
;             `proc name param0:dword, param1:qword`.
75
macro proc [args]
76
macro proc [args]
76
 { common
77
 { common
77
    match name params, args>
78
    match name params, args>
78
    \{ define@proc name,
79
    \{ define@proc name,
79
 
80
 
80
prologue@proc equ prologuedef
81
prologue@proc equ prologuedef
81
 
82
 
82
; @dont_give_a_doxygen
83
; @dont_give_a_doxygen
83
macro prologuedef procname,flag,parmbytes,localbytes,reglist
84
macro prologuedef procname,flag,parmbytes,localbytes,reglist
84
 { local loc
85
 { local loc
85
   loc = (localbytes+3) and (not 3)
86
   loc = (localbytes+3) and (not 3)
86
   parmbase@proc equ ebp+8
87
   parmbase@proc equ ebp+8
87
   localbase@proc equ ebp-loc
88
   localbase@proc equ ebp-loc
88
   if parmbytes | localbytes
89
   if parmbytes | localbytes
89
        push    ebp
90
        push    ebp
90
        mov     ebp, esp
91
        mov     ebp, esp
91
    if localbytes
92
    if localbytes
92
        sub     esp, loc
93
        sub     esp, loc
93
    end if
94
    end if
94
   end if
95
   end if
95
   irps reg, reglist \{ push reg \} }
96
   irps reg, reglist \{ push reg \} }
96
 
97
 
97
epilogue@proc equ epiloguedef
98
epilogue@proc equ epiloguedef
98
 
99
 
99
; @dont_give_a_doxygen
100
; @dont_give_a_doxygen
100
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
101
macro epiloguedef procname,flag,parmbytes,localbytes,reglist
101
 { irps reg, reglist \{ reverse pop reg \}
102
 { irps reg, reglist \{ reverse pop reg \}
102
   if parmbytes | localbytes
103
   if parmbytes | localbytes
103
        leave
104
        leave
104
   end if
105
   end if
105
   if flag and 10000b
106
   if flag and 10000b
106
        retn
107
        retn
107
   else
108
   else
108
        retn    parmbytes
109
        retn    parmbytes
109
   end if }
110
   end if }
110
 
111
 
111
close@proc equ
112
close@proc equ
112
 
113
 
113
; @dont_give_a_doxygen
114
; @dont_give_a_doxygen
114
macro define@proc name,statement
115
macro define@proc name,statement
115
 { local params,flag,regs,parmbytes,localbytes,current
116
 { local params,flag,regs,parmbytes,localbytes,current
116
   if used name
117
   if used name
117
   name:
118
   name:
118
   match =stdcall args, statement \{ params equ args
119
   match =stdcall args, statement \{ params equ args
119
                                     flag = 11b \}
120
                                     flag = 11b \}
120
   match =stdcall, statement \{ params equ
121
   match =stdcall, statement \{ params equ
121
                                flag = 11b \}
122
                                flag = 11b \}
122
   match =c args, statement \{ params equ args
123
   match =c args, statement \{ params equ args
123
                               flag = 10001b \}
124
                               flag = 10001b \}
124
   match =c, statement \{ params equ
125
   match =c, statement \{ params equ
125
                          flag = 10001b \}
126
                          flag = 10001b \}
126
   match =params, params \{ params equ statement
127
   match =params, params \{ params equ statement
127
                            flag = 0 \}
128
                            flag = 0 \}
128
   match =uses reglist=,args, params \{ regs equ reglist
129
   match =uses reglist=,args, params \{ regs equ reglist
129
                                        params equ args \}
130
                                        params equ args \}
130
   match =regs =uses reglist, regs params \{ regs equ reglist
131
   match =regs =uses reglist, regs params \{ regs equ reglist
131
                                             params equ \}
132
                                             params equ \}
132
   match =regs, regs \{ regs equ \}
133
   match =regs, regs \{ regs equ \}
133
   match prologue:reglist, prologue@proc: \{ prologue name,flag,parmbytes,localbytes,reglist \}
134
   match prologue:reglist, prologue@proc: \{ prologue name,flag,parmbytes,localbytes,reglist \}
134
   virtual at parmbase@proc
135
   virtual at parmbase@proc
135
   match =,args, params \{ defargs@proc args \}
136
   match =,args, params \{ defargs@proc args \}
136
   match =args@proc args, args@proc params \{ defargs@proc args \}
137
   match =args@proc args, args@proc params \{ defargs@proc args \}
137
   parmbytes = $-(parmbase@proc)
138
   parmbytes = $-(parmbase@proc)
138
   end virtual
139
   end virtual
139
   name # % = parmbytes/4
140
   name # % = parmbytes/4
140
   all@vars equ
141
   all@vars equ
141
   current = 0
142
   current = 0
142
   macro locals
143
   macro locals
143
   \{ virtual at localbase@proc+current
144
   \{ virtual at localbase@proc+current
144
      macro label def \\{ match . type,def> \\\{ deflocal@proc .,label,
145
      macro label def \\{ match . type,def> \\\{ deflocal@proc .,label,
145
      struc db [val] \\{ \common deflocal@proc .,db,val \\}
146
      struc db [val] \\{ \common deflocal@proc .,db,val \\}
146
      struc du [val] \\{ \common deflocal@proc .,du,val \\}
147
      struc du [val] \\{ \common deflocal@proc .,du,val \\}
147
      struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
148
      struc dw [val] \\{ \common deflocal@proc .,dw,val \\}
148
      struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
149
      struc dp [val] \\{ \common deflocal@proc .,dp,val \\}
149
      struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
150
      struc dd [val] \\{ \common deflocal@proc .,dd,val \\}
150
      struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
151
      struc dt [val] \\{ \common deflocal@proc .,dt,val \\}
151
      struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
152
      struc dq [val] \\{ \common deflocal@proc .,dq,val \\}
152
      struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
153
      struc rb cnt \\{ deflocal@proc .,rb cnt, \\}
153
      struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
154
      struc rw cnt \\{ deflocal@proc .,rw cnt, \\}
154
      struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
155
      struc rp cnt \\{ deflocal@proc .,rp cnt, \\}
155
      struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
156
      struc rd cnt \\{ deflocal@proc .,rd cnt, \\}
156
      struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
157
      struc rt cnt \\{ deflocal@proc .,rt cnt, \\}
157
      struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
158
      struc rq cnt \\{ deflocal@proc .,rq cnt, \\} \}
158
   macro endl
159
   macro endl
159
   \{ purge label
160
   \{ purge label
160
      restruc db,du,dw,dp,dd,dt,dq
161
      restruc db,du,dw,dp,dd,dt,dq
161
      restruc rb,rw,rp,rd,rt,rq
162
      restruc rb,rw,rp,rd,rt,rq
162
      current = $-(localbase@proc)
163
      current = $-(localbase@proc)
163
      end virtual \}
164
      end virtual \}
164
   macro ret operand
165
   macro ret operand
165
   \{ match any, operand \\{ retn operand \\}
166
   \{ match any, operand \\{ retn operand \\}
166
      match , operand \\{ match epilogue:reglist, epilogue@proc: \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
167
      match , operand \\{ match epilogue:reglist, epilogue@proc: \\\{ epilogue name,flag,parmbytes,localbytes,reglist \\\} \\} \}
167
   macro finish@proc
168
   macro finish@proc
168
   \{ localbytes = current
169
   \{ localbytes = current
169
      match close:reglist, close@proc: \\{ close name,flag,parmbytes,localbytes,reglist \\}
170
      match close:reglist, close@proc: \\{ close name,flag,parmbytes,localbytes,reglist \\}
170
      end if \} }
171
      end if \} }
171
 
172
 
172
; @dont_give_a_doxygen
173
; @dont_give_a_doxygen
173
macro defargs@proc [arg]
174
macro defargs@proc [arg]
174
 { common
175
 { common
175
    if ~ arg eq
176
    if ~ arg eq
176
   forward
177
   forward
177
     local ..arg,current@arg
178
     local ..arg,current@arg
178
     match argname:type, arg
179
     match argname:type, arg
179
      \{ current@arg equ argname
180
      \{ current@arg equ argname
180
         label ..arg type
181
         label ..arg type
181
         argname equ ..arg
182
         argname equ ..arg
182
         if dqword eq type
183
         if dqword eq type
183
           dd ?,?,?,?
184
           dd ?,?,?,?
184
         else if tbyte eq type
185
         else if tbyte eq type
185
           dd ?,?,?
186
           dd ?,?,?
186
         else if qword eq type | pword eq type
187
         else if qword eq type | pword eq type
187
           dd ?,?
188
           dd ?,?
188
         else
189
         else
189
           dd ?
190
           dd ?
190
         end if \}
191
         end if \}
191
     match =current@arg,current@arg
192
     match =current@arg,current@arg
192
      \{ current@arg equ arg
193
      \{ current@arg equ arg
193
         arg equ ..arg
194
         arg equ ..arg
194
         ..arg dd ? \}
195
         ..arg dd ? \}
195
   common
196
   common
196
     args@proc equ current@arg
197
     args@proc equ current@arg
197
   forward
198
   forward
198
     restore current@arg
199
     restore current@arg
199
   common
200
   common
200
    end if }
201
    end if }
201
 
202
 
202
; @dont_give_a_doxygen
203
; @dont_give_a_doxygen
203
macro deflocal@proc name,def,[val] { name def val }
204
macro deflocal@proc name,def,[val] { name def val }
204
 
205
 
205
; @dont_give_a_doxygen
206
; @dont_give_a_doxygen
206
macro deflocal@proc name,def,[val]
207
macro deflocal@proc name,def,[val]
207
 { common
208
 { common
208
    match vars, all@vars \{ all@vars equ all@vars, \}
209
    match vars, all@vars \{ all@vars equ all@vars, \}
209
    all@vars equ all@vars name
210
    all@vars equ all@vars name
210
   forward
211
   forward
211
    local ..var,..tmp
212
    local ..var,..tmp
212
    ..var def val
213
    ..var def val
213
    match =?, val \{ ..tmp equ \}
214
    match =?, val \{ ..tmp equ \}
214
    match any =?, val \{ ..tmp equ \}
215
    match any =?, val \{ ..tmp equ \}
215
    match any (=?), val \{ ..tmp equ \}
216
    match any (=?), val \{ ..tmp equ \}
216
    match =label, def \{ ..tmp equ \}
217
    match =label, def \{ ..tmp equ \}
217
    match tmp : value, ..tmp : val
218
    match tmp : value, ..tmp : val
218
     \{ tmp: end virtual
219
     \{ tmp: end virtual
219
        initlocal@proc ..var,def value
220
        initlocal@proc ..var,def value
220
        virtual at tmp\}
221
        virtual at tmp\}
221
   common
222
   common
222
    match first rest, ..var, \{ name equ first \} }
223
    match first rest, ..var, \{ name equ first \} }
223
 
224
 
224
struc label type { label . type }
225
struc label type { label . type }
225
 
226
 
226
; @dont_give_a_doxygen
227
; @dont_give_a_doxygen
227
macro initlocal@proc name,def
228
macro initlocal@proc name,def
228
 { virtual at name
229
 { virtual at name
229
    def
230
    def
230
    size@initlocal = $ - name
231
    size@initlocal = $ - name
231
   end virtual
232
   end virtual
232
   position@initlocal = 0
233
   position@initlocal = 0
233
   while size@initlocal > position@initlocal
234
   while size@initlocal > position@initlocal
234
    virtual at name
235
    virtual at name
235
     def
236
     def
236
     if size@initlocal - position@initlocal < 2
237
     if size@initlocal - position@initlocal < 2
237
      current@initlocal = 1
238
      current@initlocal = 1
238
      load byte@initlocal byte from name+position@initlocal
239
      load byte@initlocal byte from name+position@initlocal
239
     else if size@initlocal - position@initlocal < 4
240
     else if size@initlocal - position@initlocal < 4
240
      current@initlocal = 2
241
      current@initlocal = 2
241
      load word@initlocal word from name+position@initlocal
242
      load word@initlocal word from name+position@initlocal
242
     else
243
     else
243
      current@initlocal = 4
244
      current@initlocal = 4
244
      load dword@initlocal dword from name+position@initlocal
245
      load dword@initlocal dword from name+position@initlocal
245
     end if
246
     end if
246
    end virtual
247
    end virtual
247
    if current@initlocal = 1
248
    if current@initlocal = 1
248
        mov     byte [name+position@initlocal], byte@initlocal
249
        mov     byte [name+position@initlocal], byte@initlocal
249
    else if current@initlocal = 2
250
    else if current@initlocal = 2
250
        mov     word [name+position@initlocal], word@initlocal
251
        mov     word [name+position@initlocal], word@initlocal
251
    else
252
    else
252
        mov     dword [name+position@initlocal], dword@initlocal
253
        mov     dword [name+position@initlocal], dword@initlocal
253
    end if
254
    end if
254
    position@initlocal = position@initlocal + current@initlocal
255
    position@initlocal = position@initlocal + current@initlocal
255
   end while }
256
   end while }
256
 
257
 
-
 
258
; @brief Mark the end of a procedure created by `proc` macro
257
macro endp
259
macro endp
258
 { purge ret,locals,endl
260
 { purge ret,locals,endl
259
   finish@proc
261
   finish@proc
260
   purge finish@proc
262
   purge finish@proc
261
   restore regs@proc
263
   restore regs@proc
262
   match all,args@proc \{ restore all \}
264
   match all,args@proc \{ restore all \}
263
   restore args@proc
265
   restore args@proc
264
   match all,all@vars \{ restore all \} }
266
   match all,all@vars \{ restore all \} }
265
 
267
 
266
macro local [var]
268
macro local [var]
267
 { common
269
 { common
268
    locals
270
    locals
269
   forward done@local equ
271
   forward done@local equ
270
    match varname[count]:vartype, var
272
    match varname[count]:vartype, var
271
    \{ match =BYTE, vartype \\{ varname rb count
273
    \{ match =BYTE, vartype \\{ varname rb count
272
                                restore done@local \\}
274
                                restore done@local \\}
273
       match =WORD, vartype \\{ varname rw count
275
       match =WORD, vartype \\{ varname rw count
274
                                restore done@local \\}
276
                                restore done@local \\}
275
       match =DWORD, vartype \\{ varname rd count
277
       match =DWORD, vartype \\{ varname rd count
276
                                 restore done@local \\}
278
                                 restore done@local \\}
277
       match =PWORD, vartype \\{ varname rp count
279
       match =PWORD, vartype \\{ varname rp count
278
                                 restore done@local \\}
280
                                 restore done@local \\}
279
       match =QWORD, vartype \\{ varname rq count
281
       match =QWORD, vartype \\{ varname rq count
280
                                 restore done@local \\}
282
                                 restore done@local \\}
281
       match =TBYTE, vartype \\{ varname rt count
283
       match =TBYTE, vartype \\{ varname rt count
282
                                 restore done@local \\}
284
                                 restore done@local \\}
283
       match =DQWORD, vartype \\{ label varname dqword
285
       match =DQWORD, vartype \\{ label varname dqword
284
                                  rq count+count
286
                                  rq count+count
285
                                  restore done@local \\}
287
                                  restore done@local \\}
286
       match , done@local \\{ virtual
288
       match , done@local \\{ virtual
287
                               varname vartype
289
                               varname vartype
288
                              end virtual
290
                              end virtual
289
                              rb count*sizeof.\#vartype
291
                              rb count*sizeof.\#vartype
290
                              restore done@local \\} \}
292
                              restore done@local \\} \}
291
    match :varname:vartype, done@local:var
293
    match :varname:vartype, done@local:var
292
    \{ match =BYTE, vartype \\{ varname db ?
294
    \{ match =BYTE, vartype \\{ varname db ?
293
                                restore done@local \\}
295
                                restore done@local \\}
294
       match =WORD, vartype \\{ varname dw ?
296
       match =WORD, vartype \\{ varname dw ?
295
                                restore done@local \\}
297
                                restore done@local \\}
296
       match =DWORD, vartype \\{ varname dd ?
298
       match =DWORD, vartype \\{ varname dd ?
297
                                 restore done@local \\}
299
                                 restore done@local \\}
298
       match =PWORD, vartype \\{ varname dp ?
300
       match =PWORD, vartype \\{ varname dp ?
299
                                 restore done@local \\}
301
                                 restore done@local \\}
300
       match =QWORD, vartype \\{ varname dq ?
302
       match =QWORD, vartype \\{ varname dq ?
301
                                 restore done@local \\}
303
                                 restore done@local \\}
302
       match =TBYTE, vartype \\{ varname dt ?
304
       match =TBYTE, vartype \\{ varname dt ?
303
                                 restore done@local \\}
305
                                 restore done@local \\}
304
       match =DQWORD, vartype \\{ label varname dqword
306
       match =DQWORD, vartype \\{ label varname dqword
305
                                  dq ?,?
307
                                  dq ?,?
306
                                  restore done@local \\}
308
                                  restore done@local \\}
307
       match , done@local \\{ varname vartype
309
       match , done@local \\{ varname vartype
308
                              restore done@local \\} \}
310
                              restore done@local \\} \}
309
    match ,done@local
311
    match ,done@local
310
    \{ var
312
    \{ var
311
       restore done@local \}
313
       restore done@local \}
312
   common
314
   common
313
    endl }
315
    endl }