+(* L2 compiler
+ * X86 instruction/operand internal representation and manipulation
+ * Author: Joshua Wise <jwise@andrew.cmu.edu>
+ * Author: Chris Lu <czl@andrew.cmu.edu>
+ *)
+
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
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"
| 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
| 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
| 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)
| 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")*)