diff modules/x86.tp @ 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 3b13ced3b562
children a8dffa4d4b54
line wrap: on
line diff
--- 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: