|
|
1.1 ! root 1: (* Copyright 1989 by AT&T Bell Laboratories *) ! 2: functor MipsCM(MipsC : MIPSCODER) : CMACHINE = struct ! 3: ! 4: open MipsC System.Tags ! 5: ! 6: fun three f (Direct x, ea, Direct y) = f(x,ea,y) ! 7: | three f (ea, Direct x, Direct y) = f(x,ea,y) ! 8: | three f _ =ErrorMsg.impossible "neither arg to three f is register in mips" ! 9: ! 10: ! 11: val immed = Immed ! 12: fun isimmed(Immed i) = SOME i ! 13: | isimmed _ = NONE ! 14: ! 15: fun isreg(Direct(Reg i)) = SOME i | isreg _ = NONE ! 16: fun eqreg (a: EA) b = a=b ! 17: ! 18: ! 19: ! 20: val standardarg = Direct(Reg 2) ! 21: val standardcont = Direct(Reg 3) ! 22: val standardclosure = Direct(Reg 4) ! 23: val miscregs = map (Direct o Reg) [5,6,7,8,9,10,11,12,13,14, ! 24: 15,16,17,18,19] ! 25: val storeptr as Direct storeptr' = Direct(Reg 22) ! 26: val dataptr as Direct dataptr' = Direct(Reg 23) ! 27: val exnptr = Direct(Reg 30) ! 28: ! 29: (* internal use only *) ! 30: val my_arithtemp as Direct my_arithtemp'= Direct(Reg 20) ! 31: val my_ptrtemp as Direct my_ptrtemp' = Direct(Reg 21) ! 32: ! 33: (* exported for external use *) ! 34: val arithtemp as Direct arithtemp' = Direct(Reg 24) ! 35: val arithtemp2 as Direct arithtemp2'= Direct(Reg 25) ! 36: ! 37: ! 38: fun move (src,Direct dest) = M.move(src, dest) ! 39: | move _ = ErrorMsg.impossible "destination of move not register in mips" ! 40: val align = M.align ! 41: val mark = M.mark ! 42: ! 43: val emitlong = M.emitlong ! 44: val realconst = M.realconst ! 45: val emitstring = M.emitstring ! 46: ! 47: fun emitlab(i,Immedlab lab) = M.emitlab(i,lab) ! 48: | emitlab _ = ErrorMsg.impossible "bad emitlab arg in mips" ! 49: fun newlabel() = Immedlab(M.newlabel()) ! 50: fun define (Immedlab lab) = M.define lab ! 51: | define _ = ErrorMsg.impossible "bad define arg in mips" ! 52: fun record(vl, Direct z) = ! 53: let open CPS ! 54: val len = List.length vl ! 55: fun f(i,nil) = () ! 56: | f(i,(r, SELp(j,p))::rest) = (* follow ptrs to get the item *) ! 57: (M.lw(my_ptrtemp', r, j*4); f(i,(my_ptrtemp,p)::rest)) ! 58: | f(i,(Direct r,OFFp 0)::rest) = (* simple store, last first *) ! 59: (M.sw(r, dataptr, i*4); f(i-1,rest)) ! 60: | f(i,(Direct r, OFFp j)::rest) = ! 61: (M.add(r, Immed(4*j), my_ptrtemp'); ! 62: f(i,(my_ptrtemp,OFFp 0)::rest)) ! 63: | f(i,(ea,p)::rest) = (* convert to register-based *) ! 64: (M.move(ea, my_ptrtemp'); f(i,(my_ptrtemp,p)::rest)) ! 65: in f(len - 1, rev vl); (* store first word in [[0(dataptr')]] *) ! 66: M.add(dataptr', Immed 4, z); ! 67: M.add(dataptr', Immed(4*len), dataptr') ! 68: end ! 69: | record _ = ErrorMsg.impossible "result of record not register in mips" ! 70: ! 71: fun select(i, r, Direct s) = M.lw(s, r, i*4) ! 72: | select _ = ErrorMsg.impossible "result of select not register in mips" ! 73: ! 74: fun offset(i, Direct r, Direct s) = M.add(r,Immed(i*4), s) ! 75: | offset _ = ErrorMsg.impossible "nonregister arg to offset in mips" ! 76: (* fetchindexb(x,y) fetches a byte: y <- mem[x+arithtemp] ! 77: y cannot be arithtemp *) ! 78: fun fetchindexb(x,Direct y) = ! 79: (M.add(arithtemp',x,my_arithtemp'); ! 80: M.lbu(y,my_arithtemp,0)) ! 81: | fetchindexb _ = ErrorMsg.impossible "fetchb result not register in mips" ! 82: ! 83: (* storeindexb(x,y) stores a byte: mem[y+arithtemp] <- x; *) ! 84: fun storeindexb(Direct x,y) = ! 85: (M.add(arithtemp',y,my_arithtemp'); ! 86: M.sb(x,my_arithtemp,0)) ! 87: | storeindexb _ = ErrorMsg.impossible "storeb arg not register in mips" ! 88: ! 89: (* jmpindexb(x) pc <- (x+arithtemp) *) ! 90: fun jmpindexb x = (M.add(arithtemp',x,my_arithtemp'); ! 91: M.jump(my_arithtemp')) ! 92: ! 93: (* fetchindexl(x,y,z) fetches a word: y <- mem[x+2*(z-1)] *) ! 94: (* storeindexl(x,y,z) stores a word: mem[y+2*(z-1)] <- x *) ! 95: ! 96: fun fetchindexl(x,Direct y, Direct z) = ! 97: (M.sll(Immed 1,z,my_arithtemp'); ! 98: M.add(my_arithtemp',x,my_arithtemp'); ! 99: M.lw(y, my_arithtemp,~2)) ! 100: | fetchindexl(x,Direct y, Immed z) = M.lw(y, x, z+z-2) ! 101: | fetchindexl _ = ErrorMsg.impossible "fetchl result not register in mips" ! 102: ! 103: fun storeindexl(Direct x,y, Immed 1) = M.sw(x,y,0) ! 104: | storeindexl(Direct x,y,Direct z) = ! 105: (M.sll(Immed 1,z,my_arithtemp'); ! 106: M.add(my_arithtemp',y,my_arithtemp'); ! 107: M.sw(x, my_arithtemp,~2)) ! 108: | storeindexl(Direct x,y,Immed z) = M.sw(x,y,z+z-2) ! 109: ! 110: | storeindexl(Direct _,_,Immedlab _) = ! 111: ErrorMsg.impossible "storeindexl(Direct _,_,Immedlab _) in mips" ! 112: ! 113: | storeindexl(Immedlab label,y,z) = ! 114: (M.move(Immedlab label,my_ptrtemp'); ! 115: storeindexl(my_ptrtemp,y,z)) ! 116: ! 117: | storeindexl(Immed constant,y,offset) = ! 118: (M.move(Immed constant,my_ptrtemp'); ! 119: storeindexl(my_ptrtemp,y,offset)) ! 120: ! 121: val addl3 = three M.add ! 122: ! 123: fun subl3(Immed k, x, y) = addl3(x, Immed(~k), y) ! 124: | subl3(Direct x, Direct y, Direct z) = M.sub(y,x,z) ! 125: | subl3(x, Immed k, dest) = ! 126: (M.move(Immed k, my_arithtemp'); ! 127: subl3(x, my_arithtemp, dest)) ! 128: | subl3 _ = ErrorMsg.impossible "subl3 args don't match in mips" ! 129: ! 130: fun mull2(Direct x, Direct y) = M.mult(y,x,y) ! 131: | mull2(Immed x, Direct y) = (M.move(Immed x,my_arithtemp'); ! 132: M.mult(y,my_arithtemp',y)) ! 133: | mull2 _ = ErrorMsg.impossible "mull2 args don't match in mips" ! 134: fun divl2(Direct x, Direct y) = M.div(y,x,y) ! 135: | divl2(Immed x, Direct y) = (M.move(Immed x,my_arithtemp'); ! 136: M.div(y,my_arithtemp',y)) ! 137: | divl2 _ = ErrorMsg.impossible "divl2 args don't match in mips" ! 138: ! 139: fun ashr(shamt, Direct op1, Direct result) = M.sra(shamt,op1,result) ! 140: | ashr(shamt, Immed op1, Direct result) = ! 141: (M.move(Immed op1,my_arithtemp'); M.sra(shamt,my_arithtemp',result)) ! 142: | ashr _ = ErrorMsg.impossible "ashr args don't match in mips" ! 143: fun ashl(shamt, Direct op1, Direct result) = M.sll(shamt,op1,result) ! 144: | ashl(shamt, Immed op1, Direct result) = ! 145: (M.move(Immed op1,my_arithtemp'); M.sll(shamt,my_arithtemp',result)) ! 146: | ashl _ = ErrorMsg.impossible "ashl args don't match in mips" ! 147: val addl3t = addl3 ! 148: val subl3t = subl3 ! 149: val ashlt = ashl ! 150: fun mull2t(x,y as Direct y') = ! 151: let val ok = M.newlabel() ! 152: in mull2(x,y); ! 153: M.mfhi(my_arithtemp'); ! 154: M.slt(y',Direct (Reg 0),my_ptrtemp'); (* 0 or 1 OK in pointer *) ! 155: M.add(my_arithtemp',my_ptrtemp,my_arithtemp'); ! 156: M.beq(true,my_arithtemp',Reg 0,ok); (* OK if not overflow *) ! 157: M.lui(my_arithtemp',32767); ! 158: M.add(my_arithtemp',my_arithtemp,my_arithtemp'); (* overflows *) ! 159: M.define(ok) ! 160: end ! 161: | mull2t _ = ErrorMsg.impossible "result of mull2t not register in mips" ! 162: ! 163: val orb = three M.or ! 164: val andb = three M.and' ! 165: fun notb (a,b) = subl3(a, Immed ~1, b) (* ~1 - a == one's complement *) ! 166: val xorb = three M.xor ! 167: datatype condition = NEQ | EQL | LEQ | GEQ | LSS | GTR ! 168: local ! 169: fun makeibranch reverse = ! 170: let ! 171: fun ibranch (cond, Immed a, Immed b, Immedlab label) = ! 172: if (case cond of EQL => a=b | NEQ => a<>b | LSS => a<b | ! 173: LEQ => a<=b | GTR => a>b | GEQ => a>=b) ! 174: then M.beq(true,Reg 0, Reg 0, label) else () ! 175: | ibranch (NEQ, Direct r, Direct s, Immedlab label) = ! 176: M.beq(false, r, s, label) ! 177: | ibranch (NEQ, Direct r, x, Immedlab label) = ! 178: (M.move(x, my_arithtemp'); ! 179: M.beq(false, r, my_arithtemp', label)) ! 180: | ibranch (EQL, Direct r, Direct s, Immedlab label) = ! 181: M.beq(true, r, s, label) ! 182: | ibranch (EQL, Direct r, x, Immedlab label) = ! 183: (M.move(x, my_arithtemp'); ! 184: M.beq(true, r, my_arithtemp', label)) ! 185: | ibranch (LSS, Direct r, x, Immedlab lab) = ! 186: (M.slt(r,x,my_arithtemp'); ! 187: M.beq(false,Reg 0, my_arithtemp',lab)) ! 188: | ibranch (GEQ, Direct r, x, Immedlab lab) = ! 189: (M.slt(r,x,my_arithtemp'); ! 190: M.beq(true,Reg 0, my_arithtemp',lab)) ! 191: | ibranch (GTR, x, Direct r, Immedlab lab) = ! 192: (M.slt(r,x,my_arithtemp'); ! 193: M.beq(false,Reg 0, my_arithtemp',lab)) ! 194: | ibranch (LEQ, x, Direct r, Immedlab lab) = ! 195: (M.slt(r,x,my_arithtemp'); ! 196: M.beq(true,Reg 0, my_arithtemp',lab)) ! 197: (* These two cases added to prevent infinite reversal *) ! 198: | ibranch (GTR, Direct r, x, Immedlab lab) = ! 199: (M.move(x, my_arithtemp'); ! 200: M.slt(my_arithtemp',Direct r,my_arithtemp'); ! 201: M.beq(false,Reg 0,my_arithtemp',lab)) ! 202: | ibranch (LEQ, Direct r, x, Immedlab lab) = ! 203: (M.move(x, my_arithtemp'); ! 204: M.slt(my_arithtemp',Direct r,my_arithtemp'); ! 205: M.beq(true,Reg 0,my_arithtemp',lab)) ! 206: | ibranch (_, Immedlab _, Immedlab _, _) = ! 207: ErrorMsg.impossible "bad ibranch args 1 in mips" ! 208: | ibranch (_, Immedlab _, _, _) = ! 209: ErrorMsg.impossible "bad ibranch args 1a in mips" ! 210: | ibranch (_, _, Immedlab _, _) = ! 211: ErrorMsg.impossible "bad ibranch args 1b in mips" ! 212: | ibranch (_, _, _, Direct _) = ! 213: ErrorMsg.impossible "bad ibranch args 2 in mips" ! 214: | ibranch (_, _, _, Immed _) = ! 215: ErrorMsg.impossible "bad ibranch args 3 in mips" ! 216: | ibranch (cond, x, y, l) = ! 217: let fun rev LEQ = GEQ ! 218: | rev GEQ = LEQ ! 219: | rev LSS = GTR ! 220: | rev GTR = LSS ! 221: | rev NEQ = NEQ ! 222: | rev EQL = EQL ! 223: in if reverse then (makeibranch false) (rev cond, y,x,l) ! 224: else ErrorMsg.impossible "infinite ibranch reversal in mips" ! 225: ! 226: end ! 227: in ibranch ! 228: end ! 229: in ! 230: val ibranch = makeibranch true ! 231: end ! 232: ! 233: fun jmp (Direct r) = M.jump(r) ! 234: | jmp (Immedlab lab) = M.beq(true,Reg 0,Reg 0,lab) ! 235: | jmp (Immed i) = ErrorMsg.impossible "jmp (Immed i) in mips" ! 236: ! 237: ! 238: (* branch on bit set *) ! 239: fun bbs (Immed k, Direct y, Immedlab label) = ! 240: (M.and'(y,Immed (Bits.lshift(1,k)),my_arithtemp'); ! 241: M.beq(false,my_arithtemp',Reg 0,label)) ! 242: | bbs _ = ErrorMsg.impossible "bbs args don't match in mips" ! 243: ! 244: ! 245: val floatop1 = Reg 0 ! 246: val floatop2 = Reg 2 ! 247: val floatresult = Reg 0 ! 248: ! 249: val real_tag = Immed(8*System.Tags.power_tags + System.Tags.tag_string) ! 250: ! 251: fun store_float(Reg n,ea,offset) = ! 252: if n mod 2 <> 0 then ErrorMsg.impossible "bad float reg in mips" ! 253: else (M.swc1(Reg (n+1),ea,offset+4);M.swc1(Reg n,ea,offset)) ! 254: ! 255: fun finish_real (Direct result) = ( ! 256: store_float(floatresult,dataptr,4); ! 257: M.move(real_tag,my_arithtemp'); ! 258: M.sw(my_arithtemp',dataptr,0); ! 259: M.add(dataptr',Immed 4,result); ! 260: M.add(dataptr',Immed 12,dataptr')) ! 261: | finish_real _ = ! 262: ErrorMsg.impossible "ptr to result of real operation not register in mips" ! 263: ! 264: fun load_float(Reg dest,src,offset) = ! 265: if dest mod 2 <> 0 then ErrorMsg.impossible "bad float reg in mips" ! 266: else (M.lwc1(Reg dest,src,offset); M.lwc1(Reg (dest+1),src,offset+4)) ! 267: ! 268: fun two_float instruction (op1,result) = ( ! 269: load_float(floatop1,op1,0); ! 270: instruction(floatop1,floatresult); ! 271: finish_real(result)) ! 272: ! 273: fun three_float instruction (op1,op2,result) = ( ! 274: load_float(floatop1,op1,0); ! 275: load_float(floatop2,op2,0); ! 276: instruction(floatop1,floatop2,floatresult); ! 277: finish_real(result)) ! 278: ! 279: val mnegg = two_float M.neg_double ! 280: val mulg3 = three_float M.mul_double ! 281: val divg3 = three_float M.div_double ! 282: val addg3 = three_float M.add_double ! 283: val subg3 = three_float M.sub_double ! 284: ! 285: ! 286: local ! 287: fun compare(LSS,op1,op2) = (M.slt_double(op1,op2); true) ! 288: | compare(GEQ,op1,op2) = (M.slt_double(op1,op2); false) ! 289: | compare(EQL,op1,op2) = (M.seq_double(op1,op2); true) ! 290: | compare(NEQ,op1,op2) = (M.seq_double(op1,op2); false) ! 291: | compare(LEQ,op1,op2) = compare(GEQ,op2,op1) ! 292: | compare(GTR,op1,op2) = compare(LSS,op2,op1) ! 293: in ! 294: fun gbranch (cond, op1, op2, Immedlab label) = ( ! 295: load_float(floatop1,op1,0); ! 296: load_float(floatop2,op2,0); ! 297: M.bcop1(compare(cond,floatop1,floatop2),label)) ! 298: | gbranch _ = ErrorMsg.impossible "insane gbranch target in mips.nw" ! 299: end ! 300: ! 301: ! 302: fun checkLimit max_allocation = M.sw(Reg 0, dataptr, max_allocation-4) ! 303: (* store zero in last location to be used *) ! 304: ! 305: ! 306: ! 307: fun beginStdFn _ = () (* do nothing, just like the Vax *) ! 308: ! 309: fun profile(i,incr) = () ! 310: ! 311: ! 312: val comment = M.comment ! 313: ! 314: (* +DEBUG *) ! 315: fun diag (s : string) f x = ! 316: f x handle e => ! 317: (print "?exception "; print (System.exn_name e); ! 318: print " in mips."; print s; print "\n"; ! 319: raise e) ! 320: ! 321: val emitlab = diag "emitlab" emitlab ! 322: val define = diag "define" define ! 323: ! 324: ! 325: val record = diag "record" record ! 326: val select = diag "select" select ! 327: val offset = diag "offset" offset ! 328: ! 329: val fetchindexb = diag "fetchindexb" fetchindexb ! 330: val storeindexb = diag "storeindexb" storeindexb ! 331: val jmpindexb = diag "jmpindexb" jmpindexb ! 332: ! 333: ! 334: val fetchindexl = diag "fetchindexl" fetchindexl ! 335: val storeindexl = diag "storeindexl" storeindexl ! 336: ! 337: ! 338: val ashr = diag "ashr" ashr ! 339: val ashl = diag "ashl" ashl ! 340: ! 341: val orb = diag "orb" orb ! 342: val andb = diag "andb" andb ! 343: val notb = diag "notb" notb ! 344: val xorb = diag "xorb" xorb ! 345: ! 346: ! 347: val addl3 = diag "addl3" addl3 ! 348: val subl3 = diag "subl3" subl3 ! 349: val mull2 = diag "mull2" mull2 ! 350: val divl2 = diag "divl2" divl2 ! 351: ! 352: ! 353: val addl3t = diag "addl3t" addl3t ! 354: val subl3t = diag "subl3t" subl3t ! 355: val mull2t = diag "mull2t" mull2t ! 356: val ashlt = diag "ashlt" ashlt ! 357: ! 358: ! 359: val ibranch = diag "ibranch" ibranch ! 360: val jmp = diag "jmp" jmp ! 361: val bbs = diag "bbs" bbs ! 362: ! 363: (* -DEBUG *) ! 364: ! 365: end (* MipsCM *) ! 366:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.