⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssrules.asm

📁 [随书类]Dos6.0源代码
💻 ASM
📖 第 1 页 / 共 2 页
字号:
page	49,132
	TITLE	ssrules - Scanner Table Definitions
;***
;ssrules.asm - Scanner Table Definitions
;
;	Copyright <C> 1986, Microsoft Corporation
;
;Purpose:
;
;   This module defines the coercion and rules tables used by the scanner.
;   The following is a description of how all scan tables are organized.
;
;   tOpSsDisp:	    tOpAtr:	    tOpRule:	    tOpExe:
;	    ssOp1	    op1Atr	    op1Rule	    ex1
;	    ssOp2	    op2Atr	    op2Rule	    ex2
;	    ... 	    ... 	    ... 	    ...
;
;   tOpSsDisp is the scan dispatch for the opcode.  Entries are 1 word.
;
;   tOpAtr is the atribute byte for the opcode. Entries are 1 byte.  The
;   atribute value is the number of operand bytes owned by the opcode.
;   Some opcodes own a variable number of operand bytes.  In these cases
;   the first operand word is the number of operand bytes - 2.	This is
;   signified by LOW UNDEFINED in the atribute table.
;
;   tOpRule is a scan helper byte that can be:
;	1. a rule table index.	Used in this way when there are more than one
;	   variables in the opcode to executor algorithm.  The rule table index
;	   is used to index tRuleWord and tRuleByte desribed below.
;	2. an ET type.	Used in this manner when the emitted type is the only
;	   variable in the opcode to executor algorithm.  An example is all
;	   intrinsic functions that have no operands (ERR, ERL,...).
;
;   tOpExe is the executor for the opcode.  If an opcode has several executors
;   then tOpExe contains the address of an ordered list of executors for
;   the opcode.
;
;   tRuleWord:
;	This table usually contains one of the following:
;	1. coercion table address
;	2. other scan routine specific information such as an ET type.
;
;   tRuleByte:
;	This table almost always contains an ET type which is the emitted
;	type for opcodes using this rule.  The special emitted type
;	LOW UNDEFINED indicates that the coerced input type is to be emitted.
;	For example, opAdd emits an I2 when the arguments are I2.
;
;   tCo<rule>
;	These are the coercion tables.	They are either one or two dimensional
;	and overlay each other as much as possible in order to save space.
;	Coercion tables contain:
;	1. ET types.  These are present when coercion may be required.	The
;	   type is the target type to which the current argument(s) must be
;	   coerced.
;	2. 0.  This value is used as a speed hack.  It is present when it is
;	   known that coercion is not required.
;	3. LOW UNDEFINED.  This value is used to indicate "type mismatch"
;	   was detected.
;
;   tCoerceExe is a 2 dimensional (typeXtype) table of coercion executor
;   addresses.
;
;In general, these tables are accessed as follows (refer to following diagram):
;	1. The opcode is used to index into tOpRule to find the rule index
;	   for the current op.	This allows a single scan routine to scan
;	   a family of related opcodes.
;	2. The rule index is used to find the coercion table and the emitted
;	   type for the current op.
;	3. Arguments are popped from the scan stack and used to index the
;	   coercion table.
;	4. For opcodes that emit a value the emitted type and current
;	   expression fragment pcode address are pushed on the stack.
;
;		tOpRule:	   tRuleWord: tRuleByte:
;		    [index]
;    opcode-------->[index]--------> [ptCoerce][ET_emit]
;		    [...  ]		 |
;					 +---------------->tCoerce
;
;
;****************************************************************************

	.xlist
	include 	version.inc
SSRULES_ASM = ON
	IncludeOnce	context 	    
	IncludeOnce	opintrsc
	IncludeOnce	pcode
	IncludeOnce	qbimsgs
	IncludeOnce	ssint
	IncludeOnce	txtmgr
	IncludeOnce	variable
	.list


assumes cs, SCAN
assumes ds, DATA
assumes SS, DATA

sBegin	CODE

	extrn	exLitI21:near		;Literal executor

	    extrn   exPushSeg:near	
	    extrn   exCopyTmpAr:near	

sEnd	CODE

subttl	Coercion Label Definitions

sBegin	SCAN

	extrn	GetTrueType:near	

mOpExLitR8	label word	    
	DWEXT	exLitR80	    
	DWEXT	exLitR81	    
	DWEXT	exLitR82	    
	DWEXT	exLitR83	    
	DWEXT	exLitR84	    
	DWEXT	exLitR85	    
	DWEXT	exLitR86	    
	DWEXT	exLitR87	    
	DWEXT	exLitR88	    
	DWEXT	exLitR89	    
	DWEXT	exLitR810	    

