|
|
1.1 ! root 1: (* Copyright 1989 by AT&T Bell Laboratories *) ! 2: (* sparcinstr.sml ! 3: * ! 4: * J.H. Reppy ! 5: * Cornell University ! 6: * Ithaca, NY 14853 ! 7: * [email protected] ! 8: * ! 9: * HISTORY: ! 10: * 11/20/89 created ! 11: *) ! 12: ! 13: structure SparcInstr = ! 14: struct ! 15: ! 16: open BaseCoder ! 17: ! 18: datatype register = REG of int ! 19: datatype fregister = FREG of int ! 20: ! 21: datatype labelexp ! 22: = LABELexp of { (* An offset relative to a label. The value of a *) ! 23: base : label, (* label expression is ((dst - base) + offset). *) ! 24: dst : label, ! 25: offset : int ! 26: } ! 27: ! 28: datatype operand ! 29: = REGrand of register (* A register value *) ! 30: | IMrand of int (* A small integer constant (13 bits) *) ! 31: | LABrand of labelexp (* A small valued label expression (13 bits) *) ! 32: | HIrand of labelexp (* The high 22 bits of a label expression *) ! 33: | LOrand of labelexp (* The low 10 bits of a label expression *) ! 34: ! 35: datatype condition = EQL | NEQ | GTR | GEQ | LSS | LEQ ! 36: ! 37: datatype instruction ! 38: = I_nop ! 39: | I_ld of ops3 (* ld: load word *) ! 40: | I_ldb of ops3 (* ldb: load byte (unsigned) *) ! 41: | I_ldf of fmemops (* ldf: load floating-point register *) ! 42: | I_st of ops3 (* st: store word *) ! 43: | I_stb of ops3 (* stb: store byte *) ! 44: | I_stf of fmemops (* stf: store floating-point register *) ! 45: | I_sethi of (operand * register) (* sethi *) ! 46: | I_ba of label (* branch always *) ! 47: | I_bcc of (condition * label) ! 48: | I_fbcc of (condition * label) ! 49: | I_jmpl of ops3 (* jmpl: jump and link *) ! 50: | I_add of ops3 (* add *) ! 51: | I_addcc of ops3 (* add and set condition codes *) ! 52: | I_taddcctv of ops3 (* tagged add with overflow trap *) ! 53: | I_sub of ops3 ! 54: | I_subcc of ops3 (* subtract and set condition codes *) ! 55: | I_sll of ops3 ! 56: | I_sra of ops3 ! 57: | I_and of ops3 ! 58: | I_andcc of ops3 (* logical and and set condition codes *) ! 59: | I_or of ops3 ! 60: | I_xor of ops3 ! 61: | I_not of (register * register) ! 62: | I_tvs (* tvs: trap on integer overflow *) ! 63: | I_fadd of fops3 (* floating-point addition *) ! 64: | I_fsub of fops3 (* floating-point subtraction *) ! 65: | I_fmul of fops3 (* floating-point multiplication *) ! 66: | I_fdiv of fops3 (* floating-point division *) ! 67: | I_fneg of fops2 (* floating-point negation *) ! 68: | I_fcmp of fops2 (* floating-point comparison *) ! 69: withtype ops3 = (register * operand * register) ! 70: and fmemops = (register * operand * fregister) ! 71: and fops3 = (fregister * fregister * fregister) ! 72: and fops2 = (fregister * fregister) ! 73: ! 74: datatype ikind = IK_NOP | IK_JUMP | IK_INSTR ! 75: ! 76: fun instrKind (I_nop) = IK_NOP ! 77: | instrKind (I_ba _) = IK_JUMP ! 78: | instrKind (I_bcc _) = IK_JUMP ! 79: | instrKind (I_fbcc _) = IK_JUMP ! 80: | instrKind (I_jmpl _) = IK_JUMP ! 81: | instrKind _ = IK_INSTR ! 82: ! 83: val nop = I_nop ! 84: ! 85: ! 86: ! 87: (** Span dependent instructions ** ! 88: * The implementation of these instructions depends on the value of the ! 89: * label expressions. The last register argument is a temporary register ! 90: * to be used in address computations (if necessary). ! 91: *) ! 92: ! 93: datatype sdi ! 94: = SetBaseAddr of (bool ref * register * labelexp * register) ! 95: | LoadAddr of (labelexp * register * register) ! 96: | Load of (labelexp * register * register) ! 97: | LoadF of (labelexp * fregister * register) ! 98: ! 99: fun minSize (SetBaseAddr _) = 0 ! 100: | minSize (LoadF _) = 8 ! 101: | minSize _ = 4 ! 102: ! 103: local ! 104: (* Sizes of SDIs *) ! 105: val sz0max = (true, 0) and sz12max = (true, 12) ! 106: val sz16max = (true, 16) and sz20max = (true, 20) ! 107: val sz4 = (false, 4) and sz8 = (false, 8) and sz12 = (false, 12) ! 108: in ! 109: ! 110: (* Return the size of the various span-dependent instructions. This should ! 111: * be consistent with expand in "sparccoder.sml" *) ! 112: fun sizeOf I = let ! 113: fun span (LABELexp{base, dst, offset}) = ! 114: ((addrOf dst) + offset) - (addrOf base) ! 115: fun sizeOf' labexp = let ! 116: val x = span labexp ! 117: in ! 118: if (x < ~4096) orelse (4095 < x) then sz12max else sz4 ! 119: end ! 120: in ! 121: case I ! 122: of SetBaseAddr(ref false, _, _, _) => sz0max ! 123: | SetBaseAddr(ref true, _, labexp, _) => let ! 124: val x = span labexp ! 125: in if (4095 < x) ! 126: then if (8190 < x) ! 127: then sz16max ! 128: else sz12 (* use two subtract immediates *) ! 129: else if (x < ~4096) ! 130: then sz16max ! 131: else sz8 ! 132: end ! 133: | LoadAddr(labexp, _, _) => sizeOf' labexp ! 134: | Load(labexp, _, _) => sizeOf' labexp ! 135: | LoadF(labexp, _, _) => let ! 136: val x = span labexp ! 137: in ! 138: if (x < ~4092) orelse (4092 <= x) then sz20max else sz8 ! 139: end ! 140: end ! 141: ! 142: end (* local *) ! 143: ! 144: local ! 145: val baseReg = REG 27 (* %i3 *) ! 146: val zeroR = REG 0 (* %g0 *) ! 147: val zeroRand = REGrand zeroR ! 148: in ! 149: ! 150: (* expand SDIs into real instruction sequences. *) ! 151: fun expand (SetBaseAddr(ref false, _, _, _), 0) = [] ! 152: | expand (SetBaseAddr(ref true, contReg, labexp, _), 8) = [ ! 153: I_ld(contReg, IMrand 0, baseReg), ! 154: I_sub(baseReg, LABrand labexp, baseReg)] ! 155: | expand (SetBaseAddr(ref true, contReg, LABELexp{base, dst, offset}, _), 12) = let ! 156: val n = if (((addrOf dst) - (addrOf base)) < 0) then ~4096 else 4095 ! 157: val labexp = LABELexp{base=base, dst=dst, offset=offset - n} ! 158: in [ ! 159: I_ld(contReg, zeroRand, baseReg), ! 160: I_sub(baseReg, IMrand n, baseReg), ! 161: I_sub(baseReg, LABrand labexp, baseReg)] ! 162: end ! 163: | expand (SetBaseAddr(ref true, contReg, labexp, tmpR), 16) = [ ! 164: I_ld(contReg, zeroRand, baseReg), ! 165: I_sethi(HIrand labexp, tmpR), ! 166: I_or(tmpR, LOrand labexp, tmpR), ! 167: I_sub(baseReg, REGrand tmpR, baseReg)] ! 168: | expand (LoadAddr(labexp, dst, _), 4) = [I_add(baseReg, LABrand(labexp), dst)] ! 169: | expand (LoadAddr(labexp, dst, tmpR), 12) = [ ! 170: I_sethi(HIrand labexp, tmpR), ! 171: I_or(tmpR, LOrand labexp, tmpR), ! 172: I_add(baseReg, REGrand tmpR, dst)] ! 173: | expand (Load(labexp, dst, _), 4) = [I_ld(baseReg, LABrand(labexp), dst)] ! 174: | expand (Load(labexp, dst, tmpR), 12) = [ ! 175: I_sethi(HIrand(labexp), tmpR), ! 176: I_or(tmpR, LOrand labexp, tmpR), ! 177: I_ld(baseReg, REGrand tmpR, dst)] ! 178: | expand (LoadF(labexp as LABELexp{base, dst, offset}, FREG i, _), 8) = [ ! 179: I_ldf(baseReg, LABrand(labexp), FREG i), ! 180: I_ldf(baseReg, LABrand(LABELexp{base=base, dst=dst, offset=offset+4}), ! 181: FREG(i+1))] ! 182: | expand (LoadF(labexp, FREG i, tmpR), 20) = [ ! 183: I_sethi(HIrand(labexp), tmpR), ! 184: I_or(tmpR, LOrand(labexp), tmpR), ! 185: I_add(baseReg, REGrand tmpR, tmpR), ! 186: I_ldf(tmpR, zeroRand, FREG i), ! 187: I_ldf(tmpR, IMrand 4, FREG(i+1)) ] ! 188: ! 189: end (* local *) ! 190: ! 191: ! 192: (** Resource usage ** ! 193: * ! 194: * The sparc resources are the condition codes, floating-point condition codes, ! 195: * registers %r1-%r31, floating-point registers (viewed as a single resource) ! 196: * and memory. We treat %g6 (the dataptr) specially. We assume that %g6 is ! 197: * only used in 'add', 'taddcctv', 'st', 'stf', and 'or' (move) instructions. ! 198: * We use %g6 to denote the "allocation" resource. This interferes in a ! 199: * non-standard way with the memory resource and with itself. Store instructions ! 200: * using %g6 as a base register don't define the memory resource, but the ! 201: * move of %g6 (using 'or') to another register is an implicit definition of ! 202: * the memory resource (since it makes the allocation visible), the move also ! 203: * defines the allocation resource, since it should only occur after the record ! 204: * has been initialized. There is an implicit use dependency between the ! 205: * 'tvs' instruction and the exnptr register. ! 206: *) ! 207: ! 208: val numRegs = 31 (* %r1-%r31 *) ! 209: ! 210: val numResources = (* registers + fp regs + mem, cond codes, fp cond codes *) ! 211: (numRegs + 4) ! 212: ! 213: local ! 214: val memRId = 0 ! 215: val memR = [memRId] ! 216: fun addRegR (REG 0, lst) = lst ! 217: | addRegR (REG i, lst) = (i :: lst) ! 218: fun regR r = addRegR(r, nil) ! 219: val allocRId = 6 and allocR = [6] ! 220: val exnptrRId = 7 ! 221: val fregsRId = (numRegs + 1) ! 222: val ccRId = (fregsRId + 1) ! 223: val fccRId = (ccRId + 1) ! 224: val fregsR = [fregsRId] ! 225: val ccR = [ccRId] and fccR = [fccRId] ! 226: fun rUseDef3 (a, REGrand b, c) = (addRegR(a, regR b), regR c) ! 227: | rUseDef3 (a, _, c) = (regR a, regR c) ! 228: fun rUseDef3cc (a, REGrand b, c) = (addRegR(a, regR b), ccRId :: (regR c)) ! 229: | rUseDef3cc (a, _, c) = (regR a, ccRId :: (regR c)) ! 230: val fregUseDef = (fregsR, fregsR) ! 231: val allR = let ! 232: fun f (~1, l) = l | f (i, l) = f(i-1, i::l) ! 233: in ! 234: f (numResources-1, nil) ! 235: end ! 236: in ! 237: ! 238: fun rUseDef (I_nop) = ([], []) ! 239: | rUseDef (I_ld args) = let val (u, d) = rUseDef3 args in (memRId :: u, d) end ! 240: | rUseDef (I_ldb args) = let val (u, d) = rUseDef3 args in (memRId :: u, d) end ! 241: | rUseDef (I_ldf(a, REGrand b, c)) = (memRId :: addRegR(a, regR b), fregsR) ! 242: | rUseDef (I_ldf(a, _, c)) = (memRId :: regR a, fregsR) ! 243: | rUseDef (I_st(REG 6, REGrand b, c)) = (6 :: addRegR(b, regR c), []) ! 244: | rUseDef (I_st(REG 6, _, c)) = (6 :: (regR c), []) ! 245: | rUseDef (I_st(a, REGrand b, c)) = (addRegR(a, addRegR(b, regR c)), memR) ! 246: | rUseDef (I_st(a, _, c)) = (addRegR(a, regR c), memR) ! 247: | rUseDef (I_stb(a, REGrand b, c)) = (addRegR(a, addRegR(b, regR c)), memR) ! 248: | rUseDef (I_stb(a, _, c)) = (addRegR(a, regR c), memR) ! 249: | rUseDef (I_stf(REG 6, REGrand b, c)) = (6 :: addRegR(b, fregsR), []) ! 250: | rUseDef (I_stf(REG 6, _, c)) = (6 :: fregsR, []) ! 251: | rUseDef (I_stf(a, REGrand b, c)) = (addRegR(a, addRegR(b, fregsR)), memR) ! 252: | rUseDef (I_stf(a, _, c)) = (addRegR(a, fregsR), memR) ! 253: | rUseDef (I_sethi(_, r)) = ([], regR r) ! 254: | rUseDef (I_ba _) = ([], []) ! 255: | rUseDef (I_bcc _) = (ccR, []) ! 256: | rUseDef (I_fbcc _) = (fccR, []) ! 257: | rUseDef (I_jmpl args) = rUseDef3 args ! 258: | rUseDef (I_add args) = rUseDef3 args ! 259: | rUseDef (I_addcc args) = rUseDef3cc args ! 260: | rUseDef (I_taddcctv _) = (allR, allR) (* GC limit check *) ! 261: | rUseDef (I_sub args) = rUseDef3 args ! 262: | rUseDef (I_subcc args) = rUseDef3cc args ! 263: | rUseDef (I_sll args) = rUseDef3 args ! 264: | rUseDef (I_sra args) = rUseDef3 args ! 265: | rUseDef (I_and args) = rUseDef3 args ! 266: | rUseDef (I_andcc args) = rUseDef3cc args ! 267: | rUseDef (I_or(_, REGrand(REG 6), REG c)) = (* this completes the allocation *) ! 268: ([6], [6, c, memRId]) ! 269: | rUseDef (I_or args) = rUseDef3 args ! 270: | rUseDef (I_xor args) = rUseDef3 args ! 271: | rUseDef (I_not(a, b)) = (regR a, regR b) ! 272: | rUseDef (I_tvs) = ([ccRId, exnptrRId], []) ! 273: | rUseDef (I_fadd args) = fregUseDef ! 274: | rUseDef (I_fsub args) = fregUseDef ! 275: | rUseDef (I_fmul args) = fregUseDef ! 276: | rUseDef (I_fdiv args) = fregUseDef ! 277: | rUseDef (I_fneg(a, b)) = fregUseDef ! 278: | rUseDef (I_fcmp(a, b)) = (fregsR, fccR) ! 279: ! 280: local ! 281: fun uses (r, I) = let ! 282: fun uses3 (REG a, REGrand(REG b), _) = ((r = a) orelse (r = b)) ! 283: | uses3 (REG a, _, _) = (r = a) ! 284: fun st_uses (REG a, REGrand(REG b), REG c) = ! 285: ((r = a) orelse (r = b) orelse (r = c)) ! 286: | st_uses (REG a, _, REG c) = ((r = a) orelse (r = c)) ! 287: in ! 288: case I ! 289: of (I_ld args) => uses3 args ! 290: | (I_ldb args) => uses3 args ! 291: | (I_ldf (REG a, REGrand(REG b), _)) => ((r = a) orelse (r = b)) ! 292: | (I_ldf (REG a, _, _)) => (r = a) ! 293: | (I_st args) => st_uses args ! 294: | (I_stb args) => st_uses args ! 295: | (I_stf (REG a, REGrand(REG b), _)) => ((r = a) orelse (r = b)) ! 296: | (I_stf (REG a, _, _)) => (r = a) ! 297: | (I_jmpl args) => uses3 args ! 298: | (I_add args) => uses3 args ! 299: | (I_addcc args) => uses3 args ! 300: | (I_taddcctv _) => true (* GC limit check *) ! 301: | (I_sub args) => uses3 args ! 302: | (I_subcc args) => uses3 args ! 303: | (I_sll args) => uses3 args ! 304: | (I_sra args) => uses3 args ! 305: | (I_and args) => uses3 args ! 306: | (I_andcc args) => uses3 args ! 307: | (I_or args) => uses3 args ! 308: | (I_xor args) => uses3 args ! 309: | (I_not(REG a, _)) => (r = a) ! 310: | (I_tvs) => (r = exnptrRId) ! 311: | _ => false ! 312: end ! 313: in ! 314: fun hazard (I_ld(_, _, REG dst), I) = uses (dst, I) ! 315: | hazard (I_ldb(_, _, REG dst), I) = uses (dst, I) ! 316: | hazard (I_ldf _, I) = (case I of (I_stf _) => true ! 317: | (I_fadd _) => true | (I_fsub _) => true | (I_fmul _) => true ! 318: | (I_fdiv _) => true | (I_fneg _) => true | (I_fcmp _) => true ! 319: | _ => false) ! 320: | hazard (I, I_stf _) = (case I ! 321: of (I_fadd _) => true | (I_fsub _) => true | (I_fmul _) => true ! 322: | (I_fdiv _) => true | (I_fneg _) => true | (I_fcmp _) => true ! 323: | _ => false) ! 324: | hazard _ = false ! 325: end (* local *) ! 326: end (* local *) ! 327: ! 328: fun needsNop (I_fcmp _, I_fbcc _) = true ! 329: | needsNop _ = false ! 330: ! 331: end (* SparcInstr *)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.