Annotation of researchv10no/cmd/sml/src/sparc/sparcinstr.sml, revision 1.1

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 *)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.