| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- MODULE REG;
- CONST
- N = 16;
- R0* = 0; R1* = 1; R2* = 2; R3* = 3;
- R4* = 4; R5* = 5; R6* = 6; R7* = 7;
- R8* = 8; R9* = 9; R10* = 10; R11* = 11;
- R12* = 12; R13* = 13; R14* = 14; R15* = 15;
- TYPE
- OP1 = PROCEDURE (arg: INTEGER);
- OP2 = PROCEDURE (arg1, arg2: INTEGER);
- REGS* = RECORD
- regs*: SET;
- stk*: ARRAY N OF INTEGER;
- top*: INTEGER;
- pushed*: INTEGER;
- push, pop: OP1;
- mov, xch: OP2
- END;
- PROCEDURE push (VAR R: REGS);
- VAR
- i, reg: INTEGER;
- BEGIN
- reg := R.stk[0];
- INCL(R.regs, reg);
- R.push(reg);
- FOR i := 0 TO R.top - 1 DO
- R.stk[i] := R.stk[i + 1]
- END;
- DEC(R.top);
- INC(R.pushed)
- END push;
- PROCEDURE pop (VAR R: REGS; reg: INTEGER);
- VAR
- i: INTEGER;
- BEGIN
- FOR i := R.top + 1 TO 1 BY -1 DO
- R.stk[i] := R.stk[i - 1]
- END;
- R.stk[0] := reg;
- EXCL(R.regs, reg);
- R.pop(reg);
- INC(R.top);
- DEC(R.pushed)
- END pop;
- PROCEDURE InStk (R: REGS; reg: INTEGER): INTEGER;
- VAR
- i: INTEGER;
- BEGIN
- i := R.top;
- WHILE (i >= 0) & (R.stk[i] # reg) DO
- DEC(i)
- END
- RETURN i
- END InStk;
- PROCEDURE GetFreeReg (R: REGS): INTEGER;
- VAR
- i: INTEGER;
- BEGIN
- i := 0;
- WHILE (i < N) & ~(i IN R.regs) DO
- INC(i)
- END;
- IF i = N THEN
- i := -1
- END
- RETURN i
- END GetFreeReg;
- PROCEDURE Put (VAR R: REGS; reg: INTEGER);
- BEGIN
- EXCL(R.regs, reg);
- INC(R.top);
- R.stk[R.top] := reg
- END Put;
- PROCEDURE PopAnyReg (VAR R: REGS): INTEGER;
- VAR
- reg: INTEGER;
- BEGIN
- reg := GetFreeReg(R);
- ASSERT(reg # -1);
- ASSERT(R.top < LEN(R.stk) - 1);
- ASSERT(R.pushed > 0);
- pop(R, reg)
- RETURN reg
- END PopAnyReg;
- PROCEDURE GetAnyReg* (VAR R: REGS): INTEGER;
- VAR
- reg: INTEGER;
- BEGIN
- reg := GetFreeReg(R);
- IF reg = -1 THEN
- ASSERT(R.top >= 0);
- reg := R.stk[0];
- push(R)
- END;
- Put(R, reg)
- RETURN reg
- END GetAnyReg;
- PROCEDURE GetReg* (VAR R: REGS; reg: INTEGER): BOOLEAN;
- VAR
- free: INTEGER;
- res: BOOLEAN;
- PROCEDURE exch (VAR R: REGS; reg1, reg2: INTEGER);
- VAR
- n1, n2: INTEGER;
- BEGIN
- n1 := InStk(R, reg1);
- n2 := InStk(R, reg2);
- R.stk[n1] := reg2;
- R.stk[n2] := reg1;
- R.xch(reg1, reg2)
- END exch;
- BEGIN
- IF reg IN R.regs THEN
- Put(R, reg);
- res := TRUE
- ELSE
- res := InStk(R, reg) # -1;
- IF res THEN
- free := GetFreeReg(R);
- IF free # -1 THEN
- Put(R, free);
- exch(R, reg, free)
- ELSE
- push(R);
- free := GetFreeReg(R);
- ASSERT(free # -1);
- Put(R, free);
- IF free # reg THEN
- exch(R, reg, free)
- END
- END
- END
- END
- RETURN res
- END GetReg;
- PROCEDURE Exchange* (VAR R: REGS; reg1, reg2: INTEGER): BOOLEAN;
- VAR
- n1, n2: INTEGER;
- res: BOOLEAN;
- BEGIN
- res := TRUE;
- IF reg1 # reg2 THEN
- n1 := InStk(R, reg1);
- n2 := InStk(R, reg2);
- IF (n1 # -1) & (n2 # -1) THEN
- R.stk[n1] := reg2;
- R.stk[n2] := reg1;
- R.xch(reg2, reg1)
- ELSIF (n1 # -1) & (reg2 IN R.regs) THEN
- R.stk[n1] := reg2;
- INCL(R.regs, reg1);
- EXCL(R.regs, reg2);
- R.mov(reg2, reg1)
- ELSIF (n2 # -1) & (reg1 IN R.regs) THEN
- R.stk[n2] := reg1;
- EXCL(R.regs, reg1);
- INCL(R.regs, reg2);
- R.mov(reg1, reg2)
- ELSE
- res := FALSE
- END
- END
- RETURN res
- END Exchange;
- PROCEDURE Drop* (VAR R: REGS);
- BEGIN
- INCL(R.regs, R.stk[R.top]);
- DEC(R.top)
- END Drop;
- PROCEDURE BinOp* (VAR R: REGS; VAR reg1, reg2: INTEGER);
- BEGIN
- IF R.top > 0 THEN
- reg1 := R.stk[R.top - 1];
- reg2 := R.stk[R.top]
- ELSIF R.top = 0 THEN
- reg1 := PopAnyReg(R);
- reg2 := R.stk[1]
- ELSE (* R.top = -1 *)
- reg2 := PopAnyReg(R);
- reg1 := PopAnyReg(R)
- END
- END BinOp;
- PROCEDURE UnOp* (VAR R: REGS; VAR reg: INTEGER);
- BEGIN
- IF R.top >= 0 THEN
- reg := R.stk[R.top]
- ELSE
- reg := PopAnyReg(R)
- END
- END UnOp;
- PROCEDURE PushAll* (VAR R: REGS);
- BEGIN
- WHILE R.top >= 0 DO
- push(R)
- END
- END PushAll;
- PROCEDURE PushAll_1* (VAR R: REGS);
- BEGIN
- WHILE R.top >= 1 DO
- push(R)
- END
- END PushAll_1;
- PROCEDURE Init* (VAR R: REGS; push, pop: OP1; mov, xch: OP2; regs: SET);
- BEGIN
- R.regs := regs;
- R.pushed := 0;
- R.top := -1;
- R.push := push;
- R.pop := pop;
- R.mov := mov;
- R.xch := xch;
- END Init;
- END REG.
|