Mercurial > repos > rhope
annotate genasm.rhope @ 75:0083b2f7b3c7
Partially working implementation of List. Modified build scripts to allow use of other compilers. Fixed some bugs involving method implementations on different types returning different numbers of outputs. Added Fold to the 'builtins' in the comipler.
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 06 Jul 2010 07:52:59 -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 } |