diff genasm.rhope @ 2:73e978d590c7

Adding WIP compiler code
author Mike Pavone <pavone@retrodev.com>
date Wed, 29 Apr 2009 02:58:03 -0400
parents
children 31f8182f3433
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/genasm.rhope	Wed Apr 29 02:58:03 2009 -0400
@@ -0,0 +1,940 @@
+//Import extendlib.rhope
+Escape Rhope Name[name:escaped]
+{
+	escaped <- [[[[[[[[[name]Replace["_","__"]
+		]Replace["@","_AT_"]
+		]Replace[" ","_SP_"]
+		]Replace[":","_CN_"]
+		]Replace["?","_QN_"]
+		]Replace["+","_PL_"]
+		]Replace["-","_MN_"]
+		]Replace["*","_TM_"]
+		]Replace["/","_DV_"]
+}
+
+Blueprint Registers
+{
+	Names
+	Can Data
+	Can Pointer
+	Available?
+	Need Save
+	Max Size
+}
+
+Set Yes[in:out]
+{
+	out <- Yes
+}
+
+_Flip[dest,val,index:out]
+{
+	out <- [dest]Set[val,index]
+}
+Flip[list,dest:out]
+{
+	out <- Fold["_Flip", dest, list]
+}
+
+Registers[names, data, pointer, need save, max size:out]
+{
+	out <- [[[[[[Build["Registers"]
+	]Names << [names]
+	]Can Data << [data]
+	]Can Pointer << [pointer]
+	]Available? << [ Map[names, "Set Yes"] ]
+	]Need Save << [ Flip[need save, ()] ]
+	]Max Size <<[max size]
+}
+
+Name@Registers[regs,num:out]
+{
+	out <- [[regs]Names >>]Index[num]
+}
+
+Allocate Helper@Registers[regs, try, current:found, not found]
+{
+	reg <- [try]Index[current]
+	If[[[regs]Available? >>]Index[reg]]
+	{
+		found <- Val[reg]
+	}{
+		[try]Next[current]
+		{
+			found, not found <- [regs]Allocate Helper[try, ~]
+		}{
+			not found <- Yes
+		}
+	}
+}
+
+Allocate Reg@Registers[regs,try:next regs,found,need save?,not found]
+{
+	[try]First
+	{
+		found, not found <- [regs]Allocate Helper[try, ~]
+		{
+			next regs <- [regs]Available? << [ [[regs]Available? >>]Set[~, No] ]
+			[[regs]Need Save >>]Index[~]
+			{
+				need save? <- Yes
+			}{
+				need save? <- No
+			}
+		}
+	}{
+		not found <- Yes
+	}
+}
+
+Free Reg@Registers[regs,num:out]
+{
+	out <- [regs]Available? <<[ [[regs]Available? >>]Set[num, Yes] ]
+}
+
+Processor Reg[func,type:next func,num,not found]
+{
+	regs <- [func]Registers >>
+	If[[type] = ["pointer"]]
+	{
+		source <- [regs]Can Pointer >>
+	}{
+		source <- [regs]Can Data >>
+	}
+	next regs, reg num, need save?, not found <- [regs]Allocate Reg[source] {}
+	{
+		If[need save?]
+		{
+			next func <- [[func]Need Save << [ [[func]Need Save >>]Set[reg num, Yes] ]
+			]Registers << [next regs]
+		}{
+			next func <- [func]Registers << [next regs]
+		}
+		num <- Val[reg num]
+	}
+}
+
+Processor Free Reg[func,num:out func]
+{
+	out func <- [func]Registers <<[  [[func]Registers >>]Free Reg[num] ]
+}
+
+Processor Allocate[func,name,size,type:out func,out]
+{
+	regs <- [func]Registers >>
+	If[[type] = ["pointer"]]
+	{
+		alloc size <- [func]Pointer Size
+	}{
+		alloc size <- size
+	}
+	If[[alloc size] > [[regs]Max Size >>]] {
+			stack alloc <- Val[alloc size]
+	}{
+		next func <- [func]Processor Reg[type] {}
+		{
+			location <- Register[~, alloc size]
+		}{
+			stack alloc <- Val[alloc size]
+		}
+	}
+	Val[stack alloc]
+	{
+		next func, location <- [func]Allocate Stack[alloc size]
+	}
+	out func <- [next func]Variables <<[ [[next func]Variables >>]Set[name, location] ]
+	out <- Val[location]
+}
+
+Blueprint Register
+{
+	Number
+	Value Size
+}
+Register[num,size:out]
+{
+	If[[size] = [3]]
+	{
+		value size <- 4
+	}{
+		value size <- size
+	}
+	out <- [[Build["Register"]]Number <<[num]]Value Size <<[value size]
+}
+
+In Memory?@Register[reg:out]
+{
+	out <- No
+}
+
+=@Register[reg,other:out]
+{
+	,out <- If[[Type Of[reg]] = [Type Of[other]]]
+	{
+		out <- [[reg]Number >>] = [[other]Number >>]
+	}
+}
+
+Op ASM@Register[reg,func,regs,extra offset:out]
+{
+	out <- [regs]Index[ [reg]Number >> ]
+}
+
+Size@Register[reg:out]
+{
+	out <- [reg]Value Size >>
+}
+
+Blueprint Immediate
+{
+	Value
+}
+
+Immediate[val:out]
+{
+	out <- [Build["Immediate"]]Value <<[val]
+}
+
+In Memory?@Immediate[val:out]
+{
+	out <- No
+}
+
+=@Immediate[val,other:out]
+{
+	,out <- If[[Type Of[val]] = [Type Of[other]]]
+	{
+		out <- [[val]Value >>] = [[other]Value >>]
+	}
+}
+
+Op ASM@Immediate[val,func,regs,extra offset:out]
+{
+	out <- [val]Value >>
+}
+
+Size@Immediate[val:out]
+{
+	out <- 4
+}
+
+Blueprint None
+{
+	Dummy
+}
+
+None[:out]
+{
+	out <- Build["None"]
+}
+
+In Memory?@None[none:out]
+{
+	out <- No
+}
+
+Op ASM@None[none,func,regs,extra offset:out]
+{
+	out <- ""
+}
+
+Size@None[none:out]
+{
+	out <- 0
+}
+
+Blueprint Stack Location
+{
+	Offset
+	Size
+}
+
+Stack Location[offset,size:out]
+{
+	out <- [[Build["Stack Location"]]Offset <<[offset]]Size <<[size]
+}
+
+In Memory?@Stack Location[location:out]
+{
+	out <- Yes
+}
+
+=@Stack Location[loc,other:out]
+{
+	,out <- If[[Type Of[loc]] = [Type Of[other]]]
+	{
+		out <- [[loc]Offset >>] = [[other]Offset >>]
+	}
+}
+
+Op ASM@Stack Location[loc,func,regs,extra offset:out]
+{
+	offset <- [[[func]Stack Size >>] - [[loc]Offset >>]] - [[loc]Size >>]
+	If[[offset] > [0]]
+	{
+		toffset <- ["+"]Append[offset]
+	}{
+		toffset <- ""
+	}
+	out <- [["[esp"]Append[toffset]]Append["]"]
+}
+
+Size@Stack Location[loc:out]
+{
+	out <- [loc]Size >>
+}
+
+Blueprint Pointer
+{
+	Base
+	Offset
+	Target Size
+}
+
+Pointer[base,offset,size:out]
+{
+	out <- [[[Build["Pointer"]]Base <<[base]]Offset <<[offset]]Target Size <<[size]
+}
+
+In Memory?@Pointer[location:out]
+{
+	out <- Yes
+}
+
+=@Pointer[pointer,other:out]
+{
+	,out <- If[[Type Of[loc]] = [Type Of[other]]]
+	{
+		out <- [[loc]Storage >>] = [[other]Storage >>]
+	}
+}
+
+Op ASM@Pointer[pointer,func,regs,extra offset:out]
+{
+	If[[Type Of[ [pointer]Offset >> ]] = ["None"]]
+	{
+		out <- [["["]Append[ [[pointer]Base >>]Op ASM[func,regs,extra offset] ]]Append["]"]
+	}{
+		out <- [[[["["
+			]Append[ [[pointer]Base >>]Op ASM[func,regs,extra offset] ]
+			]Append["+"]
+			]Append[ [[pointer]Offset >>]Op ASM[func,regs,extra offset] ]
+			]Append["]"]
+	}
+}
+
+Size@Pointer[pointer:out]
+{
+	out <- [pointer]Target Size >>
+}
+
+Blueprint X86 Instruction
+{
+	Name
+	Op1
+	Op2
+	Width
+	Extra Offset
+}
+
+X86 Instruction[name, op1, op2, width:out]
+{
+	out <- [[[[[Build["X86 Instruction"]]Name << [name]]Op1 << [op1]]Op2 <<[op2]]Width <<[width]]Extra Offset <<[0]
+}
+
+CAppend[left,right:out]
+{
+	If[[right] = [""]]
+	{
+		out <- ""
+	}{
+		out <- [left]Append[right]
+	}
+}
+
+Inst ASM@X86 Instruction[inst,func:out]
+{
+	If[[[inst]Width >>] = [4]]
+	{
+		regs <- ("eax","ecx","edx","ebx","esi","edi","esp")
+	}{
+		If[[[inst]Width >>] = [2]]
+		{
+			regs <- ("ax","cx","dx","bx","si","di")
+		}{
+			regs <- ("al","cl","dl","bl","si","di")
+		}
+	}
+	out <- [[[inst]Name >>
+	]Append[ [" "]CAppend[[[inst]Op1>>]Op ASM[func, regs, [inst]Extra Offset >>]] ]
+	]Append[ [", "]CAppend[[[inst]Op2>>]Op ASM[func, regs, [inst]Extra Offset >>]] ]
+}
+
+Blueprint X86 Function
+{
+	Name
+	Registers
+	Variables
+	Scratch
+	Need Save
+	Free Stack Locations
+	Stack Size
+	Param Size
+	Temp Stack
+	Convention
+	Instructions
+}
+
+X86 Function[name,params,convention:out]
+{
+	[[[[[[[[[Build["X86 Function"]
+	]Name << [name]
+	]Registers << [Registers[("eax","ecx","edx","ebx","esi","edi"), (0,1,2,3,4,5), (0,1,2,3,4,5), (3,4,5), 4]]
+	]Variables  <<[New@Dictionary[]]
+	]Need Save <<[()]
+	]Free Stack Locations <<[()]
+	]Stack Size <<[0]
+	]Instructions <<[()]
+	]Convention <<[convention]
+	]Alloc Params[params, convention]
+	{
+		out <- [~]Param Size <<[ [~]Stack Size >> ]
+	}
+}
+
+Pointer Size@X86 Function[func:out]
+{
+	out <- 4
+}
+
+Param Helper@X86 Function[func, param:out]
+{
+	,loc <- [func]Allocate Stack[4]
+	{
+		out <- [~]Variables << [ [[~]Variables >>]Set[param, loc] ]
+	}
+}
+
+Alloc Params@X86 Function[func,params,convention:out]
+{
+	If[[convention] = ["fastcall"]]
+	{
+		[params]Index[0]
+		{
+				next func <- [[func]Registers <<[ [[func]Registers >>]Available? <<[ [[[func]Registers >>]Available? >>]Set[1, No] ]]
+				]Variables <<[ [[func]Variables >>]Set[~, Register[1,4]] ]
+				[params]Index[1]
+				{
+					next func2 <- [[next func]Registers <<[ [[next func]Registers >>]Available? <<[ [[[next func]Registers >>]Available? >>]Set[2, No] ]]
+					]Variables <<[ [[next func]Variables >>]Set[~, Register[2,4]] ]
+					[params]Index[2]
+					{
+						out <- _Fold[params, 2, next func2, "Param Helper"]
+					}{
+						out <- Val[next func2]
+					}
+				}{
+					out <- Val[next func]
+				}
+		}{
+			out <- func
+		}
+	}{
+		out <- Fold["Param Helper", func, params]
+	}
+}
+
+Add Instruction@X86 Function[func, inst:out]
+{
+	out <- [func]Instructions << [ [[func]Instructions >>]Append[ [inst]Extra Offset <<[[func]Temp Stack >>] ] ]
+}
+
+Allocate Stack@X86 Function[func,size:func out,out]
+{
+	out <- Stack Location[[func]Stack Size >>, size]
+	func out <- [func]Stack Size <<[ [[func]Stack Size >>]+[size] ]
+}
+
+Allocate Var@X86 Function[func,name,size,type:out func,out]
+{
+	out func, out <- Processor Allocate[func,name,size,type]
+}
+
+Resolve@X86 Function[func,op:out,out func]
+{
+	If[[Type Of[op]] = ["String"]]
+	{
+		out <- [[func]Variables >>]Index[op]
+	}{
+		out <- op
+	}
+}
+
+Allocate Scratch@X86 Function[func,size:out func,scratch]
+{
+	out func,scratch <- Processor Reg[func,"data"] {} {}
+	{
+		//FIXME: need to use a reg that's not involved in the current op
+		//FIXME: Also, might need two scratch regs and both might be in use
+		,stack inc <- [func]Save Reg[0]
+		{
+			out func <- [~]Scratch << [ [[~]Scratch >>]Set[0, Yes] ]
+		}
+	}
+}
+
+Free Scratch@X86 Function[func,scratch:out func]
+{
+	[[func]Scratch >>]Index[scratch]
+	{
+		[func]Restore Reg[scratch]
+		{
+			out func <- [~]Scratch << [ [[~]Scratch >>]Remove[scratch] ]
+		}
+	}{
+		out func <- Processor Free Reg[func, scratch]
+	}
+	If[[scratch]Index[1]]
+	{
+		
+	}{
+		
+	}
+}
+
+Classify Op@X86 Function[func,op:class]
+{
+	If[[op]In Memory?]
+	{
+		If[[Type Of[op]] = ["Pointer"]]
+		{
+			If[[[[op]Base >>]In Memory?] Or [[[op]Offset >>]In Memory?]]
+			{
+				class <- "u"
+			}{
+				class <- "m"
+			}
+		}{
+			class <- "m"
+		}
+	}{
+		class <- "r"
+	}
+}
+
+RegMem2Op@X86 Function[func,dest,notdest,op,size:out]
+{
+	out <- [func]Add Instruction[X86 Instruction[op, dest, notdest, size]]
+}
+
+MemPointer2Op@X86 Function[func,dest,notdest,op,size:out]
+{
+	,scratch <- [func]Allocate Scratch[size]
+	{
+		out <- [[[~]Fetch[notdest,scratch]
+			]Add Instruction[X86 Instruction[op, dest, scratch, size]]
+			]Free Scratch[scratch]
+	}
+}
+
+//Make sure to map this to both r, (m or r) -> m and r, (m or r) -> r
+RegMemToNotPointer@X86 Function[func,source1,source2,dest,op,size:out]
+{
+	out <- [[func]Move[source2,dest]
+		]Add Instruction[X86 Instruction[op, dest, source1, size]]
+}
+
+RegMemToPointer@X86 Function[func,source1,source2,dest,op,size:out]
+{
+	,scratch <- [func]Allocate Scratch[size]
+	{
+		spointer <- Pointer[scratch, None[], size]
+		out <- [[[[~]Calculate Address[dest, scratch]
+			]Move[source2, spointer]
+			]Add Instruction[X86 Instruction[op, spointer, source1, size]]
+			]Free Scratch[scratch]
+	}
+}
+
+RegPointerToMem@X86 Function[func,source1,source2,dest,op,size:out]
+{
+	,scratch <- [func]Allocate Scratch[size]
+	{
+		spointer <- Pointer[scratch, None[], size]
+		out <- [[[[~]Calculate Address[source2, scratch]
+			]Move[spointer, dest]
+			]Add Instruction[X86 Instruction[op, dest, source1, size]]
+			]Free Scratch[scratch]
+	}
+}
+
+RegPointerReg2Op@X86 Function[func,dest,notdest,op,size:out]
+{
+	,scratch <- [func]Allocate Scratch[size]
+	{
+		spointer <- Pointer[scratch, None[], size]
+		out <- [[[~]Calculate Address[notdest, scratch]
+			]Add Instruction[X86 Instruction[op, dest, spointer, size]]
+			]Free Scratch[scratch]
+	}
+}
+
+RegPointerPointer2Op@X86 Function[func,dest,notdest,op,size:out]
+{
+	,scratch <- [func]Allocate Scratch[size]
+	{
+		spointer <- Pointer[scratch, None[], size]
+		out <- [[[~]Calculate Address[dest, scratch]
+			]Add Instruction[X86 Instruction[op, spointer, notdest, size]]
+			]Free Scratch[scratch]
+	}
+}
+
+RegPointerToPointer@X86 Function[func,source1,source2,dest,op,size:out]
+{
+	,scratch <- [func]Allocate Scratch[size]
+	{
+		spointer <- Pointer[scratch, None[], size]
+		,scratch2 <- [~]Allocate Scratch[size]
+		{
+			spointer2 <- Pointer[scratch2, None[], size]
+			out <- [[[[[[~]Calculate Address[source2, scratch]
+				]Calculate Address[dest, scratch2]
+				]Move[spointer2, spointer]
+				]Add Instruction[X86 Instruction[op, spointer2, source1, size]]
+				]Free Scratch[scratch2]
+				]Free Scratch[scratch]
+		}
+	}
+}
+
+//If source1, source2 and dest are all pointers with register offsets, allocating a scratch register could
+//become a problem unless I let ebp be used as a scratch register. Should be doable as long as thread local
+//variables properly report ebp as a used register. Alternatively, one register could be reserved for scratch
+//usage
+MemPointerToMem@X86 Function[func,source1,source2,dest,op,size:out]
+{
+	,scratch <- [func]Allocate Scratch[size]
+	{
+		out <- [[[[~]Fetch[source2, scratch]
+			]Add Instruction[X86 Instruction[op, scratch, source1, size]]
+			]Move[scratch, dest]
+			]Free Scratch[scratch]
+	}
+}
+
+MemPointerToPointer@X86 Function[func,source1,source2,dest,op,size:out]
+{
+	,scratch <- [func]Allocate Scratch[size]
+	{
+		,scratch2 <- [~]Allocate Scratch[size]
+		{
+			spointer2 <- Pointer[scratch2, None[], size]
+			out <- [[[[[[~]Fetch[source2, scratch]
+				]Add Instruction[X86 Instruction[op, scratch, source1, size]]
+				]Calculate Address[dest, scratch2]
+				]Move[scratch, spointer2]
+				]Free Scratch[scratch2]
+				]Free Scratch[scratch]
+		}
+	}
+}
+
+//This does almost the same thing as RegMemToNotPointer, depending on how I do the pattern matching I could maybe combine them
+PointerMemToReg@X86 Function[func,source1,source2,dest,op,size:out]
+{
+	out <- [[func]Fetch[source1,dest]
+		]Add Instruction[X86 Instruction[op, dest, source2, size]]
+}
+
+PointerPointer2Op@X86 Function[func,dest,notdest,op,size:out]
+{
+	,scratch <- [func]Allocate Scratch[size]
+	{
+		spointer <- Pointer[scratch, None[], size]
+		,scratch2 <- [~]Allocate Scratch[size]
+		{
+			out <- [[[[[[[~]Calculate Address[dest, scratch]
+				]Fetch[notdest, scratch2]
+				]Add Instruction[X86 Instruction[op, scratch, scratch2, size]]
+				]Calculate Address[dest, scratch2]
+				]Move[scratch, spointer2]
+				]Free Scratch[scratch2]
+				]Free Scratch[scratch]
+		}
+	}
+}
+
+PointerPointerToPointer@X86 Function[func,source1,source2,dest,op,size:out]
+{
+	,scratch <- [func]Allocate Scratch[size]
+	{
+		,scratch2 <- [~]Allocate Scratch[size]
+		{
+			spointer2 <- Pointer[scratch2, None[], size]
+			out <- [[[[[[[~]Fetch[source1, scratch]
+				]Calculate Address[source2, scratch2]
+				]Add Instruction[X86 Instruction[op, scratch, spointer2, size]]
+				]Calculate Address[dest, scratch2]
+				]Move[scratch, spointer2]
+				]Free Scratch[scratch2]
+				]Free Scratch[scratch]
+		}
+	}
+}
+
+PointerPointerToMem@X86 Function[func,source1,souce2,dest,op,size:out]
+{
+	,scratch <- [func]Allocate Scratch[size]
+	{
+		spointer <- Pointer[scratch, None[], size]
+		out <- [[[[[~]Calculate Address[source1, scratch]
+			]Move[dest, spointer]
+			]Fetch[source2, scratch]
+			]Add Instruction[X86 Instruction[op, dest, scratch, size]]
+			]Free Scratch[scratch]
+	}
+}
+
+PointerPointerToReg@X86 Function[func,source1,souce2,dest,op,size:out]
+{
+	,scratch <- [func]Allocate Scratch[size]
+	{
+		spointer <- Pointer[scratch, None[], size]
+		out <- [[[[~]Fetch[source1, dest]
+			]Calculate Address[source2, scratch]
+			]Add Instruction[X86 Instruction[op, dest, scratch, size]]
+			]Free Scratch[scratch]
+	}
+}
+
+2Op Associative@X86 Function[func,psource1,psource2,pdest,name:out func]
+{
+	source1 <- [func]Resolve[psource1]
+	source2 <- [func]Resolve[psource2]
+	dest <- [func]Resolve[pdest]
+	dest class <- [func]Classify Op[dest]
+	width <- Min[Min[Min[[source1]Size,[source2]Size], [dest]Size], 4]
+	swapper <- (1,0)
+	sources <- [[()]Append[source1]Append[source2]
+	[sources]Find[dest]
+	{
+		source <- [swapper]Index[~]
+		source class <- [func]Classify Op[source]
+		If[[dest class] = ["u"]]
+		{
+			If[[source class] = ["r"]]
+			{
+				out func <- [func]RegPointerPointer2Op[dest,source,name,width]
+			}{
+				out func <- [func]PointerPointer2Op[dest,source,name,width]
+			}
+		}{
+			If[[dest class] = ["r"]]
+			{
+				If[[source class] = ["u"]]
+				{
+					out func <- [func]RegPointerReg2Op[dest,source,name,width]
+				}{
+					out func <- [func]RegMem2Op[dest,source,name,width]
+				}
+			}{
+				If[[source class] = ["r"]]
+				{
+					out func <- [func]RegMem2Op[dest,source,name,width]
+				}{
+					out func <- [func]MemPointer2Op[dest,source,name,width]
+				}
+			}
+		}
+	}{
+		sclasses <- Map[sources, ["Classify Op"]Set Input[0, func]]
+		first <- [sources]Index[found index]
+		other index <- [swapper]Index[found index]
+		other <- [sources]Index[other index]
+		other class <- [sclasses]Index[other index]
+		found index <- [sclasses]Find["r"]
+		{
+			If[[other class] = ["u"]]
+			{
+				If[[dest class] = ["m"]]
+				{
+					out func <- [func]RegPointerToMem[first,other,dest,name,width]
+				}{
+					If[[dest class] = ["u"]]
+					{
+						out func <- [func]RegPointerToPointer[first,other,dest,name,width]
+					}{
+						out func <- [func]PointerMemToReg[other,first,dest,name,width]
+					}
+				}
+			}{
+				If[[dest class] = ["u"]]
+				{
+					out func <- [func]RegMemToPointer[first,other,dest,name,width]
+				}{
+					out func <- [func]RegMemToNotPointer[first,other,dest,name,width]
+				}
+			}
+		}{
+			found index <- [sclasses]Find["m"]
+			{
+				If[[dest class] = ["r"]]
+				{
+					out func <- [func]PointerMemToReg[other,first,dest,name,width]
+				}{
+					If[[dest class] = ["m"]]
+					{
+						out func <- [func]MemPointerToMem[first,other,dest,name,width]	
+					}{
+						out func <- [func]MemPointerToPointer[first,other,dest,name,width]
+					}
+				}
+			}{
+				If[[dest class] = ["r"]]
+				{
+					out func <- [func]PointerPointerToReg[first,other,dest,name,width]
+				}{
+					If[[dest class] = ["m"]]
+					{
+						out func <- [func]PointerPointerToMem[first,other,dest,name,width]
+					}{
+						out func <- [func]PointerPointerToPointer[first,other,dest,name,width]
+					}
+				}
+			}
+		}
+	}
+}
+
+2Op@X86 Function[func,psource1,psource2,pdest,name:out func]
+{
+	source1 <- [func]Resolve[psource1]
+	source2 <- [func]Resolve[psource2]
+	dest <- [func]Resolve[pdest]
+	width <- Min[Min[Min[[source1]Size,[source2]Size], [dest]Size], 4]
+	If[[source1] = [dest]]
+	{
+		If[[[source1]In Memory?] And [[source2]In Memory?]]
+		{
+			,scratch, stack inc <- [func]Allocate Scratch[width]
+			{
+				out func <- [[[~]Add Instruction[X86 Instruction["mov", [scratch]Index[0], source2, width, stack inc]]
+				]Add Instruction[X86 Instruction[name, source1, [scratch]Index[0], width, stack inc]]
+				]Free Scratch[scratch]
+			}
+		}{
+			out func <- [func]Add Instruction[X86 Instruction[name, dest, source2, width, 0]]
+		}
+	}{
+		If[[dest]In Memory?]
+		{
+			If[[source2]In Memory?]
+			{
+				,scratch, stack inc <- [func]Allocate Scratch[width]
+				{
+					out func <- [[[[~]Add Instruction[X86 Instruction["mov", [scratch]Index[0], source1, width, stack inc]]
+					]Add Instruction[X86 Instruction[name, [scratch]Index[0], source2, width, stack inc]]
+					]Add Instruction[X86 Instruction["mov", dest, [scratch]Index[0], width, stack inc]]
+					]Free Scratch[scratch]
+				}
+			}{
+				out func <- [[func]Move[source1,dest]
+				]Add Instruction[X86 Instruction[name, dest, source2, width, 0]]
+			}
+		}{
+			out func <- [[func]Move[source1,dest]
+			]Add Instruction[X86 Instruction[name, dest, source2, width, 0]]
+		}
+	}
+}
+
+Add@X86 Function[func,source1,source2,dest:out func]
+{
+	out func <- [func]2Op Associative[source1,source2,dest,"add"]
+}
+
+Sub@X86 Function[func,source1,source2,dest:out func]
+{
+	out func <- [func]2Op[source1,source2,dest,"sub"]
+}
+
+Move@X86 Function[func,psource,pdest:out func]
+{
+	source <- [func]Resolve[psource]
+	dest <- [func]Resolve[pdest]
+	out func <- [func]Add Instruction[X86 Instruction["mov", dest, source, 4]]
+}
+
+Instruction ASM[current,instruction,func:out]
+{
+	out <- [[[current]Append["\t"]]Append[ [instruction]Inst ASM[func] ]]Append["\n"]
+}
+
+Save Reg@X86 Function[func,reg:out]
+{
+	out <- [[func]Add Instruction[X86 Instruction["push", Register[reg, 4], None[], 4]]
+	]Temp Stack << [ [[func]Temp Stack >>]+[4] ]
+}
+
+Prolog Save@X86 Function[func,junk,reg:out]
+{
+	out <- [[func]Add Instruction[X86 Instruction["push", Register[reg, 4], None[], 4]]
+	]Stack Size << [ [[func]Stack Size >>]+[4] ]
+}
+
+Restore Reg@X86 Function[func,reg:out]
+{
+	out <- [[func]Add Instruction[X86 Instruction["pop", Register[reg, 4], None[], 4]]
+	]Temp Stack << [ [[func]Temp Stack >>]-[4] ]
+}
+
+Epilogue Restore@X86 Function[func,junk,reg:out]
+{
+	out <- [func]Add Instruction[X86 Instruction["pop", Register[reg, 4], None[], 4]]
+}
+
+Finalize@X86 Function[func:out]
+{
+	alloc stack <- [[func]Stack Size >>] - [[func]Param Size >>]
+	
+	oldstream <- [func]Instructions >>
+	
+	If[[alloc stack] > [0]]
+	{
+		start <- [()]Append[X86 Instruction["sub", Register[6, 4],Immediate[alloc stack], Register[6, 4], 4], func]
+	}{
+		start <- ()
+	}
+	
+	If[[[func]Convention >>] = ["cdecl"]]
+	{
+		If[ [alloc stack] > [0] ]
+		{
+			retparam <- Immediate[alloc stack]
+		}{
+			retparam <- None[]
+		}
+	}{
+		retparam <- Immediate[[func]Stack Size >>]
+	}
+	
+	[[func]Need Save >>]First
+	{
+		prolog <- Fold["Prolog Save", [func]Instructions << [start], [func]Need Save >>]
+		out <- [Reverse Fold["Epilogue Restore", body, [func]Need Save >>]]Add Instruction[X86 Instruction["ret", retparam, None[], 4]]
+	}{
+		prolog <- [func]Instructions <<[start]
+		out <- [body]Add Instruction[X86 Instruction["ret", retparam, None[], 4]]
+	}
+	
+	body <- Fold["Add Instruction", prolog, oldstream]
+}
+
+Text@X86 Function[func:out]
+{
+	name line <- [Escape Rhope Name[[func]Name >>]
+	]Append[":\n"]
+	
+	out <- Fold[["Instruction ASM"]Set Input[2, func], name line, [func]Instructions >>]
+}