[list -]
%if 0

lDebug set up and macros for assembler tables

Copyright (C) 1995-2003 Paul Vojta
Copyright (C) 2008-2012 C. Masloch

Usage of the works is permitted provided that this
instrument is retained with the works, so that any entity
that uses the works is notified of this instrument.

DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.

%endif

%if 0

Assembler and disassembler instruction table.
The include file is generated by MKTABLES.
These macros serve to use the new DEBUG/X 1.18+
symbolic include file, where not everything is
done by MKTABLES so you can edit the include file.
; (lDebug's MKTABLES was still adjusted afterwards.)

; Note:	The ASMTABLE2 section corresponds to DEBUG/X 1.18's segment
	ASMDATA, while the data in ASMTABLE1 is written into the
;	program's section for DEBUG/X 1.18.
	%$currofs is defined as offset from asmtab and then written to
	the table verbatim so %assign can be used, avoiding a label at
	every position %$currofs is defined. DEBUG/X 1.18 defines its
	CURROFS as $, then subtracts asmtab later.
	"%ifnempty" is used to check whether macro parameters are used
	in all cases, although in some cases %0 could be checked for the
	current table. This is avoided to ease usage of tables that
	might specify empty parameters, like the original DEBUG/X
	tables will sometimes do.
	The table defines some equs, but that was left unchanged to ease
	transition.

%endif

		; Assembler table prefix bytes. These are described and dispatched in
		; aa.asm. The definition here and usage in aa.asm must match that in
		; debugtbl.inc (and by proxy that in mktables).
ASM_END		equ 0FFh

ASM_SPECIAL	equ ASM_END	; Special mnemonic prefix,
				;  decide meaning by mnemonic:
				; (All assembler directives belong here.)
ASM_A32PREF	equ ASM_SPECIAL	; MN_A32, a32 prefix
ASM_O32PREF	equ ASM_SPECIAL	; MN_O32, o32 prefix
ASM_A16PREF	equ ASM_SPECIAL	; MN_A16, a16 prefix
ASM_O16PREF	equ ASM_SPECIAL	; MN_O16, o16 prefix
ASM_DB		equ ASM_SPECIAL	; MN_DB, db pseudo-instruction
ASM_DW		equ ASM_SPECIAL	; MN_DW, dw pseudo-instruction
ASM_DD		equ ASM_SPECIAL	; MN_DD, dd pseudo-instruction
ASM_ORG		equ ASM_SPECIAL	; MN_ORG, org directive
ASM_AAX		equ ASM_SPECIAL	; MN_AAD, MN_AAM, aad and aam instructions (default parameter)
ASM_SEG		equ ASM_SPECIAL	; MN_ES, MN_CS, MN_SS, MN_DS, MN_FS, MN_GS (consecutive)
ASM_LOCKREP	equ ASM_SPECIAL	; MN_LOCK, MN_REP, MN_REPE, MN_REPNE (REPs consecutive)

	; Assembler table prefixes which apply to different
	; instruction mnemonics but have the same meaning.
ASM_WAIT	equ ASM_SPECIAL-1	; FPU instruction mnemonic with prefixed WAIT instruction
ASM_D32		equ ASM_WAIT-1		; 32-bit form (write OSIZE in 16-bit CS)
ASM_D16		equ ASM_D32-1		; 16-bit form (write OSIZE in 32-bit CS)
	; The following apply to the next operand list only.
ASM_LOCKABLE	equ ASM_D16-1		; LOCK in front of this instruction form valid
ASM_MACH6	equ ASM_LOCKABLE-1	; First appeared on 686
ASM_MACH5	equ ASM_MACH6-1		; 586
ASM_MACH4	equ ASM_MACH5-1		; 486
ASM_MACH3	equ ASM_MACH4-1		; 386
ASM_MACH2	equ ASM_MACH3-1		; 286
ASM_MACH1	equ ASM_MACH2-1		; 186
ASM_ESCAPE	equ ASM_MACH1-1		; prefix byte for large words
ASM_FIRST	equ ASM_ESCAPE		; The lowest assembler table prefix

%assign _ASM_ESCAPE_USED 0

	%macro mnsuffix 0-1.nolist
%define MNSUFFIX %1
	%endmacro

	%macro mne 1-2+;.nolist
%push
usesection ASMTABLE2, 1
%assign %$currofs $ - asmtab
%ifnempty %2
	db %2
%endif
__SECT__
%defstr %$string %1					; mnemonic as string
%strlen %$string_size %$string				; get string length
%if %$string_size > 15
 %error Mnemonic %1 is too long!
%endif
	dw (%$currofs)<<4|%$string_size			; 12 bits for asmtab ofs, 4 for length
%assign MN_%1%[MNSUFFIX] $ - mnlist			; label for this mnemonic (no equ necessary)
	db %$string					; write mnemonic
%pop
%define MNCURRENT %1%[MNSUFFIX]
	%endmacro

%define AGRP(num,rfld) (240h + num*8 + rfld)

	%macro variant 2-4.nolist
%push
usesection ASMTABLE2, 1
%ifnempty %3
	db %3
%endif
%ifnempty %4
	db %4
%endif

%assign %$ainfo (%1)*ASMMOD+%2
%assign %$escaped %$ainfo>>8
%assign %$escapes 0

%rep 10		; this is the number of escapes allowed here right now
 %if %$escaped < ASM_FIRST
  %exitrep
 %else	; NASM 2.09, 2.10rc1 bug
 %assign %$escaped %$escaped-ASM_ESCAPE
 %assign %$escapes %$escapes+1
 %assign _ASM_ESCAPE_USED 1
	db ASM_ESCAPE
 %endif
%endrep
%if %$escaped >= ASM_FIRST
 %error Too many assembler table escape bytes necessary.
%elif %$escaped < 0
 %error "ASM_ESCAPE currently must be equal to ASM_FIRST."
%else
 %if %$escapes > 1
  %warning %$escapes assembler table escape bytes used.
 %endif
	db %$escaped, %$ainfo & 0FFh			; big endian
%endif
%if %$escapes > %$$topbyte
 %assign %$$topbyte_ofs $-asmtab-2-%$escapes
 %ifnempty %3
	%assign %$$topbyte_ofs %$$topbyte_ofs - 1
 %endif
 %ifnempty %4
	%assign %$$topbyte_ofs %$$topbyte_ofs - 1
 %endif
 %assign %$$topbyte %$escapes
 %xdefine %$$topbyte_var mne MNCURRENT variant %1,%2,%3,%4
%endif
__SECT__
%pop
	%endmacro

	%macro fpvariant 3-5.nolist
	variant %1,%2,%4,%5
usesection ASMTABLE2, 1
	db %3
__SECT__
	%endmacro

	%macro endvariant 0.nolist
usesection ASMTABLE2, 1
	db -1
__SECT__
	%endmacro

		; Smacros internally used by the loop to create opindex and by opl.
		; %$digit is evaluated to be in the range 0..15 (of one hexadecimal
		; digit). Then, __HEXDIGIT_%$digit is appended to %$label using
		; %strcat. As it expands to __HEXDIGIT_0 to __HEXDIGIT_15, these are
		; defined here to be strings of each digit.
		; This is somewhat of a hack since there is no intrinsic support
		; for numeric expansion in the NASM preprocessor, and it can only
		; be talked into expanding to decimal numbers without leading zeros.
		; So we have to make a string for the label on our own. %defstr,
		; %strcat and %deftok are used so that the single hexadecimal digits
		; (letters) don't collide with possible smacros. (The output of our
		; _2digitshex() smacro isn't accepted as string by the preprocessor
		; so we unfortunately can't just use that.)
		; The 162 times this is used have been observed not to make much of
		; a performance impact during assembling.
%define __HEXDIGIT_0  '0'
%define __HEXDIGIT_1  '1'
%define __HEXDIGIT_2  '2'
%define __HEXDIGIT_3  '3'
%define __HEXDIGIT_4  '4'
%define __HEXDIGIT_5  '5'
%define __HEXDIGIT_6  '6'
%define __HEXDIGIT_7  '7'
%define __HEXDIGIT_8  '8'
%define __HEXDIGIT_9  '9'
%define __HEXDIGIT_10 'A'
%define __HEXDIGIT_11 'B'
%define __HEXDIGIT_12 'C'
%define __HEXDIGIT_13 'D'
%define __HEXDIGIT_14 'E'
%define __HEXDIGIT_15 'F'


	%macro opl 1+.nolist
%push
%define %$label "OPLIST_"

		; Generate OPLIST_xx smacro from %assigned number.
		; See comments in front of this macro.
%assign %$digit opidx >> 4		; evaluate the expression
%strcat %$label %$label, __HEXDIGIT_%$digit
%assign %$digit opidx & 0Fh		; evaluate the expression
%strcat %$label %$label, __HEXDIGIT_%$digit
%deftok %$label %$label
	; Specific leading zero detection and handling probably won't make
	; this faster, and this produces the result we want anyway.

%assign %[%$label] $ - oplists				; define the offset (equ not necessary)
	; Note:	Needs that macro indirection, so the smacro's name isn't "%$label"
	;	but the current content of the smacro %$label.
	db %1
%assign opidx opidx+1
%pop
	%endmacro

%define label %+ : comment				; ignore MASM label types and correctly
							;  specify a NASM label (with colon)

;%define OT(num) (OPLIST_ %+ num + OPTYPES_BASE)
%define OT(num) (0 %+ num %+ h + OPTYPES_BASE)


		; DEBUG/X 1.18 uses manually adjusted tables with if/else/endif
		; constructs for MMX support. These macros ain't optimal, but
		; allow to use the tables as created by Japheth without changes.
		; This is useful since the if could be added to MKTABLES later.
	%macro if 1.nolist
%ifctx ASMTABLE_IF
 %fatal Nested "if" in assembler tables, adjust to %if and add underscores
%elifctx ASMTABLE_ELSE
 %fatal Nested "if" in assembler tables, adjust to %if and add underscores
%elifctx ASMTABLE_ELIF
 %fatal Nested "if" in assembler tables, adjust to %if and add underscores
%endif
%push ASMTABLE_IF
%assign %$topbyte %$$topbyte
%assign %$topbyte_ofs %$$topbyte_ofs
%xdefine %$topbyte_var %$$topbyte_var
%if %[_%1]
 %assign %$haveemitted 1
 %assign %$emitting 1
%else
 %assign %$haveemitted 0
 %assign %$emitting 0
 %define opl comment
 %define mne comment
 %define variant comment
 %define fpvariant comment
 %define endvariant comment
 %define db comment
 %define dw comment
 %define dd comment
%endif
	%endmacro

	%macro elseif 1.nolist
%ifctx ASMTABLE_ELSE
 %fatal "elseif" behind "else" in assembler tables
%elifctx ASMTABLE_ELIF
%elifnctx ASMTABLE_IF
 %fatal Lone "elif" in assembler tables
%endif
%repl ASMTABLE_ELIF
%ifn %$haveemitted || !(%[_%1])
 %assign %$haveemitted 1
 %assign %$emitting 1
 %undef opl
 %undef mne
 %undef variant
 %undef fpvariant
 %undef endvariant
 %undef db
 %undef dw
 %undef dd
%else
 %assign %$emitting 0
 %define opl comment
 %define mne comment
 %define variant comment
 %define fpvariant comment
 %define endvariant comment
 %define db comment
 %define dw comment
 %define dd comment
%endif
	%endmacro

	%macro else 0.nolist
%ifctx ASMTABLE_ELSE
 %fatal Double "else" in assembler tables
%elifctx ASMTABLE_ELIF
%elifnctx ASMTABLE_IF
 %fatal Lone "else" in assembler tables
%endif
%repl ASMTABLE_ELSE
%if %$haveemitted
 %assign %$emitting 0
 %define opl comment
 %define mne comment
 %define variant comment
 %define fpvariant comment
 %define endvariant comment
 %define db comment
 %define dw comment
 %define dd comment
%else
 %assign %$emitting 1
 %undef opl
 %undef mne
 %undef variant
 %undef fpvariant
 %undef endvariant
 %undef db
 %undef dw
 %undef dd
%endif
	%endmacro

	%macro endif 0.nolist
%ifctx ASMTABLE_ELSE
%elifctx ASMTABLE_ELIF
%elifnctx ASMTABLE_IF
 %fatal Lone "endif" in assembler tables
%endif
%ifn %$emitting
 %undef opl
 %undef mne
 %undef variant
 %undef fpvariant
 %undef endvariant
 %undef db
 %undef dw
 %undef dd
%endif
%assign %$$topbyte %$topbyte
%assign %$$topbyte_ofs %$topbyte_ofs
%xdefine %$$topbyte_var %$topbyte_var
%pop
	%endmacro

%assign opidx 0
%push ASMTABLE_CTX
%assign %$topbyte 0
%assign %$topbyte_ofs 0
%xdefine %$topbyte_var

[list +]
	usesection ASMTABLE2
asmtab:
	usesection ASMTABLE1

	strdef TABLENAME, "debugtbl.inc"
	%include _TABLENAME
[list +]
opindex:
[list -]
%assign %$i 0
%rep ASMMOD

		; Generate OPLIST_xx smacro from %assigned number.
		; See comments in front of the opl macro.
%define %$label "OPLIST_"
%assign %$digit %$i >> 4		; evaluate the expression
%strcat %$label %$label, __HEXDIGIT_%$digit
%assign %$digit %$i & 0Fh		; evaluate the expression
%strcat %$label %$label, __HEXDIGIT_%$digit
%deftok %$label %$label
%assign %$index %$label + 1 - (2 * %$i)
%if %$index < 0
 %error Invalid opindex content = %$index
%endif
[list +]
	db %$index
[list -]
%assign %$i %$i+1
%endrep

%if %$topbyte > 0
%define %$label ''
%assign %$leadingzero 1
%assign %$digit (%$topbyte_ofs >> 12) & 0Fh	; evaluate the expression
%if %$digit != 0
 %strcat %$label %$label, __HEXDIGIT_%$digit
 %assign %$leadingzero 0
%endif
%assign %$digit (%$topbyte_ofs >> 8) & 0Fh	; evaluate the expression
%if %$digit != 0 || %$leadingzero == 0
 %strcat %$label %$label, __HEXDIGIT_%$digit
 %assign %$leadingzero 0
%endif
%assign %$digit (%$topbyte_ofs >> 4) & 0Fh	; evaluate the expression
%if %$digit != 0 || %$leadingzero == 0
 %strcat %$label %$label, __HEXDIGIT_%$digit
 %assign %$leadingzero 0
%endif
%assign %$digit %$topbyte_ofs & 0Fh		; evaluate the expression
%strcat %$label %$label, __HEXDIGIT_%$digit
%strcat %$label %$label, 'h'
%deftok %$label %$label

%warning Most assembler table prefix bytes: %$topbyte (ofs %$label) %$topbyte_var
%endif

%ifnctx ASMTABLE_CTX
 %fatal Missing an "endif" in assembler tables
%endif
%pop

%undef opidx
%undef OT
%undef label
%undef __HEXDIGIT_0
%undef __HEXDIGIT_1
%undef __HEXDIGIT_2
%undef __HEXDIGIT_3
%undef __HEXDIGIT_4
%undef __HEXDIGIT_5
%undef __HEXDIGIT_6
%undef __HEXDIGIT_7
%undef __HEXDIGIT_8
%undef __HEXDIGIT_9
%undef __HEXDIGIT_10
%undef __HEXDIGIT_11
%undef __HEXDIGIT_12
%undef __HEXDIGIT_13
%undef __HEXDIGIT_14
%undef __HEXDIGIT_15
%unmacro opl 1+.nolist
%unmacro endvariant 0.nolist
%unmacro fpvariant 3-5.nolist
%unmacro variant 2-4.nolist
%unmacro mne 1-2+.nolist
%unmacro if 1.nolist
%unmacro elif 1.nolist
%unmacro else 0.nolist
%unmacro endif 0.nolist
[list +]

	usesection lDEBUG_DATA_ENTRY
