Mercurial > repos > tabletprog
comparison modules/il.tp @ 200:49bca6487178
Add a save instruction around calls if there are caller-saved registers live at call-time. Fix to2Op for skipIf and save instructions.
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 27 Aug 2013 23:02:19 -0700 |
parents | 7856f0916549 |
children | 56b2100d9fff |
comparison
equal
deleted
inserted
replaced
199:3b13ced3b562 | 200:49bca6487178 |
---|---|
55 _ina recordUsage: tracker at: 0 | address withSize: _size | 55 _ina recordUsage: tracker at: 0 | address withSize: _size |
56 } | 56 } |
57 _inb recordUsage: tracker at: 0 | address withSize: _size | 57 _inb recordUsage: tracker at: 0 | address withSize: _size |
58 _out recordUsage: tracker at: 1 | address withSize: _size | 58 _out recordUsage: tracker at: 1 | address withSize: _size |
59 } | 59 } |
60 assignRegs:withSource <- :assignments :regSrc { | 60 assignRegs:at:withSource:andUsage <- :assignments :at :regSrc :usage { |
61 newa <- if: (not: (_ina isInteger?)) { | 61 newa <- if: (not: (_ina isInteger?)) { |
62 _ina assign: assignments withSource: regSrc | 62 _ina assign: assignments withSource: regSrc |
63 } else: { _ina } | 63 } else: { _ina } |
64 newb <- _inb assign: assignments withSource: regSrc | 64 newb <- _inb assign: assignments withSource: regSrc |
65 newout <- _out assign: assignments withSource: regSrc | 65 newout <- _out assign: assignments withSource: regSrc |
80 if: (not: (_in isInteger?)) { | 80 if: (not: (_in isInteger?)) { |
81 _in recordUsage: tracker at: 0 | address withSize: _size | 81 _in recordUsage: tracker at: 0 | address withSize: _size |
82 } | 82 } |
83 _out recordUsage: tracker at: 1 | address withSize: _size | 83 _out recordUsage: tracker at: 1 | address withSize: _size |
84 } | 84 } |
85 assignRegs:withSource <- :assignments :regSrc { | 85 assignRegs:at:withSource:andUsage <- :assignments :at :regSrc :usage { |
86 newin <- if: (not: (_in isInteger?)) { | 86 newin <- if: (not: (_in isInteger?)) { |
87 _in assign: assignments withSource: regSrc | 87 _in assign: assignments withSource: regSrc |
88 } else: { _in } | 88 } else: { _in } |
89 newout <- _out assign: assignments withSource: regSrc | 89 newout <- _out assign: assignments withSource: regSrc |
90 op2: _opcode in: newin out: newout size: _size | 90 op2: _opcode in: newin out: newout size: _size |
102 recordUsage:at <- :tracker :address { | 102 recordUsage:at <- :tracker :address { |
103 if: (not: (_arg isInteger?)) { | 103 if: (not: (_arg isInteger?)) { |
104 _arg recordUsage: tracker at: address withSize: _size | 104 _arg recordUsage: tracker at: address withSize: _size |
105 } | 105 } |
106 } | 106 } |
107 assignRegs:withSource <- :assignments :regSrc { | 107 assignRegs:at:withSource:andUsage <- :assignments :at :regSrc :usage { |
108 newarg <- if: (not: (_arg isInteger?)) { | 108 newarg <- if: (not: (_arg isInteger?)) { |
109 _arg assign: assignments withSource: regSrc | 109 _arg assign: assignments withSource: regSrc |
110 } else: { _arg } | 110 } else: { _arg } |
111 op1: _opcode arg: newarg size: _size | 111 op1: _opcode arg: newarg size: _size |
112 } | 112 } |
348 foreach: _args :_ arg { | 348 foreach: _args :_ arg { |
349 //TODO: have some mechanism for properly expressing sizes of arguments | 349 //TODO: have some mechanism for properly expressing sizes of arguments |
350 arg recordUsage: tracker at: address withSize: q | 350 arg recordUsage: tracker at: address withSize: q |
351 } | 351 } |
352 } | 352 } |
353 assignRegs:withSource <- :assignments :regSrc { | 353 assignRegs:at:withSource:andUsage <- :assignments :address :regSrc :usage { |
354 newtarget <- if: (_target isString?) { _target } else: { | 354 newtarget <- if: (_target isString?) { _target } else: { |
355 _target assign: assignments withSource: regSrc | 355 _target assign: assignments withSource: regSrc |
356 } | 356 } |
357 newargs <- _args map: :arg { | 357 newargs <- _args map: :arg { |
358 if: (arg isInteger?) { arg } else: { | 358 if: (arg isInteger?) { arg } else: { |
359 arg assign: assignments withSource: regSrc | 359 arg assign: assignments withSource: regSrc |
360 } | 360 } |
361 } | 361 } |
362 //TODO: Save caller-save regs if necessary | 362 newcall <- call: newtarget withArgs: newargs |
363 //TODO: Add instructions for moving arguments to proper regs/stack locations | 363 regSrc returnAll |
364 call: newtarget withArgs: newargs | 364 raddress <- address reverse |
365 foreach: (usage liveArgsAt: raddress) :_ arg { | |
366 regSrc allocArg: (arg num) | |
367 } | |
368 foreach: (usage liveRegsAt: raddress) :_ reg { | |
369 regSrc allocSpecific: (assignments get: reg) | |
370 } | |
371 tosave <- regSrc needSaveForCall | |
372 if: (tosave length) > 0 { | |
373 save: tosave #[newcall] | |
374 } else: { | |
375 newcall | |
376 } | |
365 } | 377 } |
366 } | 378 } |
367 } | 379 } |
368 | 380 |
369 return <- :val size { | 381 return <- :val size { |
386 recordUsage:at <- :tracker :address { | 398 recordUsage:at <- :tracker :address { |
387 foreach: _toskip :idx inst { | 399 foreach: _toskip :idx inst { |
388 inst recordUsage: tracker at: idx | address | 400 inst recordUsage: tracker at: idx | address |
389 } | 401 } |
390 } | 402 } |
391 assignRegs:withSource <- :assignments :regSrc { | 403 assignRegs:at:withSource:andUsage <- :assignments :address :regSrc :usage { |
392 newskip <- _toskip map: :inst { | 404 newskip <- #[] |
393 inst assignRegs: assignments withSource: regSrc | 405 foreach: _toskip :idx inst { |
406 newskip append: (inst assignRegs: assignments at: idx | address withSource: regSrc andUsage: usage) | |
394 } | 407 } |
395 skipIf: _cond newskip | 408 skipIf: _cond newskip |
409 } | |
410 to2OpInst <- { | |
411 skipIf: _cond (to2Op: _toskip) | |
396 } | 412 } |
397 } | 413 } |
398 } | 414 } |
399 save <- :regs :scope{ | 415 save <- :regs :scope{ |
400 #{ | 416 #{ |
405 block <- scope join: "\n\t" | 421 block <- scope join: "\n\t" |
406 if: (scope length) > 0 { | 422 if: (scope length) > 0 { |
407 block <- "\n\t" . block . "\n" | 423 block <- "\n\t" . block . "\n" |
408 } | 424 } |
409 name . " " . (regs join: " ") . " {" . block . "}" | 425 name . " " . (regs join: " ") . " {" . block . "}" |
426 } | |
427 to2OpInst <- { | |
428 save: regs (to2Op: scope) | |
410 } | 429 } |
411 } | 430 } |
412 } | 431 } |
413 | 432 |
414 allocRegs:withSource <- :instarr:regSrc { | 433 allocRegs:withSource <- :instarr:regSrc { |
433 } | 452 } |
434 } | 453 } |
435 } | 454 } |
436 | 455 |
437 _maxUses <- 0 | 456 _maxUses <- 0 |
457 liveFrom:to <- :regs :from :to { | |
458 live <- #[] | |
459 foreach: regs :reg usage { | |
460 if: ((usage lastUsage) addrGreatEq: from) && ((usage firstUsage) addrLessEq: to) { | |
461 live append: reg | |
462 } | |
463 } | |
464 live | |
465 } | |
438 regUsage <- #{ | 466 regUsage <- #{ |
439 reg:usedAt:withSize <- :reg :address :size { | 467 reg:usedAt:withSize <- :reg :address :size { |
440 raddress <- address reverse | 468 raddress <- address reverse |
441 usage <- _regMap get: reg elseSet: { | 469 usage <- _regMap get: reg elseSet: { |
442 _usageTracker: raddress | 470 _usageTracker: raddress |
451 usage <- _argMap get: arg elseSet: { | 479 usage <- _argMap get: arg elseSet: { |
452 _usageTracker: [0 0] | 480 _usageTracker: [0 0] |
453 } | 481 } |
454 usage usedAt: raddress withSize: size | 482 usage usedAt: raddress withSize: size |
455 } | 483 } |
484 | |
485 liveRegsAt <- :address { | |
486 _regMap liveFrom: address to: address | |
487 } | |
488 liveArgsAt <- :address { | |
489 _argMap liveFrom: address to: address | |
490 } | |
491 | |
456 print <- { | 492 print <- { |
457 foreach: _regMap :reg usage { | 493 foreach: _regMap :reg usage { |
458 print: (string: reg) . " | " . (string: usage) . "\n" | 494 print: (string: reg) . " | " . (string: usage) . "\n" |
459 } | 495 } |
460 foreach: _argMap :arg usage { | 496 foreach: _argMap :arg usage { |
499 } | 535 } |
500 } | 536 } |
501 greateq | 537 greateq |
502 } | 538 } |
503 | 539 |
504 liveFrom:to <- :regs :from :to { | |
505 live <- #[] | |
506 foreach: regs :reg usage { | |
507 if: ((usage lastUsage) addrGreatEq: from) && ((usage firstUsage) addrLessEq: to) { | |
508 live append: reg | |
509 } | |
510 } | |
511 live | |
512 } | |
513 | |
514 _assignments <- dict linear | 540 _assignments <- dict linear |
515 curuses <- _maxUses | 541 curuses <- _maxUses |
516 while: { curuses > 0 && (_assignments length) < (_regMap length) } do: { | 542 while: { curuses > 0 && (_assignments length) < (_regMap length) } do: { |
517 foreach: _regMap :reg usage { | 543 foreach: _regMap :reg usage { |
518 if: (usage useCount) = curuses { | 544 if: (usage useCount) = curuses { |
538 print: "\n\nAssignments:\n\n" | 564 print: "\n\nAssignments:\n\n" |
539 foreach: _assignments :reg assign { | 565 foreach: _assignments :reg assign { |
540 print: (string: reg) . " = " . assign . "\n" | 566 print: (string: reg) . " = " . assign . "\n" |
541 } | 567 } |
542 | 568 |
543 withassign <- map: instarr :inst { | 569 withassign <- #[] |
544 inst assignRegs: _assignments withSource: regSrc | 570 foreach: instarr :idx inst { |
571 withassign append: (inst assignRegs: _assignments at: [idx] withSource: regSrc andUsage: regUsage) | |
545 } | 572 } |
546 psave <- regSrc needSaveProlog | 573 psave <- regSrc needSaveProlog |
547 print: "Regs that need saving in prolog: " . (psave join: ",") . "\n" | |
548 if: (psave length) > 0 { | 574 if: (psave length) > 0 { |
549 withassign <- #[save: psave withassign] | 575 withassign <- #[save: psave withassign] |
550 } | 576 } |
551 withassign | 577 withassign |
552 } | 578 } |
571 if: (inst in) != (inst out) { | 597 if: (inst in) != (inst out) { |
572 newarr append: (mov: (inst in) (inst out) (inst size)) | 598 newarr append: (mov: (inst in) (inst out) (inst size)) |
573 } | 599 } |
574 newarr append: (op1: (inst opcode) val: (inst out) size: (inst size)) | 600 newarr append: (op1: (inst opcode) val: (inst out) size: (inst size)) |
575 } else: { | 601 } else: { |
576 newarr append: inst | 602 if: (inst opcode) = _skipif || (inst opcode) = _save { |
603 newarr append: (inst to2OpInst) | |
604 } else: { | |
605 newarr append: inst | |
606 } | |
577 } | 607 } |
578 } | 608 } |
579 } | 609 } |
580 } | 610 } |
581 | 611 |
596 foreach: fib :idx inst { | 626 foreach: fib :idx inst { |
597 print: (string: inst) . "\n" | 627 print: (string: inst) . "\n" |
598 } | 628 } |
599 print: "\n\nUsage:\n\n" | 629 print: "\n\nUsage:\n\n" |
600 fiba <- allocRegs: fib withSource: (x86 regSource) | 630 fiba <- allocRegs: fib withSource: (x86 regSource) |
601 print: "\n\nAFter Assignment:\n\n" | 631 print: "\n\nAfter Assignment:\n\n" |
602 foreach: fiba :idx inst { | 632 foreach: fiba :idx inst { |
603 print: (string: inst) . "\n" | 633 print: (string: inst) . "\n" |
604 } | 634 } |
605 fib2 <- to2Op: fiba | 635 fib2 <- to2Op: fiba |
606 print: "\n\n2-Operand:\n\n" | 636 print: "\n\n2-Operand:\n\n" |