changeset 185:181d8754a2ae

Initial work on IL module
author Mike Pavone <pavone@retrodev.com>
date Sun, 25 Aug 2013 14:45:00 -0700
parents ca249978ae96
children 35d2cc193d99
files modules/il.tp
diffstat 1 files changed, 333 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/il.tp	Sun Aug 25 14:45:00 2013 -0700
@@ -0,0 +1,333 @@
+{
+	//commutative ops
+	_add    <- 0
+	_and    <- 1
+	_or     <- 2
+	_xor    <- 3
+	//non-commutative ops
+	_sub    <- 4
+	_cmp    <- 5
+	_not    <- 6
+	_sl     <- 7
+	_asr    <- 8
+	_lsr    <- 9
+	_rol    <- 10
+	_ror    <- 11
+	_mov    <- 12
+	_call   <- 13
+	_ret    <- 14
+	_skipif <- 15
+
+	_names <- #[
+		"add"
+		"and"
+		"or"
+		"xor"
+		"sub"
+		"cmp"
+		"not"
+		"sl"
+		"asr"
+		"lsr"
+		"rol"
+		"ror"
+		"mov"
+		"call"
+		"ret"
+		"skipIf"
+	]
+
+	op3:a:b:out:size <- :_opcode :_ina :_inb :_out :_size {
+		#{
+			opcode <- { _opcode }
+			ina <- { _ina }
+			inb <- { _inb }
+			commutative? <- { _opcode < _sub }
+			out <- { _out }
+			size <- { _size }
+			numops <- { 3 }
+			name <- { _names get: _opcode }
+			string <- { name . " " . (string: _ina) . " " . (string: _inb) . " " . (string: _out) . " " . (string: _size) }
+		}
+	}
+	op2:in:out:size <- :_opcode :_in :_out :_size {
+		#{
+			opcode <- { _opcode }
+			in <- { _in }
+			out <- { _out }
+			size <- { _size }
+			numops <- { 2 }
+			name <- { _names get: _opcode }
+			string <- { name . " " . (string: _in) . " " . (string: _out) . " " . (string: _size) }
+		}
+	}
+	op1:arg:size <- :_opcode :_arg :_size {
+		#{
+			opcode <- { _opcode }
+			arg <- { _arg }
+			size <- { _size }
+			numops <- { 1 }
+			name <- { _names get: _opcode }
+			string <- { name . " " . (string: _arg) . " " . (string: _size) }
+		}
+	}
+
+	_sizenames <- #["b" "w" "l" "q"]
+	_size <- :_num {
+		#{
+			num <- { _num }
+			string <- { _sizenames get: _num }
+			= <- :other {
+				_num = (other num)
+			}
+			<= <- :other {
+				_num <= (other num)
+			}
+			>= <- :other {
+				_num >= (other num)
+			}
+			> <- :other {
+				_num > (other num)
+			}
+			< <- :other {
+				_num < (other num)
+			}
+		}
+	}
+	byte <- _size: 0
+	word <- _size: 1
+	long <- _size: 2
+	quad <- _size: 3
+
+	_retr <- #{
+		isInteger? <- { false }
+		register? <- { true }
+		argument? <- { false }
+		return? <- { true }
+		string <- { "retr" }
+		= <- :other {
+			(not: (other isInteger?)) && (other register?) && (other return?)
+		}
+	}
+
+	_condnames <- #[
+		"eq"
+		"neq"
+		"ge"
+		"le"
+		"gr"
+		"ls"
+		"uge"
+		"ule"
+		"ugr"
+		"uls"
+	]
+	condition <- :num {
+		#{
+			cc <- { num }
+			string <- { _condnames get: num }
+			= <- :other { num = (other cc) }
+		}
+	}
+	_eq <- condition: 0
+	_neq <- condition: 1
+	_ge <- condition: 2
+	_le <- condition: 3
+	_gr <- condition: 4
+	_ls <- condition: 5
+	_uge <- condition: 6
+	_ule <- condition: 7
+	_ugr <- condition: 8
+	_uls <- condition: 9
+
+	#{
+		b <- { byte }
+		w <- { word }
+		l <- { long }
+		q <- { quad }
+
+		eq <- { _eq }
+		neq <- { _neq }
+
+		//signed conditions
+		ge <- { _ge }
+		le <- { _le }
+		gr <- { _gr }
+		ls <- { _ls }
+
+		//unsigned conditions
+		uge <- { _uge }
+		ule <- { _ule }
+		ugr <- { _ugr }
+		uls <- { _uls }
+
+
+		reg <- :num {
+			#{
+				isInteger? <- { false }
+				register? <- { true }
+				argument? <- { false }
+				return? <- { false }
+				regnum <- { num }
+				string <- { "r" . (string: num) }
+				= <- :other {
+					(not: (other isInteger?)) && (other register?) && (not: (other argument?)) && (not: (other return?)) && num = (other regnum)
+				}
+			}
+		}
+		arg <- :num {
+			#{
+				isInteger? <- { false }
+				register? <- { true }
+				argument? <- { true }
+				return? <- { false }
+				argnum <- { num }
+				string <- { "a" . (string: num) }
+				= <- :other {
+					(not: (other isInteger?)) && (other register?) && (other argument?)  && num = (other regnum)
+				}
+			}
+		}
+		retr <- { _retr }
+
+		add <- :ina inb out size {
+			op3: _add a: ina b: inb out: out size: size
+		}
+
+		sub <- :ina inb out size {
+			op3: _sub a: ina b: inb out: out size: size
+		}
+
+		cmp <- :ina inb out size {
+			op3: _cmp a: ina b: inb out: out size: size
+		}
+
+		and <- :ina inb out size {
+			op3: _and a: ina b: inb out: out size: size
+		}
+
+		or <- :ina inb out size {
+			op3: _or a: ina b: inb out: out size: size
+		}
+
+		xor <- :ina inb out size {
+			op3: _xor a: ina b: inb out: out size: size
+		}
+
+		bnot <- :in out size {
+			op2: _not in: in out: out size: size
+		}
+
+		sl <- :shift in out size {
+			op3: _sl a: shift b: in out: out size: size
+		}
+
+		asr <- :shift in out size {
+			op3: _asr a: shift b: in out: out size: size
+		}
+
+		lsr <- :shift in out size {
+			op3: _lsr a: shift b: in out: out size: size
+		}
+
+		rol <- :rot in out size {
+			op3: _rol a: rot b: in out: out size: size
+		}
+
+		ror <- :rot in out size {
+			op3: _ror a: rot b: in out: out size: size
+		}
+
+		mov <- :in out size {
+			op2: _mov in: in out: out size: size
+		}
+
+		call:withArgs <- :_target :_args {
+			#{
+				opcode <- { _call }
+				target <- { _target }
+				args <- { _args }
+				numops <- { 0 }
+				name <- { _names get: _call }
+				string <- {
+					argstr <- _args map: :el {
+						string: el
+					}
+					name . " " . (string: _target) . " " . (argstr join: " ")
+				}
+			}
+		}
+
+		return <- :val size {
+			op1: _ret arg: val size: size
+		}
+		skipIf <- :_cond _toskip {
+			#{
+				opcode <- { _skipif }
+				toskip <- { _toskip }
+				cond <- { _cond }
+				numops <- { 0 }
+				name <- { _names get: _skipif }
+				string <- {
+					block <- (_toskip map: :el { string: el }) join: "\n\t"
+					if: (_toskip length) > 0 {
+						block <- "\n\t" . block . "\n"
+					}
+					name . " " . (string: _cond) . " {" . block .  "}"
+				}
+			}
+		}
+
+		//used to convert IL to a format suitable for a 2-operand architecture
+		//should be run after register allocation (I think....)
+		to2Op <- :instarr {
+			instarr fold: #[] with: :newarr inst {
+				if: (inst numops) = 3 {
+					if: (inst inb) = (inst out) {
+						newarr append: (op2: (inst opcode) in: (inst ina) out: (inst out) size: (inst size))
+					} else: {
+						if: (inst commutative?) && (inst ina) = (inst out) {
+							newarr append: (op2: (inst opcode) in: (inst inb) out: (inst out) size: (inst size))
+						} else: {
+							newarr append: (mov: (inst inb) (inst out) (inst size))
+							newarr append: (op2: (inst opcode) in: (inst ina) out: (inst out) size: (inst size))
+						}
+					}
+				} else: {
+					if: (inst numops) = 2 && (inst opcode) != _mov {
+						if: (inst in) != (inst out) {
+							newarr append: (mov: (inst in) (inst out) (inst size))
+						}
+						newarr append: (op1: (inst opcode) val: (inst out) size: (inst size))
+					} else: {
+						newarr append: inst
+					}
+				}
+			}
+		}
+
+		main <- {
+			fib <- #[
+				sub: 2 (arg: 0) (reg: 0) q
+				skipIf: ge #[
+					return: 1 q
+				]
+				call: "fib" withArgs: #[reg: 0]
+				mov: retr (reg: 1) q
+				add: 1 (reg: 0) (reg: 2) q
+				call: "fib" withArgs: #[reg: 2]
+				add: retr (reg: 1) (reg: 3) q
+				return: (reg: 3) q
+			]
+			print: "Original:\n\n"
+			foreach: fib :idx inst {
+				print: (string: inst) . "\n"
+			}
+			fib2 <- to2Op: fib
+			print: "\n\n2-Operand:\n\n"
+			foreach: fib2 :idx inst {
+				print: (string: inst) . "\n"
+			}
+		}
+	}
+}