Mercurial > repos > rhope
comparison genasm.rhope @ 2:73e978d590c7
Adding WIP compiler code
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Wed, 29 Apr 2009 02:58:03 -0400 |
parents | |
children | 31f8182f3433 |
comparison
equal
deleted
inserted
replaced
1:b3f71490858c | 2:73e978d590c7 |
---|---|
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 } |