Exporting functions for MIPSCODER

We now know enough to implement most of the functions called for in [[MIPSCODER]]. We still haven't decided on an implementation of labels, and there is one subtlety in multiplication and division, but the rest is set. «[[MIPSCODER]] functions»= val emitstring = keep STRINGCONST (* literals *) exception BadReal = IEEEReal.BadReal val low_order_offset = Emitter.low_order_offset val realconst = keep (STRINGCONST o order_real o IEEEReal.realconst) val emitlong = keep EMITLONG «label functions» (* labels *) val slt = keep SLT (* control flow *) val beq = delay BEQ val jump = delay JUMP val slt_double = delay SLT_D val seq_double = delay SEQ_D val bcop1 = delay BCOP1 val add = keep ADD (* arithmetic *) val and' = keep AND val or = keep OR val xor = keep XOR val op sub = keep SUB «multiplication and division functions» val neg_double = keep NEG_D val mul_double = keep MUL_D val div_double = keep DIV_D val add_double = keep ADD_D val sub_double = keep SUB_D val move = keep MOVE fun lbu (a,b,c) = delay LOAD (Byte,a,b,c) (* load and store *) fun lw (a,b,c) = delay LOAD (Word,a,b,c) fun lwc1 (a,b,c) = delay LOAD (Floating,a,b,c) fun sb (a,b,c) = keep STORE (Byte,a,b,c) fun sw (a,b,c) = keep STORE (Word,a,b,c) fun swc1 (a,b,c) = delay STORE (Floating,a,b,c) val lui = keep LUI val sll = keep SLL (* shift *) val sra = keep SRA fun align() = () (* never need to align on MIPS *) val mark = keep (fn () => MARK) val comment = keep COMMENT @ Multiplication has a minor complication; the result has to be fetched from the LO register. «multiplication and division functions»= fun mult (op1, op2, result) = keeplist [MFLO result, MULT (op1, op2)] val mfhi = keep MFHI @ Division has a major complication; I must test for divide by zero since the hardware does not. If the divisor is zero, I cause an overflow exception by adding [[limitreg]] to itself. «multiplication and division functions»= fun op div (op1, op2, result) = let val next = newlabel() in keeplist [ MFLO result, (* get the result *) DEFINE next, (* skip to here if nonzero *) BREAK 7, (* signals zerodivide *) DIV (op1, op2), (* divide in delay slot *) BEQ (false, Reg 0, op2, next) (* skip if divisor nonzero *) ] end @ For now, labels are just pointers to integers. During code generation, those integers will be set to positions in the instruction stream, and then they'll be useful as addresses relative to the program counter pointer (to be held in [[Reg pcreg]]). «definition of [[Label]]»= type Label = int ref «label functions»= fun newlabel () = ref 0 val define = keep DEFINE val emitlab = keep EMITLAB @ Here's the overall plan of this structure: «*»= functor MipsCoder(Emitter: EMITTER) : MIPSCODER = struct open Emitter «definition of [[Label]]» datatype Register = Reg of int datatype EA = Direct of Register | Immed of int | Immedlab of Label «definition of [[instr]]» «instruction stream and its functions» structure M = struct «[[MIPSCODER]] functions» end open M «functions that assemble [[instr]]s into code» «statistics» end (* MipsInstr *) @