RasterOpGreenbayImpl.mesa
Copyright Ó 1988, 1990, 1991 by Xerox Corporation. All rights reserved.
Michael Plass, October 1, 1991 11:34 am PDT
DIRECTORY
Basics,
RasterOp USING [BitAddress, BitsPerSample];
RasterOpGreenbayImpl: PROGRAM
IMPORTS Basics
EXPORTS RasterOp
~ BEGIN OPEN RasterOp, Basics;
bpw: CARDINAL ~ BITS[WORD];
Pack: PUBLIC PROC [dst: BitAddress, src: LONG POINTER TO RawWords, bitsPerSample: BitsPerSample, nSamples: CARDINAL] ~ UNCHECKED {
p: LONG POINTER TO ARRAY [0..0] OF WORD ¬ LOOPHOLE[dst.word];
h: WORD ¬ BITSHIFT[p[0], dst.bit-bpw];
g: [0..bpw] ¬ dst.bit; -- number of good bits at least-sig end of h
j: CARDINAL ¬ 0;
count: CARDINAL ¬ nSamples;
bps: [0..bpw) ~ bitsPerSample;
m: WORD ~ BITLSHIFT[1, bps]-1;
bitsPerSample2: CARDINAL ~ bitsPerSample+bitsPerSample;
bitsPerSample4: CARDINAL ~ bitsPerSample2+bitsPerSample2;
bitsPerSample8: CARDINAL ~ bitsPerSample4+bitsPerSample4;
Combine: PROC [w: WORD, s: WORD] RETURNS [WORD] ~ INLINE {
RETURN [BITOR[BITLSHIFT[w, bps], BITAND[s, m]]]
};
WHILE count >= 8 DO
SELECT CARDINAL[bpw-g] FROM
>= bitsPerSample8 => {
h ¬ Combine[h, src[j]];
h ¬ Combine[h, src[j+1]];
h ¬ Combine[h, src[j+2]];
h ¬ Combine[h, src[j+3]];
h ¬ Combine[h, src[j+4]];
h ¬ Combine[h, src[j+5]];
h ¬ Combine[h, src[j+6]];
h ¬ Combine[h, src[j+7]];
count ¬ count - 8;
j ¬ j + 8;
g ¬ g + bitsPerSample8;
};
>= bitsPerSample4 => {
h ¬ Combine[h, src[j]];
h ¬ Combine[h, src[j+1]];
h ¬ Combine[h, src[j+2]];
h ¬ Combine[h, src[j+3]];
count ¬ count - 4;
j ¬ j + 4;
g ¬ g + bitsPerSample4;
};
>= bitsPerSample2 => {
h ¬ Combine[h, src[j]];
h ¬ Combine[h, src[j+1]];
count ¬ count - 2;
j ¬ j + 2;
g ¬ g + bitsPerSample2;
};
>= bps => {
h ¬ Combine[h, src[j]];
count ¬ count - 1;
j ¬ j + 1;
g ¬ g + bps;
};
ENDCASE => EXIT; -- Need to span a word, so drop through to the slower case below
IF g = bpw THEN {
p[0] ¬ h;
p ¬ p + SIZE[WORD];
g ¬ 0;
};
ENDLOOP;
UNTIL j = nSamples DO
SELECT bpw-g FROM
>= bps => {
There is room for another whole sample in this output word
h ¬ Combine[h, src[j]];
g ¬ g + bps;
};
= 0 => {
The output word is full; store it and get the next sample
p[0] ¬ h;
p ¬ p + SIZE[WORD];
h ¬ src[j];
g ¬ bps;
};
ENDCASE => {
The sample goes partially in this word and partially in the next
k: WORD ~ BITAND[src[j], m];
p[0] ¬ BITLSHIFT[h, bpw-g] + BITRSHIFT[k, bps+g-bpw];
p ¬ p + SIZE[WORD];
h ¬ k;
g ¬ g + bps - bpw;
};
j ¬ j + 1;
ENDLOOP;
IF g # 0 THEN {
p[0] ¬ BITLSHIFT[h, bpw-g]+BITAND[p[0], BITLSHIFT[1, bpw-g]-1];
};
};
Unpack: PUBLIC PROC [dst: LONG POINTER TO RawWords, src: BitAddress, bitsPerSample: BitsPerSample, nSamples: CARDINAL] ~ UNCHECKED {
SELECT TRUE FROM
(nSamples = 0) => NULL;
(bitsPerSample = 1) => {
wordPointer: LONG POINTER TO WORD ¬ @(dst[0]);
srcp: LONG POINTER TO WORD ¬ src.word;
bit: CARDINAL ¬ src.bit;
word: WORD ¬ 0;
count: CARDINAL ¬ nSamples;
IF bit#0 THEN {
word ¬ BITLSHIFT[srcp­, bit];
srcp ¬ srcp + SIZE[WORD];
WHILE count#0 AND bit#bpw DO
Assert[word = BITSHIFT[(srcp-SIZE[WORD])^, bit]];
wordPointer­ ¬ BITRSHIFT[word, bpw-1];
count ¬ count-1;
bit ¬ bit+1;
word ¬ 2*word;
wordPointer ¬ wordPointer + SIZE[WORD];
ENDLOOP;
};
bit ¬ bpw;
WHILE count>=32 DO
a: LONG POINTER TO ARRAY [0..32) OF WORD ~ LOOPHOLE[wordPointer];
lp: LONG POINTER TO PACKED ARRAY [0..32) OF [0..1] ~ LOOPHOLE[srcp];
b: PACKED ARRAY [0..32) OF [0..1] ~ lp­;
a[0] ¬ b[0];  a[1] ¬ b[1];  a[2] ¬ b[2];  a[3] ¬ b[3];
a[4] ¬ b[4];  a[5] ¬ b[5];  a[6] ¬ b[6];  a[7] ¬ b[7];
a[8] ¬ b[8];  a[9] ¬ b[9];  a[10] ¬ b[10]; a[11] ¬ b[11];
a[12] ¬ b[12]; a[13] ¬ b[13]; a[14] ¬ b[14]; a[15] ¬ b[15];
a[16] ¬ b[16]; a[17] ¬ b[17]; a[18] ¬ b[18]; a[19] ¬ b[19];
a[20] ¬ b[20]; a[21] ¬ b[21]; a[22] ¬ b[22]; a[23] ¬ b[23];
a[24] ¬ b[24]; a[25] ¬ b[25]; a[26] ¬ b[26]; a[27] ¬ b[27];
a[28] ¬ b[28]; a[29] ¬ b[29]; a[30] ¬ b[30]; a[31] ¬ b[31];
wordPointer ¬ wordPointer + SIZE[ARRAY [0..32) OF WORD];
count ¬ count - 32;
srcp ¬ srcp + SIZE[PACKED ARRAY [0..32) OF [0..1]];
ENDLOOP;
WHILE count#0 DO
Assert[word = BITSHIFT[(srcp-SIZE[WORD])^, bit]];
IF bit = bpw THEN {bit ¬ 0; word ¬ srcp­; srcp ¬ srcp + SIZE[WORD]};
Assert[word = BITSHIFT[(srcp-SIZE[WORD])^, bit]];
wordPointer­ ¬ BITRSHIFT[word, bpw-1];
count ¬ count-1;
word ¬ 2*word;
wordPointer ¬ wordPointer + SIZE[WORD];
bit ¬ bit+1;
ENDLOOP;
};
((bitsPerSample = 8) AND ((src.bit MOD 8) = 0)) => {
wordPointer: LONG POINTER TO WORD ¬ @(dst[0]);
chunksize: CARDINAL ~ 8; -- to change this, also change assignments in the unrolled loop below. Must be a multiple of BYTES[WORD].
srcp: LONG POINTER TO PACKED ARRAY [0..chunksize) OF BYTE ¬ LOOPHOLE[src.word];
byte: CARDINAL ¬ src.bit/8;
count: CARDINAL ¬ nSamples;
IF byte#0 THEN {
WHILE count#0 AND byte#chunksize DO
wordPointer­ ¬ srcp[byte];
wordPointer ¬ wordPointer + SIZE[WORD];
byte ¬ byte + 1;
count ¬ count-1;
ENDLOOP;
srcp ¬ srcp + SIZE[PACKED ARRAY [0..chunksize) OF BYTE];
byte ¬ 0;
};
WHILE count>=chunksize DO
a: LONG POINTER TO ARRAY [0..chunksize) OF WORD ~ LOOPHOLE[wordPointer];
b: PACKED ARRAY [0..chunksize) OF BYTE ~ srcp­;
a[0] ¬ b[0];  a[1] ¬ b[1];  a[2] ¬ b[2];  a[3] ¬ b[3];
a[4] ¬ b[4];  a[5] ¬ b[5];  a[6] ¬ b[6];  a[7] ¬ b[7];
wordPointer ¬ wordPointer + SIZE[ARRAY [0..chunksize) OF WORD];
count ¬ count - chunksize;
srcp ¬ srcp + SIZE[PACKED ARRAY [0..chunksize) OF BYTE];
ENDLOOP;
WHILE count#0 DO
wordPointer­ ¬ srcp[byte];
wordPointer ¬ wordPointer + SIZE[WORD];
byte ¬ byte + 1;
count ¬ count-1;
ENDLOOP;
};
ENDCASE => {
m: WORD ~ BITLSHIFT[1, bitsPerSample]-1;
p: LONG POINTER TO ARRAY [0..1] OF WORD ¬ LOOPHOLE[src.word];
h: WORD ¬ p[0];
g: INTEGER ¬ bpw-src.bit; -- number of good bits at least-sig end of h
FOR j: CARDINAL IN [0..nSamples) DO
SELECT g FROM
>= bitsPerSample => {
The whole sample is in this word
dst[j] ¬ BITAND[m, BITRSHIFT[h, g-bitsPerSample]];
g ¬ g - bitsPerSample;
};
0 => {
The word is totally exhausted; pull the next one
p ¬ p + SIZE[WORD];
h ¬ p[0];
dst[j] ¬ BITAND[m, BITRSHIFT[h, bpw-bitsPerSample]];
g ¬ bpw - bitsPerSample;
};
ENDCASE => {
The sample is partially in this word and partially in the next
k: WORD ~ p[1];
dst[j] ¬ BITAND[m, BITOR[BITLSHIFT[h, bitsPerSample-g], BITRSHIFT[k, g+bpw-bitsPerSample]]];
h ¬ k;
p ¬ p + SIZE[WORD];
g ¬ g + bpw - bitsPerSample;
};
ENDLOOP;
};
};
END.