X-Git-Url: http://git.joshuawise.com/snipe.git/blobdiff_plain/12aa4087bee3e70f170d7457794921de4e385227..0a24e44d4e9f82f8d3d83de8e58c83c8cf2868b6:/codegen/x86.sml diff --git a/codegen/x86.sml b/codegen/x86.sml index b7055f6..33ddd60 100644 --- a/codegen/x86.sml +++ b/codegen/x86.sml @@ -1,28 +1,60 @@ +(* L2 compiler + * X86 instruction/operand internal representation and manipulation + * Author: Joshua Wise + * Author: Chris Lu + *) + signature X86 = sig + (* register type *) datatype reg = EAX | EBX | ECX | EDX | ESI | EDI | EBP | RSP | R8D | R9D | R10D | R11D | R12D | R13D | R14D | R15D + (* operands to instructions *) datatype oper = REG of reg | TEMP of Temp.temp | CONST of Word32.word | REL of (reg * int) + (* instructions + * a better way to do SET would be SET of cc * oper, + * same with JMP + *) datatype insn = DIRECTIVE of string | COMMENT of string | + LABEL of Label.label | MOVL of oper * oper | SUBL of oper * oper | IMUL of oper * oper | IMUL3 of oper * oper * Word32.word | ADDL of oper * oper | - LEAL of oper * oper * oper | IDIVL of oper | NEG of oper | + NOTL of oper | + SALL of oper * oper | + SARL of oper * oper | + ANDL of oper * oper | + ORL of oper * oper | + XORL of oper * oper | + CMPL of oper * oper | + TEST of oper * oper | + SETNE of oper | + SETE of oper | + SETLE of oper | + SETL of oper | + SETGE of oper | + SETG of oper | + JMP of Label.label | + JE of Label.label | + JNE of Label.label | + MOVZBL of oper * oper | CLTD | RET val cmpoper : oper * oper -> order val opereq : oper * oper -> bool val regname : reg -> string + val regnameb : reg -> string val regtonum : reg -> int val numtoreg : int -> reg val prettyprint_oper : oper -> string + val prettyprint_operb : oper -> string val prettyprint : insn -> string end @@ -34,17 +66,36 @@ struct datatype insn = DIRECTIVE of string | COMMENT of string | + LABEL of Label.label | MOVL of oper * oper | SUBL of oper * oper | IMUL of oper * oper | IMUL3 of oper * oper * Word32.word | ADDL of oper * oper | - LEAL of oper * oper * oper | IDIVL of oper | NEG of oper | + NOTL of oper | + SALL of oper * oper | + SARL of oper * oper | + ANDL of oper * oper | + ORL of oper * oper | + XORL of oper * oper | + CMPL of oper * oper | + TEST of oper * oper | + SETNE of oper | + SETE of oper | + SETLE of oper | + SETL of oper | + SETGE of oper | + SETG of oper | + JMP of Label.label | + JE of Label.label | + JNE of Label.label | + MOVZBL of oper * oper | CLTD | RET - + + (* gives name of reg *) fun regname EAX = "eax" | regname EBX = "ebx" | regname ECX = "ecx" @@ -61,7 +112,26 @@ struct | regname R13D = "r13d" | regname R14D = "r14d" | regname R15D = "r15d" - + + (* like regname, but for the byte name *) + fun regnameb EAX = "al" + | regnameb EBX = "bl" + | regnameb ECX = "cl" + | regnameb EDX = "dl" + | regnameb ESI = "sil" + | regnameb EDI = "dil" + | regnameb EBP = "bpl" + | regnameb RSP = "spl" + | regnameb R8D = "r8b" + | regnameb R9D = "r9b" + | regnameb R10D = "r10b" + | regnameb R11D = "r11b" + | regnameb R12D = "r12b" + | regnameb R13D = "r13b" + | regnameb R14D = "r14b" + | regnameb R15D = "r15b" + + (* gives number (color) associated with reg *) fun regtonum EAX = 0 | regtonum EBX = 1 | regtonum ECX = 2 @@ -78,7 +148,8 @@ struct | regtonum R15D = 13 | regtonum EBP = 14 (* Dummy numbers -- not permitted for allocation, but there so that we can compare *) | regtonum RSP = 15 - + + (* gives reg associated with number (color) *) fun numtoreg 0 = EAX | numtoreg 1 = EBX | numtoreg 2 = ECX @@ -94,9 +165,13 @@ struct | numtoreg 12 = R14D | numtoreg 13 = R15D | numtoreg n = raise ErrorMsg.InternalError ("numtoreg: Unknown register "^(Int.toString n)) - + + (* register compare *) fun regcmp (r1, r2) = Int.compare (regtonum r1, regtonum r2) + (* operand compare; arbitrary order imposed to make + * various things easier (e.g. liveness, for sorting) + *) fun cmpoper (REG(reg1), REG(reg2)) = regcmp (reg1, reg2) | cmpoper (TEMP(temp1), TEMP(temp2)) = Temp.compare (temp1,temp2) | cmpoper (CONST(const1), CONST(const2)) = Word32.compare (const1, const2) @@ -112,28 +187,55 @@ struct | cmpoper (REG _, _) = LESS | cmpoper (REL _, _) = LESS | cmpoper (_, _) = GREATER - + fun opereq (a, b) = cmpoper (a, b) = EQUAL - + + (* integer tostring, except with more - and less ~ *) fun moreDifferentToString (i) = if (i >= 0) then Int.toString i else "-" ^ (Int.toString (~i)) - + + (* pretty prints an operand *) fun prettyprint_oper (REG r) = "%" ^ (regname r) | prettyprint_oper (TEMP t) = Temp.name t | prettyprint_oper (CONST c) = "$0x" ^ (Word32.toString c) | prettyprint_oper (REL (r, i)) = (moreDifferentToString i) ^ "(%" ^ (regname r) ^ ")" + (* pretty prints an operand as a byte *) + fun prettyprint_operb (REG r) = "%" ^ (regnameb r) + | prettyprint_operb (TEMP t) = Temp.name t ^ "b" + | prettyprint_operb (CONST c) = "$0x" ^ (Word32.toString (c mod 0w32)) + | prettyprint_operb x = prettyprint_oper x + + (* pretty prints (no...) *) fun prettyprint (DIRECTIVE(str)) = str ^ "\n" | prettyprint (COMMENT(str)) = "// " ^ str ^ "\n" + | prettyprint (LABEL(l)) = Label.name l ^ "\n" | prettyprint (MOVL(src, dst)) = "\tMOVL\t" ^ (prettyprint_oper src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" | prettyprint (SUBL(src, dst)) = "\tSUBL\t" ^ (prettyprint_oper src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" | prettyprint (IMUL(src, dst)) = "\tIMUL\t" ^ (prettyprint_oper src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" | prettyprint (IMUL3(dst, tmp, const)) = "\tIMUL\t" ^ (prettyprint_oper (CONST const)) ^ ", " ^ (prettyprint_oper tmp) ^ ", " ^ (prettyprint_oper dst) ^ "\n" | prettyprint (ADDL(src, dst)) = "\tADDL\t" ^ (prettyprint_oper src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" - | prettyprint (LEAL(src1, src2, dst)) = "\tLEAL\t(" ^ (prettyprint_oper src1) ^ "," ^ (prettyprint_oper src2) ^ ")," ^ (prettyprint_oper dst) ^ "\n" | prettyprint (IDIVL(src)) = "\tIDIVL\t" ^ (prettyprint_oper src) ^ "\n" | prettyprint (NEG (src)) = "\tNEG\t" ^ (prettyprint_oper src) ^ "\n" + | prettyprint (NOTL (src)) = "\tNOTL\t" ^ (prettyprint_oper src) ^ "\n" + | prettyprint (SALL (dst, shft)) = "\tSALL\t" ^ (prettyprint_oper dst) ^ ", " ^ (prettyprint_operb shft) ^ "\n" + | prettyprint (SARL (dst, shft)) = "\tSARL\t" ^ (prettyprint_oper dst) ^ ", " ^ (prettyprint_operb shft) ^ "\n" + | prettyprint (ANDL(src, dst)) = "\tANDL\t" ^ (prettyprint_oper src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" + | prettyprint (ORL(src, dst)) = "\tORL\t" ^ (prettyprint_oper src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" + | prettyprint (XORL(src, dst)) = "\tXORL\t" ^ (prettyprint_oper src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" + | prettyprint (CMPL(src, dst)) = "\tCMPL\t" ^ (prettyprint_oper src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" + | prettyprint (TEST(src, dst)) = "\tTEST\t" ^ (prettyprint_oper src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" + | prettyprint (SETNE(dst)) = "\tSETNE\t" ^ (prettyprint_operb dst) ^ "\n" + | prettyprint (SETE(dst)) = "\tSETE\t" ^ (prettyprint_operb dst) ^ "\n" + | prettyprint (SETLE(dst)) = "\tSETLE\t" ^ (prettyprint_operb dst) ^ "\n" + | prettyprint (SETL(dst)) = "\tSETL\t" ^ (prettyprint_operb dst) ^ "\n" + | prettyprint (SETGE(dst)) = "\tSETGE\t" ^ (prettyprint_operb dst) ^ "\n" + | prettyprint (SETG(dst)) = "\tSETG\t" ^ (prettyprint_operb dst) ^ "\n" + | prettyprint (JMP(label)) = "\tJMP\t" ^ (Label.name label) ^ "\n" + | prettyprint (JE(label)) = "\tJE\t" ^ (Label.name label) ^ "\n" + | prettyprint (JNE(label)) = "\tJNE\t" ^ (Label.name label) ^ "\n" + | prettyprint (MOVZBL(src, dst)) = "\tMOVZBL\t" ^ (prettyprint_operb src) ^ ", " ^ (prettyprint_oper dst) ^ "\n" | prettyprint (CLTD) = "\tCLTD\n" | prettyprint (RET) = "\tRET\n" (* | prettyprint _ = raise ErrorMsg.InternalError ("prettyprint: unknown instruction")*)