|
|
@@ -136,7 +136,9 @@ CONST
|
|
|
D_HT = 825 ; (* 2 bytes: Horner table pointer *)
|
|
|
D_HC = 827 ; (* 1 byte: Horner/square iteration count *)
|
|
|
D_HF = 828 ; (* 1 byte: Horner final +1 flag *)
|
|
|
- D_END = 829 ; (* the block is padded to here *) (* the block is padded to here *)
|
|
|
+ D_ISTMP = 829 ; (* 2 bytes: Insert index *)
|
|
|
+ D_ITMP = 831 ; (* 2 bytes: Insert new length *)
|
|
|
+ D_END = 833 ; (* the block is padded to here *) (* the block is padded to here *)
|
|
|
|
|
|
(* THE LOAD BIAS. Everything above is an offset into the image as this
|
|
|
compiler numbers it: the entry JMP is at image 0. But a DOS .COM is
|
|
|
@@ -802,6 +804,10 @@ PROCEDURE XorBhBh ; BEGIN B (30H) ; B (0FFH) END XorBhBh ; (* BH:=0 *)
|
|
|
PROCEDURE AddAlAh ; BEGIN B (00H) ; B (0E0H) END AddAlAh ; (* AL:=AL+AH *)
|
|
|
PROCEDURE AddAxCx ; BEGIN B (03H) ; B (0C1H) END AddAxCx ; (* AX:=AX+CX *)
|
|
|
PROCEDURE AddAxBx ; BEGIN B (03H) ; B (0C3H) END AddAxBx ; (* AX:=AX+BX *)
|
|
|
+PROCEDURE AddSiAx ; BEGIN B (01H) ; B (0C6H) END AddSiAx ; (* SI:=SI+AX *)
|
|
|
+PROCEDURE CmpAxBx ; BEGIN B (39H) ; B (0D8H) END CmpAxBx ; (* CMP AX,BX *)
|
|
|
+PROCEDURE SubAxSi ; BEGIN B (2BH) ; B (0C6H) END SubAxSi ; (* AX:=AX-SI *)
|
|
|
+PROCEDURE MovSiDx ; BEGIN B (89H) ; B (0D6H) END MovSiDx ; (* SI:=DX *)
|
|
|
PROCEDURE SubAxCx ; BEGIN B (2BH) ; B (0C1H) END SubAxCx ; (* AX:=AX-CX *)
|
|
|
PROCEDURE AdcBxCx ; BEGIN B (13H) ; B (0D9H) END AdcBxCx ; (* BX:=BX+CX+CF *)
|
|
|
PROCEDURE AdcDxCx ; BEGIN B (13H) ; B (0D1H) END AdcDxCx ; (* DX:=DX+CX+CF *)
|
|
|
@@ -868,6 +874,7 @@ PROCEDURE PushBp6 ; BEGIN B (0FFH) ; B (76H) ; B (6) END PushBp6 ;
|
|
|
PROCEDURE MovCxBp6 ; BEGIN B (8BH) ; B (4EH) ; B (6) END MovCxBp6 ;
|
|
|
PROCEDURE MovCxBp4 ; BEGIN B (8BH) ; B (4EH) ; B (4) END MovCxBp4 ;
|
|
|
PROCEDURE MovBxBp8 ; BEGIN B (8BH) ; B (5EH) ; B (8) END MovBxBp8 ;
|
|
|
+PROCEDURE MovBxBp10 ; BEGIN B (8BH) ; B (5EH) ; B (0AH) END MovBxBp10 ;
|
|
|
PROCEDURE MovSiBp8 ; BEGIN B (8BH) ; B (76H) ; B (8) END MovSiBp8 ;
|
|
|
PROCEDURE MovSiBp10 ; BEGIN B (8BH) ; B (76H) ; B (0AH) END MovSiBp10 ;
|
|
|
PROCEDURE LdDlDi ; BEGIN B (8AH) ; B (15H) END LdDlDi ; (* DL:=[DI] *)
|
|
|
@@ -3410,6 +3417,59 @@ BEGIN
|
|
|
PopDi ; PopSi ; PopDx ; PopCx ; PopBx ; MovSpBp ; PopBp ; RetR
|
|
|
END EmitStrDelete ;
|
|
|
|
|
|
+PROCEDURE EmitStrInsert ;
|
|
|
+(* str_insert: Insert(Source, Dest, Index, Max). The compiler pushes Max,
|
|
|
+ Index, Dest, Source in that order, so Source is at [BP+10], Dest at
|
|
|
+ [BP+8], Index at [BP+6], Max at [BP+4]. Both strings are counted; the
|
|
|
+ operation is in place. Index is clamped to [1, |Dest|+1], and an
|
|
|
+ overflowing result leaves through TP3 error 16 ("String too long"). *)
|
|
|
+BEGIN
|
|
|
+ M ("str_insert") ;
|
|
|
+ PushBp ; MovBpSp ;
|
|
|
+ PushBx ; PushCx ; PushDx ; PushSi ; PushDi ;
|
|
|
+ MovBxBp10 ; (* BX := source *)
|
|
|
+ LdAlBx ; XorAhAh ; MovCxAx ; (* CX := source length *)
|
|
|
+ CmpAx0 ; JccNear (74H, "ins_done") ;
|
|
|
+ MovDiBp8 ; (* DI := destination *)
|
|
|
+ LdAlDi ; XorAhAh ; MovDxAx ; (* DX := destination length *)
|
|
|
+ MovAxBp6 ; (* AX := index *)
|
|
|
+ CmpAxImm (1) ; Jae8 ("ins_idx") ;
|
|
|
+ MovAxImm (1) ;
|
|
|
+ M ("ins_idx") ;
|
|
|
+ MovSiDx ; IncSi ; (* |Dest| + 1 *)
|
|
|
+ CmpAxSi ; Jbe8 ("ins_idx2") ;
|
|
|
+ MovAxSi ;
|
|
|
+ M ("ins_idx2") ;
|
|
|
+ StDataAx (D_ISTMP) ;
|
|
|
+ MovAxCx ; AddAxDx ; (* total length *)
|
|
|
+ StDataAx (D_ITMP) ;
|
|
|
+ MovBxBp4 ; (* BX := max *)
|
|
|
+ CmpAxBx ; Jbe8 ("ins_len") ;
|
|
|
+ MovAlD (10H) ; MovAh (4CH) ; Int21 ;
|
|
|
+ M ("ins_len") ;
|
|
|
+ (* Move the tail backwards: tail = |Dest| - Index + 1. *)
|
|
|
+ MovAxData (D_ISTMP) ; MovSiAx ; (* SI := index *)
|
|
|
+ MovAxDx ; SubAxSi ; AddAxImm (1) ;
|
|
|
+ MovCxAx ; (* tail count *)
|
|
|
+ MovAxDx ; AddAxDi ; MovSiAx ; (* SI := dest + destlen *)
|
|
|
+ MovBxBp10 ; LdAlBx ; XorAhAh ; (* source length *)
|
|
|
+ MovDiSi ; AddDiAx ; (* DI := SI + source length *)
|
|
|
+ Jcxz8 ("ins_tail_done") ;
|
|
|
+ M ("ins_tail") ;
|
|
|
+ LdAlSi ; StDiAl ; DecSi ; DecDi ; Loop8 ("ins_tail") ;
|
|
|
+ M ("ins_tail_done") ;
|
|
|
+ (* Copy the source forward at dest+index. *)
|
|
|
+ MovDiBp8 ; MovAxData (D_ISTMP) ; AddDiAx ;
|
|
|
+ MovBxBp10 ; LdAlBx ; XorAhAh ; MovCxAx ; IncBx ;
|
|
|
+ Jcxz8 ("ins_copy_done") ;
|
|
|
+ M ("ins_copy") ;
|
|
|
+ LdAlBx ; StDiAl ; IncBx ; IncDi ; Loop8 ("ins_copy") ;
|
|
|
+ M ("ins_copy_done") ;
|
|
|
+ MovAxData (D_ITMP) ; MovDiBp8 ; StDiAl ;
|
|
|
+ M ("ins_done") ;
|
|
|
+ PopDi ; PopSi ; PopDx ; PopCx ; PopBx ; MovSpBp ; PopBp ; RetR
|
|
|
+END EmitStrInsert ;
|
|
|
+
|
|
|
PROCEDURE EmitFileOps ;
|
|
|
(* File control-block operations. The block is Compiler.FileVarSize:
|
|
|
+0 DOS handle (FFFFh when closed)
|
|
|
@@ -4056,7 +4116,7 @@ BEGIN
|
|
|
EmitRdStr ; EmitStrStore ; EmitCmpStr ; EmitStrCat ; EmitStrCopy ;
|
|
|
EmitRealFromInt ; EmitRealAddSub ; EmitRealMul ;
|
|
|
EmitRealCmp ; EmitRealInt ; EmitRealMath ; EmitRealConv ; EmitSetOps ;
|
|
|
- EmitStrDelete ; EmitFileOps ; EmitValReal ;
|
|
|
+ EmitStrDelete ; EmitStrInsert ; EmitFileOps ; EmitValReal ;
|
|
|
EmitData ;
|
|
|
FixUp ;
|
|
|
SetStr (entNm [0], "initmem") ;
|
|
|
@@ -4114,6 +4174,7 @@ BEGIN
|
|
|
SetStr (entNm [52], "real_cos") ;
|
|
|
SetStr (entNm [53], "real_arctan") ;
|
|
|
SetStr (entNm [54], "str_delete") ;
|
|
|
+ SetStr (entNm [55], "str_insert") ;
|
|
|
built := TRUE
|
|
|
END RT_Build ;
|
|
|
|
|
|
@@ -4141,7 +4202,7 @@ BEGIN
|
|
|
IF NOT built THEN
|
|
|
RT_Build (0)
|
|
|
END ;
|
|
|
- IF i > 54 THEN
|
|
|
+ IF i > 55 THEN
|
|
|
RETURN 0
|
|
|
END ;
|
|
|
RETURN rtBase + LblOff (entNm [i])
|