1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
(*
* This module describes how to fill delay slots on the HPPA
*)
functor HppaDelaySlots
(structure I : HPPAINSTR
structure P : INSN_PROPERTIES (* where I = I *)
where type I.addressing_mode = I.addressing_mode
and type I.ea = I.ea
and type I.instr = I.instr
and type I.instruction = I.instruction
and type I.operand = I.operand
) : DELAY_SLOT_PROPERTIES =
struct
structure I = I
structure C = I.C
structure SL = CellsBasis.SortedCells
fun error msg = MLRiscErrorMsg.error("HppaDelaySlotProps",msg)
datatype delay_slot = D_NONE | D_ERROR | D_ALWAYS | D_TAKEN | D_FALLTHRU
val delaySlotSize = 4
(*
* On the HP, things are quite complicated:
*
* For conditional branches:
* -------------------------
* Branch direction
* Forward Backward
* Nullify bit on Nullify if branch taken Nullify if branch not-taken
* Nullify bit off Delay slot active Delay slot active
*
* For unconditional branches:
* ---------------------------
*
* Nullify bit on Delay slot nullified
* Nullify bit off Delay slot active
*)
fun delaySlot{instr, backward} =
case instr of
I.INSTR(I.BCOND{nop,n,...}) =>
{nop=nop, n=n, nOn=if backward then D_TAKEN else D_FALLTHRU,
nOff=D_ALWAYS}
| I.INSTR(I.BCONDI{nop,n,...}) =>
{nop=nop, n=n, nOn=if backward then D_TAKEN else D_FALLTHRU,
nOff=D_ALWAYS}
| I.INSTR(I.BB{nop,n,...}) =>
{nop=nop, n=n, nOn=if backward then D_TAKEN else D_FALLTHRU,
nOff=D_ALWAYS}
| I.INSTR(I.B{n,...}) => {nop=false, n=n, nOn=D_NONE, nOff=D_ALWAYS}
| I.INSTR(I.LONGJUMP{n,...}) => {nop=false, n=n, nOn=D_NONE, nOff=D_ALWAYS}
| I.INSTR(I.BV{n,...}) => {nop=false, n=n, nOn=D_NONE, nOff=D_ALWAYS}
| I.INSTR(I.BE{n,...}) => {nop=false, n=n, nOn=D_NONE, nOff=D_ALWAYS}
| I.INSTR(I.BLR{n,...}) => {nop=false, n=n, nOn=D_NONE, nOff=D_ALWAYS}
| I.INSTR(I.BL{n,...}) => {nop=false, n=n, nOn=D_NONE, nOff=D_ALWAYS}
| I.ANNOTATION{i,...} => delaySlot{instr=i,backward=backward}
| _ => {n=false,nOn=D_ERROR,nOff=D_NONE,nop=false}
fun enableDelaySlot{instr, n, nop} =
case (instr,nop) of
(I.INSTR(I.BCOND{cmp,bc,r1,r2,t,f,...}),_) =>
I.bcond{cmp=cmp,bc=bc,nop=nop,n=n,r1=r1,r2=r2,t=t,f=f}
| (I.INSTR(I.BCONDI{cmpi,bc,i,r2,t,f,...}),_) =>
I.bcondi{cmpi=cmpi,bc=bc,nop=nop,n=n,i=i,r2=r2,t=t,f=f}
| (I.INSTR(I.BB{bc,p,r,t,f,...}),_) =>
I.bb{bc=bc,p=p,nop=nop,n=n,r=r,t=t,f=f}
| (I.INSTR(I.B{lab,...}),false) => I.b{lab=lab,n=n}
| (I.INSTR(I.BV{labs,b,x,...}),false) => I.bv{labs=labs,b=b,x=x,n=n}
| (I.INSTR(I.BE{labs,b,d,sr,...}),false) => I.be{labs=labs,b=b,d=d,sr=sr,n=n}
| (I.INSTR(I.BLR{x,t,labs,...}),false) => I.blr{x=x,t=t,labs=labs,n=n}
| (I.INSTR(I.BL{lab,t,defs,uses,cutsTo,mem,...}),false) =>
I.bl{lab=lab,t=t,defs=defs,uses=uses,cutsTo=cutsTo,mem=mem,n=n}
| (I.INSTR(I.LONGJUMP{lab,tmp,tmpLab,...}),false) =>
I.longjump{lab=lab,tmp=tmp,tmpLab=tmpLab,n=n}
| (I.ANNOTATION{i,a},_) =>
I.ANNOTATION{i=enableDelaySlot{instr=i,n=n,nop=nop},a=a}
| _ => error "enableDelaySlot"
val defUseI = P.defUse CellsBasis.GP
val defUseF = P.defUse CellsBasis.FP
val zeroR = Option.valOf(C.zeroReg CellsBasis.GP)
fun conflict{src=i,dst=j} =
let fun clash(defUse) =
let val (di,ui) = defUse i
val (dj,uj) = defUse j
in SL.nonEmptyIntersection(di,uj) orelse
SL.nonEmptyIntersection(di,dj) orelse
SL.nonEmptyIntersection(ui,dj)
end
fun defUseInt i =
let val (d,u) = defUseI i
val d = SL.uniq d
val u = SL.uniq u
(* no dependence on register 0! *)
in (SL.rmv(zeroR,d), SL.rmv(zeroR,u)) end
fun defUseReal i =
let val (d,u) = defUseF i
val d = SL.uniq d
val u = SL.uniq u
in (d,u) end
in clash(defUseInt) orelse clash(defUseReal)
end
fun delaySlotCandidate{jmp,delaySlot=
( I.INSTR(I.BCOND _) | I.INSTR(I.BCONDI _) | I.INSTR(I.BB _) | I.INSTR(I.FBRANCH _)
| I.INSTR(I.BV _) | I.INSTR(I.BE _) | I.INSTR(I.COMCLR_LDO _) | I.INSTR(I.COMICLR_LDO _)
| I.INSTR(I.B _) | I.INSTR(I.LONGJUMP _) | I.INSTR(I.BLR _) | I.INSTR(I.BL _)
| I.INSTR(I.BLE _))} = false
| delaySlotCandidate{jmp=I.ANNOTATION{i,...},delaySlot} =
delaySlotCandidate{jmp=i,delaySlot=delaySlot}
| delaySlotCandidate{jmp,delaySlot=I.ANNOTATION{i,...}} =
delaySlotCandidate{jmp=jmp,delaySlot=i}
| delaySlotCandidate _ = true
fun setTarget(I.INSTR(I.BCOND{n,nop,r1,r2,cmp,bc,t,f,...}), lab) =
I.bcond{cmp=cmp,bc=bc,nop=nop,n=n,r1=r1,r2=r2,t=lab,f=f}
| setTarget(I.INSTR(I.BCONDI{n,nop,i,r2,cmpi,bc,t,f,...}), lab) =
I.bcondi{cmpi=cmpi,bc=bc,nop=nop,n=n,i=i,r2=r2,t=lab,f=f}
| setTarget(I.INSTR(I.BB{bc,r,p,n,nop,t,f,...}), lab) =
I.bb{bc=bc,p=p,nop=nop,n=n,r=r,t=lab,f=f}
| setTarget(I.INSTR(I.B{n,...}), lab) = I.b{n=n,lab=lab}
| setTarget(I.INSTR(I.LONGJUMP{n, tmp, tmpLab, ...}), lab) =
I.longjump{n=n, tmp=tmp, tmpLab=tmpLab, lab=lab}
| setTarget(I.ANNOTATION{i,a},lab) = I.ANNOTATION{i=setTarget(i,lab),a=a}
| setTarget _ = error "setTarget"
end
|