changeset 203:56b2100d9fff

Add code for converting IL into x86 machine code
author Mike Pavone <pavone@retrodev.com>
date Wed, 28 Aug 2013 01:05:45 -0700
parents cea671c4056c
children a8dffa4d4b54
files modules/il.tp modules/x86.tp
diffstat 2 files changed, 150 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/modules/il.tp	Wed Aug 28 01:05:29 2013 -0700
+++ b/modules/il.tp	Wed Aug 28 01:05:45 2013 -0700
@@ -412,20 +412,22 @@
 				}
 			}
 		}
-		save <- :regs :scope{
+		save <- :regs :_scope{
 			#{
 				opcode <- { _save }
 				numops <- { 0 }
 				name <- { _names get: _save }
+				tosave <- { regs }
+				scope <- { _scope }
 				string <- {
-					block <- scope join: "\n\t"
-					if: (scope length) > 0 {
+					block <- _scope join: "\n\t"
+					if: (_scope length) > 0 {
 						block <- "\n\t" . block . "\n"
 					}
 					name . " " . (regs join: " ") . " {" . block . "}"
 				}
 				to2OpInst <- {
-					save: regs (to2Op: scope)
+					save: regs (to2Op: _scope)
 				}
 			}
 		}
@@ -609,7 +611,26 @@
 			}
 		}
 
+		toBackend <- :program :backend {
+			prepped <- program map: :fun {
+				backend adjustIL: fun
+			}
+			labels <- prepped map: :_ {
+				backend label
+			}
+			outprog <- #[]
+			foreach: prepped :name instarr {
+				outprog append: (labels get: name)
+				foreach: instarr :_ inst {
+					backend convertIL: inst to: outprog withLabels: labels
+				}
+			}
+			outprog
+		}
+
 		main <- {
+			prog <- dict linear
+
 			fib <- #[
 				sub: 2 (arg: 0) (reg: 0) q
 				skipIf: ge #[
@@ -626,17 +647,13 @@
 			foreach: fib :idx inst {
 				print: (string: inst) . "\n"
 			}
-			print: "\n\nUsage:\n\n"
-			fiba <- allocRegs: fib withSource: (x86 regSource)
-			print: "\n\nAfter Assignment:\n\n"
-			foreach: fiba :idx inst {
-				print: (string: inst) . "\n"
-			}
-			fib2 <- to2Op: fiba
-			print: "\n\n2-Operand:\n\n"
-			foreach: fib2 :idx inst {
-				print: (string: inst) . "\n"
-			}
+			prog set: "fib" fib
+
+			mprog <- prog toBackend: x86
+			ba <- bytearray executableFromBytes: mprog
+			res <- ba runWithArg: 30u64
+			print: (string: res) . "\n"
+			0
 		}
 	}
 }
--- a/modules/x86.tp	Wed Aug 28 01:05:29 2013 -0700
+++ b/modules/x86.tp	Wed Aug 28 01:05:45 2013 -0700
@@ -9,6 +9,7 @@
 			rm <- :tail { reg or 0xC0u8 | tail }
 			validforSize? <- :size { true }
 			isInteger? <- { false }
+			isString? <- { false }
 			register? <- { true }
 			label? <- { false }
 			upper? <- { false }
@@ -57,7 +58,7 @@
 		rexBitReg <- { 0u8 }
 		rexBitRM <- { 0u8 }
 	}
-	size <- :s {
+	_size <- :s {
 		#{
 			num <- { s }
 			= <- :other {
@@ -85,10 +86,10 @@
 			}
 		}
 	}
-	byte <- size: 0
-	word <- size: 1
-	dword <- size: 2
-	qword <- size: 3
+	byte <- _size: 0
+	word <- _size: 1
+	dword <- _size: 2
+	qword <- _size: 3
 
 	condition <- :num {
 		#{
@@ -607,6 +608,118 @@
 			}
 		}
 
+		adjustIL <- :ilfun {
+			il to2Op: (il allocRegs: ilfun withSource: regSource)
+		}
+
+		convertIL:to:withLabels:withSaved <- :inst :outarr :labels :saved {
+			mapSize <- :ilsize {
+				if: (ilsize bytes) > 2 {
+					if: (ilsize bytes) = 8 { q } else: { d }
+				} else: {
+					if: (ilsize bytes) = 1 { b } else: { w }
+				}
+			}
+			mapcond <- :ilcond {
+				ccmap <- #[
+					e
+					ne
+					ge
+					le
+					g
+					l
+					ae
+					be
+					a
+					c
+				]
+				ccmap get: (ilcond cc)
+			}
+			opmap <- #[
+				{ outarr append: (add: (inst in) (inst out) (mapSize: (inst size))) }
+				{ } //and
+				{ } //or
+				{ } //xor
+				{ outarr append: (sub: (inst in) (inst out) (mapSize: (inst size))) }
+				{ } //cmp
+				{ } //not
+				{ } //sl
+				{ } //asr
+				{ } //lsr
+				{ } //rol
+				{ } //ror
+				{ outarr append: (mov: (inst in) (inst out) (mapSize: (inst size))) }
+				{
+					//call
+					arguments <- inst args
+					cur <- (arguments length) - 1
+					while: { cur >= 0 } do: {
+						src <- (arguments get: cur)
+						if: cur < (_argregs length) {
+							dst <- _argregs get: cur
+							if: (not: dst = src) {
+								//TODO: Handle edge case in which src is a caller saved
+								//reg that has been pusehd onto the stack to preserve
+								//it across this call
+								outarr append: (mov: src dst q)
+							}
+						} else: {
+							outarr append: (push: src)
+						}
+						cur <- cur - 1
+					}
+					toCall <- inst target
+					if: (toCall isString?) {
+						//TODO: Handle call to undefined label
+						toCall <- labels get: toCall
+					}
+					outarr append: (call: toCall)
+				}
+				{
+					//return
+					if: (not: _rax = (inst arg)) {
+						outarr append: (mov: (inst arg) _rax q)
+					}
+					foreach: saved :_ reg {
+						outarr append: (pop: reg)
+					}
+					outarr append: (ret: )
+				}
+				{
+					//skipIf
+					endlab <- label:
+					outarr append: (jcc: (mapcond: (inst cond)) endlab)
+					foreach: (inst toskip) :_ inst {
+						convertIL: inst to: outarr withLabels: labels withSaved: saved
+					}
+					outarr append: endlab
+				}
+				{
+					//save
+					newsave <- []
+					foreach: (inst tosave) :_ reg {
+						outarr append: (push: reg)
+						newsave <- reg | newsave
+					}
+					foreach: (inst scope) :_ inst {
+						convertIL: inst to: outarr withLabels: labels withSaved: newsave
+					}
+					if: ((inst scope) length) = 0 || (((inst scope) get: ((inst scope) length) - 1) opcode) != 14 {
+						foreach: newsave :_ reg {
+							outarr append: (pop: reg)
+						}
+					}
+				}
+			]
+			fun <- opmap get: (inst opcode)
+			fun:
+			outarr
+		}
+
+		convertIL:to:withLabels <- :inst :outarr :labels {
+			convertIL: inst to: outarr withLabels: labels withSaved: []
+		}
+
 		main <- {
 			fib <- label:
 			notbase <- label: