diff modules/x86.tp @ 193:4293c725394c

Mostly complete register allocation in il module with a register source in the x86 module
author Mike Pavone <pavone@retrodev.com>
date Mon, 26 Aug 2013 19:53:16 -0700
parents 97f107b9e8d3
children 30bed95cbb18
line wrap: on
line diff
--- a/modules/x86.tp	Mon Aug 26 19:50:17 2013 -0700
+++ b/modules/x86.tp	Mon Aug 26 19:53:16 2013 -0700
@@ -128,8 +128,8 @@
 	}
 
 	mod_rm:withTail <- :register regmem :end {
-		l <- regmem rm: end
-		(l value) or ( lshift: (register reg) by: 3u8) | (l tail)
+		list <- regmem rm: end
+		(list value) or ( lshift: (register reg) by: 3u8) | (list tail)
 	}
 
 	mod_rm <- :reg rm {
@@ -190,6 +190,30 @@
 	_dh <- upper: 6u8
 	_bh <- upper: 7u8
 
+	//AMD64 convention
+	_argregs <- #[
+		_rdi
+		_rsi
+		_rdx
+		_rcx
+		_r8
+		_r9
+	]
+	_calleesave <- #[
+		_rbx
+		_rbp
+		_r12
+		_r13
+		_r14
+		_r15
+	]
+	_tempregs <- #[
+		_r10
+		_r11
+		_rax
+	]
+
+
 	inst <- :ilist {
 		#{
 			length <- { ilist length }
@@ -477,6 +501,108 @@
 			inst: (prefix: fakesrc dst d withInstruction: base)
 		}
 
+		//TODO: support multiple calling conventions
+		regSource <- {
+			_used <- 0
+			_usedAllTime <- 0
+			_nextStackOff <- 0
+			_findUnused <- :size reglists{
+				found <- -1
+				foundlist <- -1
+				curlist <- 0
+				ll <- reglists length
+				while: { found < 0 && curlist < ll } do: {
+					cur <- 0
+					regs <- reglists get: curlist
+					len <- regs length
+					while: { found < 0 && cur < len } do: {
+						bit <- lshift: 1 by: cur
+						if: (_used and bit) = 0 {
+							found <- cur
+							foundlist <- regs
+							_used <- _used or bit
+							_usedAllTime <- _usedAllTime or bit
+						}
+						cur <- cur + 1
+					}
+					curlist <- curlist + 1
+				}
+				if: found >= 0 {
+					foundlist get: found
+				} else: {
+					myoff <- _nextStackOff
+					_nextStackOff <- _nextStackOff + size
+					il base: _rsp offset: myoff
+				}
+			}
+			#{
+				alloc <- :size {
+					_findUnused: size #[
+						_calleesave
+						_tempregs
+						_argregs
+					]
+				}
+				//used to allocate a register
+				//that will be returned before a call
+				allocTemp <- :size {
+					_findUnused: size #[
+						_tempregs
+						_argregs
+						_calleesave
+					]
+				}
+				//allocated the return register
+				allocRet <- :size {
+					bit <- (lshift: 1 by: (_rax num))
+					_used <- _used or bit
+					_usedAllTime <- _usedAllTime or bit
+					_rax
+				}
+				allocArg <- :argnum {
+					if: argnum < (_argregs length) {
+						reg <- _argregs get: argnum
+						bit <- (lshift: 1 by: (reg num))
+						_used <- _used or bit
+						_usedAllTime <- _usedAllTime or bit
+					} else: {
+						il base: _rsp offset: _nextStackOff + 8 * (argnum - (_argregs length))
+					}
+				}
+				allocSpecific <- :reg {
+					if: (reg register?) {
+						bit <- (lshift: 1 by: (reg num))
+						_used <- _used or bit
+					}
+				}
+				stackSize <- { _nextStackOff }
+				return <- :reg {
+					_used <- _used and (0xF xor (lshift: 1 by: (reg num)))
+				}
+				returnAll <- { _used = 0 }
+				needSaveProlog <- {
+					retval <- #[]
+					foreach: _calleesave :idx reg {
+						if: (_usedAllTime and (lshift: 1 by: (reg num))) != 0 {
+							retval append: reg
+						}
+					}
+					retval
+				}
+				needSaveForCall <- {
+					retval <- #[]
+					foreach: #[_tempregs _argregs] :_ regs {
+						foreach: regs :_ reg {
+							if: (_used and (lshift: 1 by: (reg num))) != 0 {
+								retval append: reg
+							}
+						}
+					}
+					retval
+				}
+			}
+		}
+
 		main <- {
 			fib <- label:
 			notbase <- label: