Annotation of researchv10no/cmd/sml/src/sparc/sparcinstr.sml, revision 1.1.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.