|
@@ -1396,6 +1396,12 @@ BEGIN
|
|
|
Ebyte (0C6H) ; Ebyte (45H) ; Ebyte (VAL (BYTE, off)) ; Ebyte (VAL (BYTE, v))
|
|
Ebyte (0C6H) ; Ebyte (45H) ; Ebyte (VAL (BYTE, off)) ; Ebyte (VAL (BYTE, v))
|
|
|
END EmStDiImm ;
|
|
END EmStDiImm ;
|
|
|
|
|
|
|
|
|
|
+PROCEDURE EmStDiAlOff (off : CARDINAL) ;
|
|
|
|
|
+(* MOV [DI+off],AL: one byte of a real copied through a DI-addressed field. *)
|
|
|
|
|
+BEGIN
|
|
|
|
|
+ Ebyte (88H) ; Ebyte (45H) ; Ebyte (VAL (BYTE, off))
|
|
|
|
|
+END EmStDiAlOff ;
|
|
|
|
|
+
|
|
|
PROCEDURE EmLdAlDiOff (off : CARDINAL) ;
|
|
PROCEDURE EmLdAlDiOff (off : CARDINAL) ;
|
|
|
(* MOV AL,[DI+off]: the byte of a set variable that holds an element's bit. *)
|
|
(* MOV AL,[DI+off]: the byte of a set variable that holds an element's bit. *)
|
|
|
BEGIN
|
|
BEGIN
|
|
@@ -3872,16 +3878,138 @@ BEGIN
|
|
|
END
|
|
END
|
|
|
END ParseLabelStmt ;
|
|
END ParseLabelStmt ;
|
|
|
|
|
|
|
|
|
|
+PROCEDURE IntToMbf (v : LONGINT ; VAR b : ARRAY OF CHAR) ;
|
|
|
|
|
+(* TP3's 6-byte Real, as measured in CALC-PORT.md against the cells holding
|
|
|
|
|
+ 1, 2, 3, 4 and 5:
|
|
|
|
|
+
|
|
|
|
|
+ value = (1 + N / 2^39) * 2^(E - 129)
|
|
|
|
|
+
|
|
|
|
|
+ byte 0 is E (biased by 129); bytes 1..5 are N, little-endian; the SIGN is
|
|
|
|
|
+ bit 7 of byte 5 (the book's `sign + 39-bit mantissa'). An all-zero value
|
|
|
|
|
+ is 0.0. 1 -> 81 00 00 00 00 00, 3 -> 82 00 00 00 00 40,
|
|
|
|
|
+ 5 -> 83 00 00 00 00 20 - all cross-checked against CALCDEMO.MCS.
|
|
|
|
|
+
|
|
|
|
|
+ Only INTEGER values are converted; real arithmetic and formatting are a
|
|
|
|
|
+ later stage, and a real RHS that is not a constant or a copy is ENoLib. *)
|
|
|
|
|
+VAR a, p, n : LONGINT ;
|
|
|
|
|
+ e, k, i : CARDINAL ;
|
|
|
|
|
+ neg : BOOLEAN ;
|
|
|
|
|
+BEGIN
|
|
|
|
|
+ i := 0 ;
|
|
|
|
|
+ WHILE i < 6 DO
|
|
|
|
|
+ b [i] := CHR (0) ;
|
|
|
|
|
+ INC (i)
|
|
|
|
|
+ END ;
|
|
|
|
|
+ IF v = 0 THEN
|
|
|
|
|
+ RETURN
|
|
|
|
|
+ END ;
|
|
|
|
|
+ neg := v < 0 ;
|
|
|
|
|
+ IF neg THEN
|
|
|
|
|
+ a := -v
|
|
|
|
|
+ ELSE
|
|
|
|
|
+ a := v
|
|
|
|
|
+ END ;
|
|
|
|
|
+ (* k = floor(log2(a)); p = 2^k *)
|
|
|
|
|
+ p := 1 ;
|
|
|
|
|
+ k := 0 ;
|
|
|
|
|
+ WHILE (k < 39) AND (p * 2 <= a) DO
|
|
|
|
|
+ p := p * 2 ;
|
|
|
|
|
+ INC (k)
|
|
|
|
|
+ END ;
|
|
|
|
|
+ IF k >= 39 THEN
|
|
|
|
|
+ Err (EConstRange) ;
|
|
|
|
|
+ RETURN
|
|
|
|
|
+ END ;
|
|
|
|
|
+ e := 129 + k ;
|
|
|
|
|
+ b [0] := CHR (e) ;
|
|
|
|
|
+ n := a - p ;
|
|
|
|
|
+ i := 39 - k ;
|
|
|
|
|
+ WHILE i > 0 DO
|
|
|
|
|
+ n := n * 2 ;
|
|
|
|
|
+ DEC (i)
|
|
|
|
|
+ END ;
|
|
|
|
|
+ i := 1 ;
|
|
|
|
|
+ WHILE i <= 5 DO
|
|
|
|
|
+ b [i] := CHR (VAL (CARDINAL, n MOD 256)) ;
|
|
|
|
|
+ n := n DIV 256 ;
|
|
|
|
|
+ INC (i)
|
|
|
|
|
+ END ;
|
|
|
|
|
+ IF neg THEN
|
|
|
|
|
+ b [5] := CHR (ORD (b [5]) + 128)
|
|
|
|
|
+ END
|
|
|
|
|
+END IntToMbf ;
|
|
|
|
|
+
|
|
|
PROCEDURE Assignment (r : ERes) ;
|
|
PROCEDURE Assignment (r : ERes) ;
|
|
|
(* ':=' already consumed by the caller; store expression into r *)
|
|
(* ':=' already consumed by the caller; store expression into r *)
|
|
|
VAR src : ERes ;
|
|
VAR src : ERes ;
|
|
|
k, n : CARDINAL ;
|
|
k, n : CARDINAL ;
|
|
|
sbuf : ARRAY [0..31] OF CHAR ;
|
|
sbuf : ARRAY [0..31] OF CHAR ;
|
|
|
|
|
+ rbuf : ARRAY [0..5] OF CHAR ;
|
|
|
BEGIN
|
|
BEGIN
|
|
|
IF (r.kind # 1) AND (r.kind # 5) THEN
|
|
IF (r.kind # 1) AND (r.kind # 5) THEN
|
|
|
Err (EUnknown) ;
|
|
Err (EUnknown) ;
|
|
|
RETURN
|
|
RETURN
|
|
|
END ;
|
|
END ;
|
|
|
|
|
+ IF r.cls = TReal THEN
|
|
|
|
|
+ (* A 6-byte REAL. A compile-time ordinal constant is converted to the
|
|
|
|
|
+ measured MBF layout; another REAL field is copied byte for byte.
|
|
|
|
|
+ Real arithmetic and real-valued expressions are a later stage and
|
|
|
|
|
+ are refused, not guessed. *)
|
|
|
|
|
+ ParseExpr (src) ;
|
|
|
|
|
+ IF NOT OK () THEN
|
|
|
|
|
+ RETURN
|
|
|
|
|
+ END ;
|
|
|
|
|
+ IF (src.kind = 0) AND (src.cls # TString) AND (src.cls # TSet) THEN
|
|
|
|
|
+ IntToMbf (src.imm, rbuf) ;
|
|
|
|
|
+ IF r.kind = 5 THEN
|
|
|
|
|
+ k := 0 ;
|
|
|
|
|
+ WHILE k < 6 DO
|
|
|
|
|
+ EmStDiImm (k, ORD (rbuf [k])) ;
|
|
|
|
|
+ INC (k)
|
|
|
|
|
+ END
|
|
|
|
|
+ ELSIF r.kind = 1 THEN
|
|
|
|
|
+ k := 0 ;
|
|
|
|
|
+ WHILE k < 6 DO
|
|
|
|
|
+ EmMovAxi (ORD (rbuf [k])) ;
|
|
|
|
|
+ EmStoreVar (symtab [r.idx].local,
|
|
|
|
|
+ (symtab [r.idx].off + r.boff + k) MOD 10000H, 1) ;
|
|
|
|
|
+ INC (k)
|
|
|
|
|
+ END
|
|
|
|
|
+ ELSE
|
|
|
|
|
+ Err (ENoLib)
|
|
|
|
|
+ END ;
|
|
|
|
|
+ RETURN
|
|
|
|
|
+ END ;
|
|
|
|
|
+ IF (src.kind = 1) AND (src.cls = TReal) THEN
|
|
|
|
|
+ IF r.kind = 5 THEN
|
|
|
|
|
+ IF src.kind = 5 THEN
|
|
|
|
|
+ Err (ENoLib) ;
|
|
|
|
|
+ RETURN
|
|
|
|
|
+ END ;
|
|
|
|
|
+ k := 0 ;
|
|
|
|
|
+ WHILE k < 6 DO
|
|
|
|
|
+ EmLoadVar (symtab [src.idx].local,
|
|
|
|
|
+ (symtab [src.idx].off + src.boff + k) MOD 10000H, 1) ;
|
|
|
|
|
+ EmStDiAlOff (k) ;
|
|
|
|
|
+ INC (k)
|
|
|
|
|
+ END
|
|
|
|
|
+ ELSIF r.kind = 1 THEN
|
|
|
|
|
+ k := 0 ;
|
|
|
|
|
+ WHILE k < 6 DO
|
|
|
|
|
+ EmLoadVar (symtab [src.idx].local,
|
|
|
|
|
+ (symtab [src.idx].off + src.boff + k) MOD 10000H, 1) ;
|
|
|
|
|
+ EmStoreVar (symtab [r.idx].local,
|
|
|
|
|
+ (symtab [r.idx].off + r.boff + k) MOD 10000H, 1) ;
|
|
|
|
|
+ INC (k)
|
|
|
|
|
+ END
|
|
|
|
|
+ ELSE
|
|
|
|
|
+ Err (ENoLib)
|
|
|
|
|
+ END ;
|
|
|
|
|
+ RETURN
|
|
|
|
|
+ END ;
|
|
|
|
|
+ Err (ENoLib) ;
|
|
|
|
|
+ RETURN
|
|
|
|
|
+ END ;
|
|
|
IF r.cls = TSet THEN
|
|
IF r.cls = TSet THEN
|
|
|
(* `field := [elements]'. The constructor's TYPE comes from the target:
|
|
(* `field := [elements]'. The constructor's TYPE comes from the target:
|
|
|
CALC's CellStatus is `set of Attributes' (one byte), not the default
|
|
CALC's CellStatus is `set of Attributes' (one byte), not the default
|