subttl	Coercion Support Functions
page
;***
;SsCoerceN - coerce n expressions on the scan stack to specified type
;Purpose:
;	Coerce n expressions on the scan stack to specified type.
;
;Input:
;	ax = oTyp of target (Record = ET_RC)
;	cx = count to coerce
;	si/di scan source and destination in pcode
;Output:
;	si/di updated if any coercion was required.
;	f_StaticCalc set FALSE if any expression was not a literal
;
;Preserves:
;	ax,bx
;***************************************************************************

	public	SsCoerceN
SsCoerceN:
	pop	[SsParmCnt]		; Get return address out of the way
	jcxz	EndCoerceN		
	.erre	ET_RC EQ 0		; Assure DEC is sufficient
	dec	ax			; Force ET_RC -> 0ffffh
	cmp	ax,ET_MaxNum		; Numeric type?
	jb	SsCoerceNStart		
	call	TMError 		
	xor	ax,ax			; Use valid type (ET_I2)
SsCoerceNStart: 			
	inc	ax			; Restore correct oTyp
SsCoerceNLoop:
	pop	dx			; Get oType
	push	dx			; But keep it on stack
	xor	dh,high ST_Lit? 	;High bits now zero if literal
	test	dh,0C0H 		;Determine if this index is a literal.
	jz	SsCoerceNNotLit 	;Not a literal index
	mov	f_StaticCalc,FALSE	;Indicate not a $STATIC array if this
SsCoerceNNotLit:			; is the first reference.
	test	dh,ST_ByVal+ST_Seg	; Have ByVal or Seg been used?
	jz	@F			; Brif no
	call	TMError 		
@@:
	call	EnsureArgType		
	loop	SsCoerceNLoop		;Go check next index
EndCoerceN:				
	jmp	[SsParmCnt]		; Return to caller

	page
;***
;EnsureArgType
;Purpose:
;	Ensure that the expression entry on the stack is of the desired
;	type.
;Input:
;	ax = type required for this expression
;	si/di scan source and emit
;
;	ParmW	oTxExp
;	ParmW	oTypExp (Records use ET_RC)
;
;Output:
;	ax = oTyp of target (Records use true oTyp)
;Preserves:
;	bx,cx,dx
;****
cProc	EnsureArgType,<NEAR,PUBLIC>,<ax,bx,cx,dx>
ParmW	oTxExp
ParmW	oTypExp
cBegin
	mov	bx,oTxExp		;Expression location
	cmp	ax,ET_MaxNum		; Is target numeric ?
	xchg	cx,ax			;CX = oTyp of target
	jbe	Numeric 		
	mov	ax,oTypExp		;AX = oTyp of source (Record = ET_RC)
	TestX	ax,ST_Var?		;Is it a variable?
	jz	Coerce			;If not, it won't move
	mov	dh,0			;Assume near - SD/FS
	or	al,al			;[5] Is it a record?
	jnz	SafeRef 		; Make sure reference is safe
	mov	dh,FarArg		;Must be record - want far ref
SafeRef:
	call	SsRefArg		;Make sure it's safe from moving
Numeric:
	mov	ax,oTypExp		;AX = oTyp of source (Record = ET_RC)
Coerce:
	call	SsCoerceReg
cEnd

;SsCoerceReg
;
;Purpose:
;	Insert a coercion token to cause an expression to be coerced to a
;	specified type.
;
;	Literals 0 through 10 may be coerced from I2 to R4 by modification
;	of the executor for these literals.
;
;	If types match, no action is performed.
;
;Inputs:
;	ax = oTyp of expression (with high bits set) (Record = ET_RC)
;	bx = oTx of expression
;	cx = oTyp of target
;Outputs:
;	bx = oTx of expression, after coercion
;	si and di updated if insertion needed
;Exceptions:
;	If expression or target type is not numeric, Type Mismatch Error
;	is generated.
;
;	Coercion token insertion may cause the text table to grow.  This
;	may result in OME.

	public	SsCoerceReg
SsCoerceReg:
	cmp	ax,ET_I2+ST_Lit 	;Determine if lit without operand
	jne	NoLitCoerce		;Can't optimize by replacing lit executor
	cmp     cx,ET_R4		
	jz	LitCoerce		
	cmp	cx,ET_R8
	jne	NoLitCoerce
LitCoerce:
;Target type is R4/R8, so replace executor with 1 word 8087 literal
	mov	dx,bx			;Preserve address of this executor
	mov	bx,PTRTX[bx-2]		;Load literal executor
	GetCodeIntoDs	SCAN		
	mov	bl,byte ptr [bx-1]	; Load MSB of opcode
	push	ss			
	pop     ds			
	.erre	OPCODE_MASK EQ 03ffh	; Assure following code is ok
