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"