2
|
1 //Import extendlib.rhope
|
|
2 Escape Rhope Name[name:escaped]
|
|
3 {
|
|
4 escaped <- [[[[[[[[[name]Replace["_","__"]
|
|
5 ]Replace["@","_AT_"]
|
|
6 ]Replace[" ","_SP_"]
|
|
7 ]Replace[":","_CN_"]
|
|
8 ]Replace["?","_QN_"]
|
|
9 ]Replace["+","_PL_"]
|
|
10 ]Replace["-","_MN_"]
|
|
11 ]Replace["*","_TM_"]
|
|
12 ]Replace["/","_DV_"]
|
|
13 }
|
|
14
|
|
15 Blueprint Registers
|
|
16 {
|
|
17 Names
|
|
18 Can Data
|
|
19 Can Pointer
|
|
20 Available?
|
|
21 Need Save
|
|
22 Max Size
|
|
23 }
|
|
24
|
|
25 Set Yes[in:out]
|
|
26 {
|
|
27 out <- Yes
|
|
28 }
|
|
29
|
|
30 _Flip[dest,val,index:out]
|
|
31 {
|
|
32 out <- [dest]Set[val,index]
|
|
33 }
|
|
34 Flip[list,dest:out]
|
|
35 {
|
|
36 out <- Fold["_Flip", dest, list]
|
|
37 }
|
|
38
|
|
39 Registers[names, data, pointer, need save, max size:out]
|
|
40 {
|
|
41 out <- [[[[[[Build["Registers"]
|
|
42 ]Names << [names]
|
|
43 ]Can Data << [data]
|
|
44 ]Can Pointer << [pointer]
|
|
45 ]Available? << [ Map[names, "Set Yes"] ]
|
|
46 ]Need Save << [ Flip[need save, ()] ]
|
|
47 ]Max Size <<[max size]
|
|
48 }
|
|
49
|
|
50 Name@Registers[regs,num:out]
|
|
51 {
|
|
52 out <- [[regs]Names >>]Index[num]
|
|
53 }
|
|
54
|
|
55 Allocate Helper@Registers[regs, try, current:found, not found]
|
|
56 {
|
|
57 reg <- [try]Index[current]
|
|
58 If[[[regs]Available? >>]Index[reg]]
|
|
59 {
|
|
60 found <- Val[reg]
|
|
61 }{
|
|
62 [try]Next[current]
|
|
63 {
|
|
64 found, not found <- [regs]Allocate Helper[try, ~]
|
|
65 }{
|
|
66 not found <- Yes
|
|
67 }
|
|
68 }
|
|
69 }
|
|
70
|
|
71 Allocate Reg@Registers[regs,try:next regs,found,need save?,not found]
|
|
72 {
|
|
73 [try]First
|
|
74 {
|
|
75 found, not found <- [regs]Allocate Helper[try, ~]
|
|
76 {
|
|
77 next regs <- [regs]Available? << [ [[regs]Available? >>]Set[~, No] ]
|
|
78 [[regs]Need Save >>]Index[~]
|
|
79 {
|
|
80 need save? <- Yes
|
|
81 }{
|
|
82 need save? <- No
|
|
83 }
|
|
84 }
|
|
85 }{
|
|
86 not found <- Yes
|
|
87 }
|
|
88 }
|
|
89
|
|
90 Free Reg@Registers[regs,num:out]
|
|
91 {
|
|
92 out <- [regs]Available? <<[ [[regs]Available? >>]Set[num, Yes] ]
|
|
93 }
|
|
94
|
|
95 Processor Reg[func,type:next func,num,not found]
|
|
96 {
|
|
97 regs <- [func]Registers >>
|
|
98 If[[type] = ["pointer"]]
|
|
99 {
|
|
100 source <- [regs]Can Pointer >>
|
|
101 }{
|
|
102 source <- [regs]Can Data >>
|
|
103 }
|
|
104 next regs, reg num, need save?, not found <- [regs]Allocate Reg[source] {}
|
|
105 {
|
|
106 If[need save?]
|
|
107 {
|
|
108 next func <- [[func]Need Save << [ [[func]Need Save >>]Set[reg num, Yes] ]
|
|
109 ]Registers << [next regs]
|
|
110 }{
|
|
111 next func <- [func]Registers << [next regs]
|
|
112 }
|
|
113 num <- Val[reg num]
|
|
114 }
|
|
115 }
|
|
116
|
|
117 Processor Free Reg[func,num:out func]
|
|
118 {
|
|
119 out func <- [func]Registers <<[ [[func]Registers >>]Free Reg[num] ]
|
|
120 }
|
|
121
|
|
122 Processor Allocate[func,name,size,type:out func,out]
|
|
123 {
|
|
124 regs <- [func]Registers >>
|
|
125 If[[type] = ["pointer"]]
|
|
126 {
|
|
127 alloc size <- [func]Pointer Size
|
|
128 }{
|
|
129 alloc size <- size
|
|
130 }
|
|
131 If[[alloc size] > [[regs]Max Size >>]] {
|
|
132 stack alloc <- Val[alloc size]
|
|
133 }{
|
|
134 next func <- [func]Processor Reg[type] {}
|
|
135 {
|
|
136 location <- Register[~, alloc size]
|
|
137 }{
|
|
138 stack alloc <- Val[alloc size]
|
|
139 }
|
|
140 }
|
|
141 Val[stack alloc]
|
|
142 {
|
|
143 next func, location <- [func]Allocate Stack[alloc size]
|
|
144 }
|
|
145 out func <- [next func]Variables <<[ [[next func]Variables >>]Set[name, location] ]
|
|
146 out <- Val[location]
|
|
147 }
|
|
148
|
|
149 Blueprint Register
|
|
150 {
|
|
151 Number
|
|
152 Value Size
|
|
153 }
|
|
154 Register[num,size:out]
|
|
155 {
|
|
156 If[[size] = [3]]
|
|
157 {
|
|
158 value size <- 4
|
|
159 }{
|
|
160 value size <- size
|
|
161 }
|
|
162 out <- [[Build["Register"]]Number <<[num]]Value Size <<[value size]
|
|
163 }
|
|
164
|
|
165 In Memory?@Register[reg:out]
|
|
166 {
|
|
167 out <- No
|
|
168 }
|
|
169
|
|
170 =@Register[reg,other:out]
|
|
171 {
|
|
172 ,out <- If[[Type Of[reg]] = [Type Of[other]]]
|
|
173 {
|
|
174 out <- [[reg]Number >>] = [[other]Number >>]
|
|
175 }
|
|
176 }
|
|
177
|
|
178 Op ASM@Register[reg,func,regs,extra offset:out]
|
|
179 {
|
|
180 out <- [regs]Index[ [reg]Number >> ]
|
|
181 }
|
|
182
|
|
183 Size@Register[reg:out]
|
|
184 {
|
|
185 out <- [reg]Value Size >>
|
|
186 }
|
|
187
|
|
188 Blueprint Immediate
|
|
189 {
|
|
190 Value
|
|
191 }
|
|
192
|
|
193 Immediate[val:out]
|
|
194 {
|
|
195 out <- [Build["Immediate"]]Value <<[val]
|
|
196 }
|
|
197
|
|
198 In Memory?@Immediate[val:out]
|
|
199 {
|
|
200 out <- No
|
|
201 }
|
|
202
|
|
203 =@Immediate[val,other:out]
|
|
204 {
|
|
205 ,out <- If[[Type Of[val]] = [Type Of[other]]]
|
|
206 {
|
|
207 out <- [[val]Value >>] = [[other]Value >>]
|
|
208 }
|
|
209 }
|
|
210
|
|
211 Op ASM@Immediate[val,func,regs,extra offset:out]
|
|
212 {
|
|
213 out <- [val]Value >>
|
|
214 }
|
|
215
|
|
216 Size@Immediate[val:out]
|
|
217 {
|
|
218 out <- 4
|
|
219 }
|
|
220
|
|
221 Blueprint None
|
|
222 {
|
|
223 Dummy
|
|
224 }
|
|
225
|
|
226 None[:out]
|
|
227 {
|
|
228 out <- Build["None"]
|
|
229 }
|
|
230
|
|
231 In Memory?@None[none:out]
|
|
232 {
|
|
233 out <- No
|
|
234 }
|
|
235
|
|
236 Op ASM@None[none,func,regs,extra offset:out]
|
|
237 {
|
|
238 out <- ""
|
|
239 }
|
|
240
|
|
241 Size@None[none:out]
|
|
242 {
|
|
243 out <- 0
|
|
244 }
|
|
245
|
|
246 Blueprint Stack Location
|
|
247 {
|
|
248 Offset
|
|
249 Size
|
|
250 }
|
|
251
|
|
252 Stack Location[offset,size:out]
|
|
253 {
|
|
254 out <- [[Build["Stack Location"]]Offset <<[offset]]Size <<[size]
|
|
255 }
|
|
256
|
|
257 In Memory?@Stack Location[location:out]
|
|
258 {
|
|
259 out <- Yes
|
|
260 }
|
|
261
|
|
262 =@Stack Location[loc,other:out]
|
|
263 {
|
|
264 ,out <- If[[Type Of[loc]] = [Type Of[other]]]
|
|
265 {
|
|
266 out <- [[loc]Offset >>] = [[other]Offset >>]
|
|
267 }
|
|
268 }
|
|
269
|
|
270 Op ASM@Stack Location[loc,func,regs,extra offset:out]
|
|
271 {
|
|
272 offset <- [[[func]Stack Size >>] - [[loc]Offset >>]] - [[loc]Size >>]
|
|
273 If[[offset] > [0]]
|
|
274 {
|
|
275 toffset <- ["+"]Append[offset]
|
|
276 }{
|
|
277 toffset <- ""
|
|
278 }
|
|
279 out <- [["[esp"]Append[toffset]]Append["]"]
|
|
280 }
|
|
281
|
|
282 Size@Stack Location[loc:out]
|
|
283 {
|
|
284 out <- [loc]Size >>
|
|
285 }
|
|
286
|
|
287 Blueprint Pointer
|
|
288 {
|
|
289 Base
|
|
290 Offset
|
|
291 Target Size
|
|
292 }
|
|
293
|
|
294 Pointer[base,offset,size:out]
|
|
295 {
|
|
296 out <- [[[Build["Pointer"]]Base <<[base]]Offset <<[offset]]Target Size <<[size]
|
|
297 }
|
|
298
|
|
299 In Memory?@Pointer[location:out]
|
|
300 {
|
|
301 out <- Yes
|
|
302 }
|
|
303
|
|
304 =@Pointer[pointer,other:out]
|
|
305 {
|
|
306 ,out <- If[[Type Of[loc]] = [Type Of[other]]]
|
|
307 {
|
|
308 out <- [[loc]Storage >>] = [[other]Storage >>]
|
|
309 }
|
|
310 }
|
|
311
|
|
312 Op ASM@Pointer[pointer,func,regs,extra offset:out]
|
|
313 {
|
|
314 If[[Type Of[ [pointer]Offset >> ]] = ["None"]]
|
|
315 {
|
|
316 out <- [["["]Append[ [[pointer]Base >>]Op ASM[func,regs,extra offset] ]]Append["]"]
|
|
317 }{
|
|
318 out <- [[[["["
|
|
319 ]Append[ [[pointer]Base >>]Op ASM[func,regs,extra offset] ]
|
|
320 ]Append["+"]
|
|
321 ]Append[ [[pointer]Offset >>]Op ASM[func,regs,extra offset] ]
|
|
322 ]Append["]"]
|
|
323 }
|
|
324 }
|
|
325
|
|
326 Size@Pointer[pointer:out]
|
|
327 {
|
|
328 out <- [pointer]Target Size >>
|
|
329 }
|
|
330
|
|
331 Blueprint X86 Instruction
|
|
332 {
|
|
333 Name
|
|
334 Op1
|
|
335 Op2
|
|
336 Width
|
|
337 Extra Offset
|
|
338 }
|
|
339
|
|
340 X86 Instruction[name, op1, op2, width:out]
|
|
341 {
|
|
342 out <- [[[[[Build["X86 Instruction"]]Name << [name]]Op1 << [op1]]Op2 <<[op2]]Width <<[width]]Extra Offset <<[0]
|
|
343 }
|
|
344
|
|
345 CAppend[left,right:out]
|
|
346 {
|
|
347 If[[right] = [""]]
|
|
348 {
|
|
349 out <- ""
|
|
350 }{
|
|
351 out <- [left]Append[right]
|
|
352 }
|
|
353 }
|
|
354
|
|
355 Inst ASM@X86 Instruction[inst,func:out]
|
|
356 {
|
|
357 If[[[inst]Width >>] = [4]]
|
|
358 {
|
|
359 regs <- ("eax","ecx","edx","ebx","esi","edi","esp")
|
|
360 }{
|
|
361 If[[[inst]Width >>] = [2]]
|
|
362 {
|
|
363 regs <- ("ax","cx","dx","bx","si","di")
|
|
364 }{
|
|
365 regs <- ("al","cl","dl","bl","si","di")
|
|
366 }
|
|
367 }
|
|
368 out <- [[[inst]Name >>
|
|
369 ]Append[ [" "]CAppend[[[inst]Op1>>]Op ASM[func, regs, [inst]Extra Offset >>]] ]
|
|
370 ]Append[ [", "]CAppend[[[inst]Op2>>]Op ASM[func, regs, [inst]Extra Offset >>]] ]
|
|
371 }
|
|
372
|
|
373 Blueprint X86 Function
|
|
374 {
|
|
375 Name
|
|
376 Registers
|
|
377 Variables
|
|
378 Scratch
|
|
379 Need Save
|
|
380 Free Stack Locations
|
|
381 Stack Size
|
|
382 Param Size
|
|
383 Temp Stack
|
|
384 Convention
|
|
385 Instructions
|
|
386 }
|
|
387
|
|
388 X86 Function[name,params,convention:out]
|
|
389 {
|
|
390 [[[[[[[[[Build["X86 Function"]
|
|
391 ]Name << [name]
|
|
392 ]Registers << [Registers[("eax","ecx","edx","ebx","esi","edi"), (0,1,2,3,4,5), (0,1,2,3,4,5), (3,4,5), 4]]
|
|
393 ]Variables <<[New@Dictionary[]]
|
|
394 ]Need Save <<[()]
|
|
395 ]Free Stack Locations <<[()]
|
|
396 ]Stack Size <<[0]
|
|
397 ]Instructions <<[()]
|
|
398 ]Convention <<[convention]
|
|
399 ]Alloc Params[params, convention]
|
|
400 {
|
|
401 out <- [~]Param Size <<[ [~]Stack Size >> ]
|
|
402 }
|
|
403 }
|
|
404
|
|
405 Pointer Size@X86 Function[func:out]
|
|
406 {
|
|
407 out <- 4
|
|
408 }
|
|
409
|
|
410 Param Helper@X86 Function[func, param:out]
|
|
411 {
|
|
412 ,loc <- [func]Allocate Stack[4]
|
|
413 {
|
|
414 out <- [~]Variables << [ [[~]Variables >>]Set[param, loc] ]
|
|
415 }
|
|
416 }
|
|
417
|
|
418 Alloc Params@X86 Function[func,params,convention:out]
|
|
419 {
|
|
420 If[[convention] = ["fastcall"]]
|
|
421 {
|
|
422 [params]Index[0]
|
|
423 {
|
|
424 next func <- [[func]Registers <<[ [[func]Registers >>]Available? <<[ [[[func]Registers >>]Available? >>]Set[1, No] ]]
|
|
425 ]Variables <<[ [[func]Variables >>]Set[~, Register[1,4]] ]
|
|
426 [params]Index[1]
|
|
427 {
|
|
428 next func2 <- [[next func]Registers <<[ [[next func]Registers >>]Available? <<[ [[[next func]Registers >>]Available? >>]Set[2, No] ]]
|
|
429 ]Variables <<[ [[next func]Variables >>]Set[~, Register[2,4]] ]
|
|
430 [params]Index[2]
|
|
431 {
|
|
432 out <- _Fold[params, 2, next func2, "Param Helper"]
|
|
433 }{
|
|
434 out <- Val[next func2]
|
|
435 }
|
|
436 }{
|
|
437 out <- Val[next func]
|
|
438 }
|
|
439 }{
|
|
440 out <- func
|
|
441 }
|
|
442 }{
|
|
443 out <- Fold["Param Helper", func, params]
|
|
444 }
|
|
445 }
|
|
446
|
|
447 Add Instruction@X86 Function[func, inst:out]
|
|
448 {
|
|
449 out <- [func]Instructions << [ [[func]Instructions >>]Append[ [inst]Extra Offset <<[[func]Temp Stack >>] ] ]
|
|
450 }
|
|
451
|
|
452 Allocate Stack@X86 Function[func,size:func out,out]
|
|
453 {
|
|
454 out <- Stack Location[[func]Stack Size >>, size]
|
|
455 func out <- [func]Stack Size <<[ [[func]Stack Size >>]+[size] ]
|
|
456 }
|
|
457
|
|
458 Allocate Var@X86 Function[func,name,size,type:out func,out]
|
|
459 {
|
|
460 out func, out <- Processor Allocate[func,name,size,type]
|
|
461 }
|
|
462
|
|
463 Resolve@X86 Function[func,op:out,out func]
|
|
464 {
|
|
465 If[[Type Of[op]] = ["String"]]
|
|
466 {
|
|
467 out <- [[func]Variables >>]Index[op]
|
|
468 }{
|
|
469 out <- op
|
|
470 }
|
|
471 }
|
|
472
|
|
473 Allocate Scratch@X86 Function[func,size:out func,scratch]
|
|
474 {
|
|
475 out func,scratch <- Processor Reg[func,"data"] {} {}
|
|
476 {
|
|
477 //FIXME: need to use a reg that's not involved in the current op
|
|
478 //FIXME: Also, might need two scratch regs and both might be in use
|
|
479 ,stack inc <- [func]Save Reg[0]
|
|
480 {
|
|
481 out func <- [~]Scratch << [ [[~]Scratch >>]Set[0, Yes] ]
|
|
482 }
|
|
483 }
|
|
484 }
|
|
485
|
|
486 Free Scratch@X86 Function[func,scratch:out func]
|
|
487 {
|
|
488 [[func]Scratch >>]Index[scratch]
|
|
489 {
|
|
490 [func]Restore Reg[scratch]
|
|
491 {
|
|
492 out func <- [~]Scratch << [ [[~]Scratch >>]Remove[scratch] ]
|
|
493 }
|
|
494 }{
|
|
495 out func <- Processor Free Reg[func, scratch]
|
|
496 }
|
|
497 If[[scratch]Index[1]]
|
|
498 {
|
|
499
|
|
500 }{
|
|
501
|
|
502 }
|
|
503 }
|
|
504
|
|
505 Classify Op@X86 Function[func,op:class]
|
|
506 {
|
|
507 If[[op]In Memory?]
|
|
508 {
|
|
509 If[[Type Of[op]] = ["Pointer"]]
|
|
510 {
|
|
511 If[[[[op]Base >>]In Memory?] Or [[[op]Offset >>]In Memory?]]
|
|
512 {
|
|
513 class <- "u"
|
|
514 }{
|
|
515 class <- "m"
|
|
516 }
|
|
517 }{
|
|
518 class <- "m"
|
|
519 }
|
|
520 }{
|
|
521 class <- "r"
|
|
522 }
|
|
523 }
|
|
524
|
|
525 RegMem2Op@X86 Function[func,dest,notdest,op,size:out]
|
|
526 {
|
|
527 out <- [func]Add Instruction[X86 Instruction[op, dest, notdest, size]]
|
|
528 }
|
|
529
|
|
530 MemPointer2Op@X86 Function[func,dest,notdest,op,size:out]
|
|
531 {
|
|
532 ,scratch <- [func]Allocate Scratch[size]
|
|
533 {
|
|
534 out <- [[[~]Fetch[notdest,scratch]
|
|
535 ]Add Instruction[X86 Instruction[op, dest, scratch, size]]
|
|
536 ]Free Scratch[scratch]
|
|
537 }
|
|
538 }
|
|
539
|
|
540 //Make sure to map this to both r, (m or r) -> m and r, (m or r) -> r
|
|
541 RegMemToNotPointer@X86 Function[func,source1,source2,dest,op,size:out]
|
|
542 {
|
|
543 out <- [[func]Move[source2,dest]
|
|
544 ]Add Instruction[X86 Instruction[op, dest, source1, size]]
|
|
545 }
|
|
546
|
|
547 RegMemToPointer@X86 Function[func,source1,source2,dest,op,size:out]
|
|
548 {
|
|
549 ,scratch <- [func]Allocate Scratch[size]
|
|
550 {
|
|
551 spointer <- Pointer[scratch, None[], size]
|
|
552 out <- [[[[~]Calculate Address[dest, scratch]
|
|
553 ]Move[source2, spointer]
|
|
554 ]Add Instruction[X86 Instruction[op, spointer, source1, size]]
|
|
555 ]Free Scratch[scratch]
|
|
556 }
|
|
557 }
|
|
558
|
|
559 RegPointerToMem@X86 Function[func,source1,source2,dest,op,size:out]
|
|
560 {
|
|
561 ,scratch <- [func]Allocate Scratch[size]
|
|
562 {
|
|
563 spointer <- Pointer[scratch, None[], size]
|
|
564 out <- [[[[~]Calculate Address[source2, scratch]
|
|
565 ]Move[spointer, dest]
|
|
566 ]Add Instruction[X86 Instruction[op, dest, source1, size]]
|
|
567 ]Free Scratch[scratch]
|
|
568 }
|
|
569 }
|
|
570
|
|
571 RegPointerReg2Op@X86 Function[func,dest,notdest,op,size:out]
|
|
572 {
|
|
573 ,scratch <- [func]Allocate Scratch[size]
|
|
574 {
|
|
575 spointer <- Pointer[scratch, None[], size]
|
|
576 out <- [[[~]Calculate Address[notdest, scratch]
|
|
577 ]Add Instruction[X86 Instruction[op, dest, spointer, size]]
|
|
578 ]Free Scratch[scratch]
|
|
579 }
|
|
580 }
|
|
581
|
|
582 RegPointerPointer2Op@X86 Function[func,dest,notdest,op,size:out]
|
|
583 {
|
|
584 ,scratch <- [func]Allocate Scratch[size]
|
|
585 {
|
|
586 spointer <- Pointer[scratch, None[], size]
|
|
587 out <- [[[~]Calculate Address[dest, scratch]
|
|
588 ]Add Instruction[X86 Instruction[op, spointer, notdest, size]]
|
|
589 ]Free Scratch[scratch]
|
|
590 }
|
|
591 }
|
|
592
|
|
593 RegPointerToPointer@X86 Function[func,source1,source2,dest,op,size:out]
|
|
594 {
|
|
595 ,scratch <- [func]Allocate Scratch[size]
|
|
596 {
|
|
597 spointer <- Pointer[scratch, None[], size]
|
|
598 ,scratch2 <- [~]Allocate Scratch[size]
|
|
599 {
|
|
600 spointer2 <- Pointer[scratch2, None[], size]
|
|
601 out <- [[[[[[~]Calculate Address[source2, scratch]
|
|
602 ]Calculate Address[dest, scratch2]
|
|
603 ]Move[spointer2, spointer]
|
|
604 ]Add Instruction[X86 Instruction[op, spointer2, source1, size]]
|
|
605 ]Free Scratch[scratch2]
|
|
606 ]Free Scratch[scratch]
|
|
607 }
|
|
608 }
|
|
609 }
|
|
610
|
|
611 //If source1, source2 and dest are all pointers with register offsets, allocating a scratch register could
|
|
612 //become a problem unless I let ebp be used as a scratch register. Should be doable as long as thread local
|
|
613 //variables properly report ebp as a used register. Alternatively, one register could be reserved for scratch
|
|
614 //usage
|
|
615 MemPointerToMem@X86 Function[func,source1,source2,dest,op,size:out]
|
|
616 {
|
|
617 ,scratch <- [func]Allocate Scratch[size]
|
|
618 {
|
|
619 out <- [[[[~]Fetch[source2, scratch]
|
|
620 ]Add Instruction[X86 Instruction[op, scratch, source1, size]]
|
|
621 ]Move[scratch, dest]
|
|
622 ]Free Scratch[scratch]
|
|
623 }
|
|
624 }
|
|
625
|
|
626 MemPointerToPointer@X86 Function[func,source1,source2,dest,op,size:out]
|
|
627 {
|
|
628 ,scratch <- [func]Allocate Scratch[size]
|
|
629 {
|
|
630 ,scratch2 <- [~]Allocate Scratch[size]
|
|
631 {
|
|
632 spointer2 <- Pointer[scratch2, None[], size]
|
|
633 out <- [[[[[[~]Fetch[source2, scratch]
|
|
634 ]Add Instruction[X86 Instruction[op, scratch, source1, size]]
|
|
635 ]Calculate Address[dest, scratch2]
|
|
636 ]Move[scratch, spointer2]
|
|
637 ]Free Scratch[scratch2]
|
|
638 ]Free Scratch[scratch]
|
|
639 }
|
|
640 }
|
|
641 }
|
|
642
|
|
643 //This does almost the same thing as RegMemToNotPointer, depending on how I do the pattern matching I could maybe combine them
|
|
644 PointerMemToReg@X86 Function[func,source1,source2,dest,op,size:out]
|
|
645 {
|
|
646 out <- [[func]Fetch[source1,dest]
|
|
647 ]Add Instruction[X86 Instruction[op, dest, source2, size]]
|
|
648 }
|
|
649
|
|
650 PointerPointer2Op@X86 Function[func,dest,notdest,op,size:out]
|
|
651 {
|
|
652 ,scratch <- [func]Allocate Scratch[size]
|
|
653 {
|
|
654 spointer <- Pointer[scratch, None[], size]
|
|
655 ,scratch2 <- [~]Allocate Scratch[size]
|
|
656 {
|
|
657 out <- [[[[[[[~]Calculate Address[dest, scratch]
|
|
658 ]Fetch[notdest, scratch2]
|
|
659 ]Add Instruction[X86 Instruction[op, scratch, scratch2, size]]
|
|
660 ]Calculate Address[dest, scratch2]
|
|
661 ]Move[scratch, spointer2]
|
|
662 ]Free Scratch[scratch2]
|
|
663 ]Free Scratch[scratch]
|
|
664 }
|
|
665 }
|
|
666 }
|
|
667
|
|
668 PointerPointerToPointer@X86 Function[func,source1,source2,dest,op,size:out]
|
|
669 {
|
|
670 ,scratch <- [func]Allocate Scratch[size]
|
|
671 {
|
|
672 ,scratch2 <- [~]Allocate Scratch[size]
|
|
673 {
|
|
674 spointer2 <- Pointer[scratch2, None[], size]
|
|
675 out <- [[[[[[[~]Fetch[source1, scratch]
|
|
676 ]Calculate Address[source2, scratch2]
|
|
677 ]Add Instruction[X86 Instruction[op, scratch, spointer2, size]]
|
|
678 ]Calculate Address[dest, scratch2]
|
|
679 ]Move[scratch, spointer2]
|
|
680 ]Free Scratch[scratch2]
|
|
681 ]Free Scratch[scratch]
|
|
682 }
|
|
683 }
|
|
684 }
|
|
685
|
|
686 PointerPointerToMem@X86 Function[func,source1,souce2,dest,op,size:out]
|
|
687 {
|
|
688 ,scratch <- [func]Allocate Scratch[size]
|
|
689 {
|
|
690 spointer <- Pointer[scratch, None[], size]
|
|
691 out <- [[[[[~]Calculate Address[source1, scratch]
|
|
692 ]Move[dest, spointer]
|
|
693 ]Fetch[source2, scratch]
|
|
694 ]Add Instruction[X86 Instruction[op, dest, scratch, size]]
|
|
695 ]Free Scratch[scratch]
|
|
696 }
|
|
697 }
|
|
698
|
|
699 PointerPointerToReg@X86 Function[func,source1,souce2,dest,op,size:out]
|
|
700 {
|
|
701 ,scratch <- [func]Allocate Scratch[size]
|
|
702 {
|
|
703 spointer <- Pointer[scratch, None[], size]
|
|
704 out <- [[[[~]Fetch[source1, dest]
|
|
705 ]Calculate Address[source2, scratch]
|
|
706 ]Add Instruction[X86 Instruction[op, dest, scratch, size]]
|
|
707 ]Free Scratch[scratch]
|
|
708 }
|
|
709 }
|
|
710
|
|
711 2Op Associative@X86 Function[func,psource1,psource2,pdest,name:out func]
|
|
712 {
|
|
713 source1 <- [func]Resolve[psource1]
|
|
714 source2 <- [func]Resolve[psource2]
|
|
715 dest <- [func]Resolve[pdest]
|
|
716 dest class <- [func]Classify Op[dest]
|
|
717 width <- Min[Min[Min[[source1]Size,[source2]Size], [dest]Size], 4]
|
|
718 swapper <- (1,0)
|
|
719 sources <- [[()]Append[source1]Append[source2]
|
|
720 [sources]Find[dest]
|
|
721 {
|
|
722 source <- [swapper]Index[~]
|
|
723 source class <- [func]Classify Op[source]
|
|
724 If[[dest class] = ["u"]]
|
|
725 {
|
|
726 If[[source class] = ["r"]]
|
|
727 {
|
|
728 out func <- [func]RegPointerPointer2Op[dest,source,name,width]
|
|
729 }{
|
|
730 out func <- [func]PointerPointer2Op[dest,source,name,width]
|
|
731 }
|
|
732 }{
|
|
733 If[[dest class] = ["r"]]
|
|
734 {
|
|
735 If[[source class] = ["u"]]
|
|
736 {
|
|
737 out func <- [func]RegPointerReg2Op[dest,source,name,width]
|
|
738 }{
|
|
739 out func <- [func]RegMem2Op[dest,source,name,width]
|
|
740 }
|
|
741 }{
|
|
742 If[[source class] = ["r"]]
|
|
743 {
|
|
744 out func <- [func]RegMem2Op[dest,source,name,width]
|
|
745 }{
|
|
746 out func <- [func]MemPointer2Op[dest,source,name,width]
|
|
747 }
|
|
748 }
|
|
749 }
|
|
750 }{
|
|
751 sclasses <- Map[sources, ["Classify Op"]Set Input[0, func]]
|
|
752 first <- [sources]Index[found index]
|
|
753 other index <- [swapper]Index[found index]
|
|
754 other <- [sources]Index[other index]
|
|
755 other class <- [sclasses]Index[other index]
|
|
756 found index <- [sclasses]Find["r"]
|
|
757 {
|
|
758 If[[other class] = ["u"]]
|
|
759 {
|
|
760 If[[dest class] = ["m"]]
|
|
761 {
|
|
762 out func <- [func]RegPointerToMem[first,other,dest,name,width]
|
|
763 }{
|
|
764 If[[dest class] = ["u"]]
|
|
765 {
|
|
766 out func <- [func]RegPointerToPointer[first,other,dest,name,width]
|
|
767 }{
|
|
768 out func <- [func]PointerMemToReg[other,first,dest,name,width]
|
|
769 }
|
|
770 }
|
|
771 }{
|
|
772 If[[dest class] = ["u"]]
|
|
773 {
|
|
774 out func <- [func]RegMemToPointer[first,other,dest,name,width]
|
|
775 }{
|
|
776 out func <- [func]RegMemToNotPointer[first,other,dest,name,width]
|
|
777 }
|
|
778 }
|
|
779 }{
|
|
780 found index <- [sclasses]Find["m"]
|
|
781 {
|
|
782 If[[dest class] = ["r"]]
|
|
783 {
|
|
784 out func <- [func]PointerMemToReg[other,first,dest,name,width]
|
|
785 }{
|
|
786 If[[dest class] = ["m"]]
|
|
787 {
|
|
788 out func <- [func]MemPointerToMem[first,other,dest,name,width]
|
|
789 }{
|
|
790 out func <- [func]MemPointerToPointer[first,other,dest,name,width]
|
|
791 }
|
|
792 }
|
|
793 }{
|
|
794 If[[dest class] = ["r"]]
|
|
795 {
|
|
796 out func <- [func]PointerPointerToReg[first,other,dest,name,width]
|
|
797 }{
|
|
798 If[[dest class] = ["m"]]
|
|
799 {
|
|
800 out func <- [func]PointerPointerToMem[first,other,dest,name,width]
|
|
801 }{
|
|
802 out func <- [func]PointerPointerToPointer[first,other,dest,name,width]
|
|
803 }
|
|
804 }
|
|
805 }
|
|
806 }
|
|
807 }
|
|
808 }
|
|
809
|
|
810 2Op@X86 Function[func,psource1,psource2,pdest,name:out func]
|
|
811 {
|
|
812 source1 <- [func]Resolve[psource1]
|
|
813 source2 <- [func]Resolve[psource2]
|
|
814 dest <- [func]Resolve[pdest]
|
|
815 width <- Min[Min[Min[[source1]Size,[source2]Size], [dest]Size], 4]
|
|
816 If[[source1] = [dest]]
|
|
817 {
|
|
818 If[[[source1]In Memory?] And [[source2]In Memory?]]
|
|
819 {
|
|
820 ,scratch, stack inc <- [func]Allocate Scratch[width]
|
|
821 {
|
|
822 out func <- [[[~]Add Instruction[X86 Instruction["mov", [scratch]Index[0], source2, width, stack inc]]
|
|
823 ]Add Instruction[X86 Instruction[name, source1, [scratch]Index[0], width, stack inc]]
|
|
824 ]Free Scratch[scratch]
|
|
825 }
|
|
826 }{
|
|
827 out func <- [func]Add Instruction[X86 Instruction[name, dest, source2, width, 0]]
|
|
828 }
|
|
829 }{
|
|
830 If[[dest]In Memory?]
|
|
831 {
|
|
832 If[[source2]In Memory?]
|
|
833 {
|
|
834 ,scratch, stack inc <- [func]Allocate Scratch[width]
|
|
835 {
|
|
836 out func <- [[[[~]Add Instruction[X86 Instruction["mov", [scratch]Index[0], source1, width, stack inc]]
|
|
837 ]Add Instruction[X86 Instruction[name, [scratch]Index[0], source2, width, stack inc]]
|
|
838 ]Add Instruction[X86 Instruction["mov", dest, [scratch]Index[0], width, stack inc]]
|
|
839 ]Free Scratch[scratch]
|
|
840 }
|
|
841 }{
|
|
842 out func <- [[func]Move[source1,dest]
|
|
843 ]Add Instruction[X86 Instruction[name, dest, source2, width, 0]]
|
|
844 }
|
|
845 }{
|
|
846 out func <- [[func]Move[source1,dest]
|
|
847 ]Add Instruction[X86 Instruction[name, dest, source2, width, 0]]
|
|
848 }
|
|
849 }
|
|
850 }
|
|
851
|
|
852 Add@X86 Function[func,source1,source2,dest:out func]
|
|
853 {
|
|
854 out func <- [func]2Op Associative[source1,source2,dest,"add"]
|
|
855 }
|
|
856
|
|
857 Sub@X86 Function[func,source1,source2,dest:out func]
|
|
858 {
|
|
859 out func <- [func]2Op[source1,source2,dest,"sub"]
|
|
860 }
|
|
861
|
|
862 Move@X86 Function[func,psource,pdest:out func]
|
|
863 {
|
|
864 source <- [func]Resolve[psource]
|
|
865 dest <- [func]Resolve[pdest]
|
|
866 out func <- [func]Add Instruction[X86 Instruction["mov", dest, source, 4]]
|
|
867 }
|
|
868
|
|
869 Instruction ASM[current,instruction,func:out]
|
|
870 {
|
|
871 out <- [[[current]Append["\t"]]Append[ [instruction]Inst ASM[func] ]]Append["\n"]
|
|
872 }
|
|
873
|
|
874 Save Reg@X86 Function[func,reg:out]
|
|
875 {
|
|
876 out <- [[func]Add Instruction[X86 Instruction["push", Register[reg, 4], None[], 4]]
|
|
877 ]Temp Stack << [ [[func]Temp Stack >>]+[4] ]
|
|
878 }
|
|
879
|
|
880 Prolog Save@X86 Function[func,junk,reg:out]
|
|
881 {
|
|
882 out <- [[func]Add Instruction[X86 Instruction["push", Register[reg, 4], None[], 4]]
|
|
883 ]Stack Size << [ [[func]Stack Size >>]+[4] ]
|
|
884 }
|
|
885
|
|
886 Restore Reg@X86 Function[func,reg:out]
|
|
887 {
|
|
888 out <- [[func]Add Instruction[X86 Instruction["pop", Register[reg, 4], None[], 4]]
|
|
889 ]Temp Stack << [ [[func]Temp Stack >>]-[4] ]
|
|
890 }
|
|
891
|
|
892 Epilogue Restore@X86 Function[func,junk,reg:out]
|
|
893 {
|
|
894 out <- [func]Add Instruction[X86 Instruction["pop", Register[reg, 4], None[], 4]]
|
|
895 }
|
|
896
|
|
897 Finalize@X86 Function[func:out]
|
|
898 {
|
|
899 alloc stack <- [[func]Stack Size >>] - [[func]Param Size >>]
|
|
900
|
|
901 oldstream <- [func]Instructions >>
|
|
902
|
|
903 If[[alloc stack] > [0]]
|
|
904 {
|
|
905 start <- [()]Append[X86 Instruction["sub", Register[6, 4],Immediate[alloc stack], Register[6, 4], 4], func]
|
|
906 }{
|
|
907 start <- ()
|
|
908 }
|
|
909
|
|
910 If[[[func]Convention >>] = ["cdecl"]]
|
|
911 {
|
|
912 If[ [alloc stack] > [0] ]
|
|
913 {
|
|
914 retparam <- Immediate[alloc stack]
|
|
915 }{
|
|
916 retparam <- None[]
|
|
917 }
|
|
918 }{
|
|
919 retparam <- Immediate[[func]Stack Size >>]
|
|
920 }
|
|
921
|
|
922 [[func]Need Save >>]First
|
|
923 {
|
|
924 prolog <- Fold["Prolog Save", [func]Instructions << [start], [func]Need Save >>]
|
|
925 out <- [Reverse Fold["Epilogue Restore", body, [func]Need Save >>]]Add Instruction[X86 Instruction["ret", retparam, None[], 4]]
|
|
926 }{
|
|
927 prolog <- [func]Instructions <<[start]
|
|
928 out <- [body]Add Instruction[X86 Instruction["ret", retparam, None[], 4]]
|
|
929 }
|
|
930
|
|
931 body <- Fold["Add Instruction", prolog, oldstream]
|
|
932 }
|
|
933
|
|
934 Text@X86 Function[func:out]
|
|
935 {
|
|
936 name line <- [Escape Rhope Name[[func]Name >>]
|
|
937 ]Append[":\n"]
|
|
938
|
|
939 out <- Fold[["Instruction ASM"]Set Input[2, func], name line, [func]Instructions >>]
|
|
940 }
|