;	and	bx,HIGH (NOT OPCODE_MASK)
	and	bx,0fch 		; Clear unwanted bits
	shr	bx,1			; Convert to word offset
	mov     ax,mOpExLitR8[bx]	; Get corresponding R8 lit executor
	mov	bx,dx			;Restore address of I2 executor in text
	mov	PTRTX[bx-2],ax		;Store the new R4 literal executor.
EndCoerce:
	ret

RecordChk:
;	At this point, the coercion has been determined to be from a record.
;	However, the true oTyp of the record is not saved on the scan stack
;	ET_RC was used instead.  This code will use the oTx of the IdLd to
;	find the oVar and in turn the true oTyp of the source.	This is
;	then compared to CX to check that types match.	No coercion is
;	possible among records so there is either an error or nothing.
;
;	ax = oTyp of source expression
;	bx = oTx of source expression
;	cx = oTyp of target

	;In non-SizeD versions, it is possible that the oTx from the scan
	;stack will point after an exCopyTmpAr and exPushSeg instead of an
	;exIdLd, exAIdLd, or exOffLd.  To differentiate between the two, the
	;exPushSeg executor is forced to start at an odd address.  Since an
	;oVar and oElem must be even, the exPushSeg can be recognized.

	    cmp     PTRTX[bx-2],codeOFFSET exPushSeg
	    jne     @F			; Brif exIdLd, exAIdLd, or exOffLd
	    DbAssertRel PTRTX[bx-10],e,<codeOFFSET exCopyTmpAr>,SCAN,<SsCoerceReg: exCopyTmpAr>
	    sub     bx,10		; Backup over inserted executors
@@:
	mov	dx,cx			; DX = oTyp of target
	call	GetTrueType		; CX = oTyp of source
	cmp	cx,dx			; Do oTyps match?

	public	TMError,TMErrorNZ
TMErrorNZ:
	;Report type mismatch error if Z flag not set.
	jz	NoError
TMError:
	;Report type mismatch error.  All registers preserved.
	push	ax
	mov	ax,ER_TM		;Type mismatch error
	call	SsError
	pop	ax
NoError:
	ret

NoLitCoerce:
;Calculate the implicit coercion executor by entering tImpCo as a two
;dimensioned table of executor addresses.
	.erre	ET_RC EQ 0		; Assure JZ is sufficient
	or	al,al			
	jz	RecordChk		; Brif source is record
	cmp	cx,ET_MAX		; Is target a primitive type?
	ja	TMError 		; Brif not.  This is an error
	call	MSdFs			; Map ET types: FS=SD
	xchg	ax,cx			; AX = Target type
	call	MSdFs			; Map target type too
	cmp	ax,cx			;Types already match?
	je	EndCoerce		; If match, skip coercion

        .erre   ET_SD EQ 5

	add	ax,cx			;AX = Source + Target
	shl	cx,1			;CX = Source * 2
	shl	cx,1			;CX = Source * 4
	add	ax,cx			;AX = Source * (5|7) + Target
	xchg	ax,bx			;AX = oTx, BX = Table index
	shl	bx,1			;To word index
	mov	cx,tImpCo[bx]		;Enter coercion executor table for executor
	xchg	bx,ax			; oTx to bx
	jcxz	EndCoerce
	mov	ax,cx			;Executor to insert to ax
	dec	cx			; Is this 1 (incompatible types)?
	jcxz	TMError 		; Brif yes
;	jmp	short Insert		;Fall into Insert, below


;*** Insert - Insert word into pcode
;
;Inputs:
;	ax = word to insert
;	bx = oTx to insert
;	cx = Number of bytes to make room for (InsertCx only)
;	si = scan source
;	di = scan destination
;Outputs:
;	cx = number of bytes inserted
;	bx = input bx + output cx: oTx of point after insertion
;	si, di updated for text moves
;Exceptions:
;	If OME:
;		Error recorded by SsError
;		Carry flag set
;Preserves:
;	ax,bx,dx (bx updated)

public	Insert,InsertCx,InsertBranchBos,InsertBranch,Insert1Op
extrn	exBranch:near

Insert:
	mov	cx,2			;Make room for two bytes
InsertCx:
	cmp	[SsErr],0		;Any errors?
	jnz	InsertFail		;Don't let error location get invalid
	push	ax
	push	bx
	push	cx
	push	dx
;Ensure room.  This may cause source side of text to move within the segment.
	call	SsEnsureGap		;Ensure reasonable gap size
	pop	dx
	pop	cx
	pop	bx
	pop	ax
	jc	InsertOME		;Out of memory error
	or	[SsBosFlags],SSBOSF_Inserted	;Remember insertion occured

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -