RasterOpCharBltImpl.mesa
Copyright Ó 1988, 1990, 1991 by Xerox Corporation. All rights reserved.
Russ Atkinson (RRA) October 29, 1990 1:58 pm PST
Michael Plass, October 1, 1991 11:09 am PDT
DIRECTORY
RasterOp USING [Offset],
Basics;
RasterOpCharBltImpl: PROGRAM
IMPORTS Basics
EXPORTS RasterOp
= BEGIN OPEN Basics;
Word: TYPE = WORD;
WordPtr: TYPE = LONG POINTER TO Word;
Offset: TYPE = RasterOp.Offset;
bpw: CARDINAL = BITS[Word];
upw: CARDINAL = SIZE[Word];
bpu: CARDINAL = BITS[UNIT];
OrBlt: PUBLIC PROC
[src: WordPtr, dst: WordPtr, offset: Offset, bpc: CARDINAL, upl: INT, lines: INT] = {
sw: Word;
dw: Word;
tw: Word ¬ offset+bpc;
shiftL: Offset;
GetD: PROC [dstOff: CARDINAL] = INLINE {dw ¬ (dst+dstOff)­};
GetS: PROC [srcOff: CARDINAL] = INLINE {sw ¬ (src+srcOff)­};
Put: PROC [dstOff: CARDINAL] = INLINE {(dst+dstOff)­ ¬ dw};
Func: PROC = INLINE {dw ¬ BITOR[dw, sw]};
FuncT: PROC = INLINE {dw ¬ BITOR[dw, tw]};
FuncShR: PROC = INLINE {tw ¬ BITRSHIFT[sw, offset]; FuncT[]};
FuncShL: PROC = INLINE {tw ¬ BITLSHIFT[sw, shiftL]; FuncT[]};
BumpD: PROC = INLINE {dst ¬ dst + upl};
SELECT TRUE FROM
bpc <= bpw => {
IF tw <= bpw
THEN {
Each scan line fits in a single dst word
IF offset = 0
THEN {
The aligned case, no shifting
DoOne: PROC = INLINE {GetD[0]; Func[]; Put[0]};
DO
IF lines >= 4 THEN {
GetS[0*upw]; DoOne[]; BumpD[];
GetS[1*upw]; DoOne[]; BumpD[];
GetS[2*upw]; DoOne[]; BumpD[];
GetS[3*upw]; DoOne[]; BumpD[];
src ¬ src + upw*4;
lines ¬ lines - 4;
LOOP;
};
IF lines = 0 THEN RETURN;
GetS[0*upw]; DoOne[];
IF lines = 1 THEN RETURN;
GetS[1*upw]; BumpD[]; DoOne[];
IF lines = 2 THEN RETURN;
GetS[2*upw]; BumpD[]; DoOne[];
RETURN;
ENDLOOP;
}
ELSE {
Unaligned, but still in one dst word
DoOne: PROC = INLINE {GetD[0]; FuncShR[]; Put[0]};
DO
IF lines >= 4 THEN {
GetS[0*upw]; DoOne[]; BumpD[];
GetS[1*upw]; DoOne[]; BumpD[];
GetS[2*upw]; DoOne[]; BumpD[];
GetS[3*upw]; DoOne[]; BumpD[];
src ¬ src + upw*4;
lines ¬ lines - 4;
LOOP;
};
IF lines = 0 THEN RETURN;
GetS[0*upw]; DoOne[];
IF lines = 1 THEN RETURN;
GetS[1*upw]; BumpD[]; DoOne[];
IF lines = 2 THEN RETURN;
GetS[2*upw]; BumpD[]; DoOne[];
RETURN;
ENDLOOP;
};
}
ELSE {
Each scan line fits in a single src word, 2 dst words
DoOne: PROC = INLINE {
GetD[0]; FuncShR[]; Put[0];
GetD[upw]; FuncShL[]; Put[upw];
};
shiftL ¬ bpw - offset;
DO
IF lines >= 4 THEN {
GetS[0*upw]; DoOne[]; BumpD[];
GetS[1*upw]; DoOne[]; BumpD[];
GetS[2*upw]; DoOne[]; BumpD[];
GetS[3*upw]; DoOne[]; BumpD[];
src ¬ src + upw*4;
lines ¬ lines - 4;
LOOP;
};
IF lines = 0 THEN RETURN;
GetS[0*upw]; DoOne[];
IF lines = 1 THEN RETURN;
GetS[1*upw]; BumpD[]; DoOne[];
IF lines = 2 THEN RETURN;
GetS[2*upw]; BumpD[]; DoOne[];
RETURN;
ENDLOOP;
};
};
bpc <= bpw*2 => {
Each char is 2 words per scan line
IF offset = 0
THEN {
Two-word aligned
WHILE lines > 0 DO
GetD[0]; GetS[0]; Func[]; Put[0];
GetD[upw]; GetS[upw]; Func[]; Put[upw];
src ¬ src + upw*2;
dst ¬ dst + upl;
lines ¬ lines - 1;
ENDLOOP;
RETURN;
}
ELSE {
Two-word unaligned
shiftL ¬ bpw - offset;
IF tw <= bpw*2
THEN {
Two src words, two dst words
WHILE lines > 0 DO
GetD[upw*0]; <<no ShL>> GetS[upw*0]; FuncShR[]; Put[upw*0];
GetD[upw*1]; FuncShL[]; GetS[upw*1]; FuncShR[]; Put[upw*1];
src ¬ src + upw*2;
dst ¬ dst + upl;
lines ¬ lines - 1;
ENDLOOP;
}
ELSE {
Two src words, three dst words
WHILE lines > 0 DO
GetD[upw*0]; <<no ShL>> GetS[upw*0]; FuncShR[]; Put[upw*0];
GetD[upw*1]; FuncShL[]; GetS[upw*1]; FuncShR[]; Put[upw*1];
GetD[upw*2]; FuncShL[]; <<no src[2]>> <<no ShR>> Put[upw*2];
src ¬ src + upw*2;
dst ¬ dst + upl;
lines ¬ lines - 1;
ENDLOOP;
};
RETURN;
};
};
ENDCASE => {
Multi-word transfers
rem: CARD;
IF offset = 0
THEN {
Multi-word aligned
bpc ¬ bpc - bpw;
WHILE lines > 0 DO
nextDst: WordPtr = dst + upl;
rem ¬ bpc;
GetD[0]; GetS[0]; Func[]; Put[0];
DO
dst ¬ dst + upw;
src ¬ src + upw;
GetD[0]; GetS[0]; Func[]; Put[0];
IF rem <= bpw THEN EXIT;
rem ¬ rem - bpw;
ENDLOOP;
dst ¬ nextDst;
src ¬ src + upw;
lines ¬ lines - 1;
ENDLOOP;
RETURN;
}
ELSE {
Multi-word unaligned
shiftL ¬ bpw - offset;
WHILE lines > 0 DO
nextDst: WordPtr = dst + upl;
rem ¬ bpc;
GetD[0];
DO
GetS[0]; FuncShR[]; Put[0];
dst ¬ dst + upw;
GetD[0]; FuncShL[];
src ¬ src + upw;
IF rem <= bpw THEN EXIT;
rem ¬ rem - bpw;
ENDLOOP;
Put[0];
dst ¬ nextDst;
lines ¬ lines - 1;
ENDLOOP;
RETURN;
};
};
};
AndCBlt: PUBLIC PROC
[src: WordPtr, dst: WordPtr, offset: Offset, bpc: CARDINAL, upl: INT, lines: INT] = {
sw: Word;
dw: Word;
tw: Word ¬ offset+bpc;
shiftL: Offset;
GetD: PROC [dstOff: CARDINAL] = INLINE {dw ¬ (dst+dstOff)­};
GetS: PROC [srcOff: CARDINAL] = INLINE {sw ¬ (src+srcOff)­};
Put: PROC [dstOff: CARDINAL] = INLINE {(dst+dstOff)­ ¬ dw};
Func: PROC = INLINE {dw ¬ BITAND[dw, BITNOT[sw]]};
FuncT: PROC = INLINE {dw ¬ BITAND[dw, BITNOT[tw]]};
FuncShR: PROC = INLINE {tw ¬ BITRSHIFT[sw, offset]; FuncT[]};
FuncShL: PROC = INLINE {tw ¬ BITLSHIFT[sw, shiftL]; FuncT[]};
BumpD: PROC = INLINE {dst ¬ dst + upl};
SELECT TRUE FROM
bpc <= bpw => {
IF tw <= bpw
THEN {
Each scan line fits in a single dst word
IF offset = 0
THEN {
The aligned case, no shifting
DoOne: PROC = INLINE {GetD[0]; Func[]; Put[0]};
DO
IF lines >= 4 THEN {
GetS[0*upw]; DoOne[]; BumpD[];
GetS[1*upw]; DoOne[]; BumpD[];
GetS[2*upw]; DoOne[]; BumpD[];
GetS[3*upw]; DoOne[]; BumpD[];
src ¬ src + upw*4;
lines ¬ lines - 4;
LOOP;
};
IF lines = 0 THEN RETURN;
GetS[0*upw]; DoOne[];
IF lines = 1 THEN RETURN;
GetS[1*upw]; BumpD[]; DoOne[];
IF lines = 2 THEN RETURN;
GetS[2*upw]; BumpD[]; DoOne[];
RETURN;
ENDLOOP;
}
ELSE {
Unaligned, but still in one dst word
DoOne: PROC = INLINE {GetD[0]; FuncShR[]; Put[0]};
DO
IF lines >= 4 THEN {
GetS[0*upw]; DoOne[]; BumpD[];
GetS[1*upw]; DoOne[]; BumpD[];
GetS[2*upw]; DoOne[]; BumpD[];
GetS[3*upw]; DoOne[]; BumpD[];
src ¬ src + upw*4;
lines ¬ lines - 4;
LOOP;
};
IF lines = 0 THEN RETURN;
GetS[0*upw]; DoOne[];
IF lines = 1 THEN RETURN;
GetS[1*upw]; BumpD[]; DoOne[];
IF lines = 2 THEN RETURN;
GetS[2*upw]; BumpD[]; DoOne[];
RETURN;
ENDLOOP;
};
}
ELSE {
Each scan line fits in a single src word, 2 dst words
DoOne: PROC = INLINE {
GetD[0]; FuncShR[]; Put[0];
GetD[upw]; FuncShL[]; Put[upw];
};
shiftL ¬ bpw - offset;
DO
IF lines >= 4 THEN {
GetS[0*upw]; DoOne[]; BumpD[];
GetS[1*upw]; DoOne[]; BumpD[];
GetS[2*upw]; DoOne[]; BumpD[];
GetS[3*upw]; DoOne[]; BumpD[];
src ¬ src + upw*4;
lines ¬ lines - 4;
LOOP;
};
IF lines = 0 THEN RETURN;
GetS[0*upw]; DoOne[];
IF lines = 1 THEN RETURN;
GetS[1*upw]; BumpD[]; DoOne[];
IF lines = 2 THEN RETURN;
GetS[2*upw]; BumpD[]; DoOne[];
RETURN;
ENDLOOP;
};
};
bpc <= bpw*2 => {
Each char is 2 words per scan line
IF offset = 0
THEN {
Two-word aligned
WHILE lines > 0 DO
GetD[0]; GetS[0]; Func[]; Put[0];
GetD[upw]; GetS[upw]; Func[]; Put[upw];
src ¬ src + upw*2;
dst ¬ dst + upl;
lines ¬ lines - 1;
ENDLOOP;
RETURN;
}
ELSE {
Two-word unaligned
shiftL ¬ bpw - offset;
IF tw <= bpw*2
THEN {
Two src words, two dst words
WHILE lines > 0 DO
GetD[upw*0]; <<no ShL>> GetS[upw*0]; FuncShR[]; Put[upw*0];
GetD[upw*1]; FuncShL[]; GetS[upw*1]; FuncShR[]; Put[upw*1];
src ¬ src + upw*2;
dst ¬ dst + upl;
lines ¬ lines - 1;
ENDLOOP;
}
ELSE {
Two src words, three dst words
WHILE lines > 0 DO
GetD[upw*0]; <<no ShL>> GetS[upw*0]; FuncShR[]; Put[upw*0];
GetD[upw*1]; FuncShL[]; GetS[upw*1]; FuncShR[]; Put[upw*1];
GetD[upw*2]; FuncShL[]; <<no src[2]>> <<no ShR>> Put[upw*2];
src ¬ src + upw*2;
dst ¬ dst + upl;
lines ¬ lines - 1;
ENDLOOP;
};
RETURN;
};
};
ENDCASE => {
Multi-word transfers
rem: CARD;
IF offset = 0
THEN {
Multi-word aligned
bpc ¬ bpc - bpw;
WHILE lines > 0 DO
nextDst: WordPtr = dst + upl;
rem ¬ bpc;
GetD[0]; GetS[0]; Func[]; Put[0];
DO
dst ¬ dst + upw;
src ¬ src + upw;
GetD[0]; GetS[0]; Func[]; Put[0];
IF rem <= bpw THEN EXIT;
rem ¬ rem - bpw;
ENDLOOP;
dst ¬ nextDst;
src ¬ src + upw;
lines ¬ lines - 1;
ENDLOOP;
RETURN;
}
ELSE {
Multi-word unaligned
shiftL ¬ bpw - offset;
WHILE lines > 0 DO
nextDst: WordPtr = dst + upl;
rem ¬ bpc;
GetD[0];
DO
GetS[0]; FuncShR[]; Put[0];
dst ¬ dst + upw;
GetD[0]; FuncShL[];
src ¬ src + upw;
IF rem <= bpw THEN EXIT;
rem ¬ rem - bpw;
ENDLOOP;
Put[0];
dst ¬ nextDst;
lines ¬ lines - 1;
ENDLOOP;
RETURN;
};
};
};
FillWords: PUBLIC PROC [dst: WordPtr, len: INT, fill: Word] = {
WHILE len >= 8 DO
(dst+0*upw)­ ¬ fill;
(dst+1*upw)­ ¬ fill;
(dst+2*upw)­ ¬ fill;
(dst+3*upw)­ ¬ fill;
(dst+4*upw)­ ¬ fill;
(dst+5*upw)­ ¬ fill;
(dst+6*upw)­ ¬ fill;
(dst+7*upw)­ ¬ fill;
dst ¬ dst + 8*upw;
len ¬ len - 8;
ENDLOOP;
IF len >= 4 THEN {
(dst+0*upw)­ ¬ fill;
(dst+1*upw)­ ¬ fill;
(dst+2*upw)­ ¬ fill;
(dst+3*upw)­ ¬ fill;
dst ¬ dst + 4*upw;
len ¬ len - 4;
};
IF len >= 2 THEN {
(dst+0*upw)­ ¬ fill;
(dst+1*upw)­ ¬ fill;
dst ¬ dst + 2*upw;
len ¬ len - 2;
};
IF len >= 1 THEN {
(dst+0*upw)­ ¬ fill;
};
};
END.