home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / sml_nj / 93src.lha / src / sparc / sparcinstr.sml < prev    next >
Encoding:
Text File  |  1993-01-27  |  12.9 KB  |  330 lines

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