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