<> <> <> <> Directory Dragon, DragOpsCross, DragonMicroPLA; Imports BitOps, Dragon, DragonIFU; Cedar depth: NAT = 16; gap: NAT = 5; lwx: NAT = 7; lpx: NAT = 32-lwx; m1:NAT = depth-1; ; IStack: CELL [ <<>> <> PushLevel3BA BOOL, IStkTooFullA >BOOL, Lev0BaddrBA > <> ResetAB > RescheduleAB > <<>> iStk: ARRAY [0..depth) OF RECORD [ valid: ARRAY Dragon.Phase OF BOOL _ ALL[FALSE], p: Dragon.HexWord, l: Dragon.HexByte ], pushYoungestA, popYoungestA, pushEldestA, popEldestA, wasEmpty: BOOL _ FALSE EvalSimple b0: DragOpsCross.ProcessorRegister _ DragonIFU.BytetoPR[Lev0BaddrBA]; c3: DragOpsCross.ProcessorRegister _ DragonIFU.BytetoPR[Lev3CaddrBA]; Valid:PROC[index:NAT] RETURNS[BOOLEAN] = { RETURN[NOT ResetAB AND iStk[index MOD depth].valid[a]]}; IF PhA THEN BEGIN top, bot, size: [0..depth] _ depth; delta:INT[-2..+2] _ 0; Dragon.Assert[NOT(IStkPushBA AND PushLevel3BA)]; pushYoungestA _ IStkPushBA OR PushLevel3BA; popYoungestA _ IStkPopBA; pushEldestA _ c3 = ifuEldestPC; popEldestA _ b0 = ifuEldestPC; wasEmpty _ FALSE; IF pushYoungestA THEN delta _ delta+1; IF popYoungestA THEN delta _ delta-1; IF pushEldestA THEN delta _ delta+1; IF popEldestA THEN delta _ delta-1; Dragon.Assert[NOT pushEldestA OR NOT popEldestA, "Not Both at once"]; Dragon.Assert[NOT pushYoungestA OR NOT popYoungestA, "Not Both at once"]; FOR i: NAT IN [0..depth) DO iStk[i].valid[a] _ iStk[i].valid[b] ENDLOOP; FOR i: NAT IN [0..depth) DO IF Valid[i] AND NOT Valid[i+ 1] THEN top _ i; IF Valid[i] AND NOT Valid[i+m1] THEN bot _ i; ENDLOOP; IF top=depth OR bot=depth THEN { Dragon.Assert[top=depth AND bot=depth, "Both or neither"]; top _ 0; bot _ 1; wasEmpty _ TRUE; IF Valid[0] THEN Dragon.Assert[FALSE, "IStack completely full"]}; size _ (top+(depth-bot)+1) MOD depth; SELECT delta+size FROM <0 => Dragon.Assert[FALSE, "IStack Underflowed"]; =0 => {IStkEmptyA _ TRUE; IStkTooFullA _ FALSE}; IN(0..depth-gap] => {IStkEmptyA _ FALSE; IStkTooFullA _ FALSE}; ENDCASE => {IStkEmptyA _ FALSE; IStkTooFullA _ TRUE}; iStk[(top+1) MOD depth] _ [ p:Dragon.LFD[Lev3PBA], l:BitOps.ECFW[Lev3LBA, lwx, 0, lwx] ]; SELECT TRUE FROM b0 IN [ifuYoungestL..ifuEldestPC] => { Dragon.Assert[ NOT wasEmpty ]; SELECT b0 FROM ifuYoungestL => XBus _ BitOps.ICID[iStk[top].l, [0,0], 32, lpx, lwx]; ifuYoungestPC => XBus _ Dragon.LTD[iStk[top].p]; ifuEldestL => XBus _ BitOps.ICID[iStk[bot].l, [0,0], 32, lpx, lwx]; ifuEldestPC => XBus _ Dragon.LTD[iStk[bot].p]; ENDCASE => NULL}; -- Not an IFU stack register c3 IN [ifuYoungestL..ifuEldestPC] => SELECT c3 FROM ifuYoungestL => iStk[top].l _ BitOps.ECFD[XBus, 32, lpx, lwx]; ifuYoungestPC => iStk[top].p _ Dragon.LFD[XBus]; ifuEldestL => iStk[bot].l _ BitOps.ECFD[XBus, 32, lpx, lwx]; ifuEldestPC => iStk[(bot+m1) MOD depth].p _ Dragon.LFD[XBus]; ENDCASE => NULL; -- Not an IFU stack register ENDCASE => NULL; -- nothing special happening END; IF PhB THEN BEGIN FOR i: NAT IN [0..depth) DO iStk[i].valid[b] _ (Valid[i] AND NOT popYoungestA AND NOT popEldestA) OR (Valid[i] AND Valid[i+m1] AND NOT popYoungestA) OR (Valid[i] AND Valid[i+1] AND NOT popEldestA) OR (Valid[i] AND Valid[i+1] AND Valid[i+m1]) OR (Valid[i+1 ] AND pushEldestA) OR (Valid[i+m1] AND pushYoungestA) OR (wasEmpty AND pushEldestA AND i=0) OR (wasEmpty AND pushYoungestA AND i=1); ENDLOOP; FOR i: NAT IN [0..depth) DO IF iStk[i].valid[b] AND NOT iStk[(i+1) MOD depth].valid[b] -- top AND XBSourceBA = iStackPC THEN { Dragon.Assert[ NOT IStkEmptyA ]; XBus _ Dragon.LTD[iStk[i].p]}; ENDLOOP; END; ENDCELL