Mercurial > repos > rhope
diff genasm.rhope @ 105:43cc42df26cc
Various compiler improvements
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 24 Aug 2010 23:22:17 -0400 |
parents | 31f8182f3433 |
children |
line wrap: on
line diff
--- a/genasm.rhope Wed Aug 11 03:13:28 2010 -0400 +++ b/genasm.rhope Tue Aug 24 23:22:17 2010 -0400 @@ -1,5 +1,3 @@ -//Import extendlib.rhope -Import backendutils.rhope Blueprint Registers { @@ -317,20 +315,6 @@ 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] = [""]] @@ -341,589 +325,3 @@ } } -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 >>] -}