home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / PROG / MISC / PASM386C.ZIP / PASM386.SEQ < prev    next >
Encoding:
Text File  |  1989-11-24  |  99.4 KB  |  2,490 lines

  1. \ PASM386.SEQ   8086/80286/80386  PreFix & PostFix Assembler - Version 1.4
  2.  
  3. \ PASM.SEQ      PREFIX & POSTFIX assembler by Robert L. Smith & Tom Zimmer
  4.  
  5. comment:
  6.  
  7.   An assembler for the 8086/8088 and the 80386/80386SX with
  8.   both Prefix and Postfix syntax.
  9.  
  10.   The Intel 80286 offers little extra instruction which are useful
  11.   for a Forth system.  The 386/386SX (on the other hand) is a big
  12.   step and does add capabilities which could be used in Forth - the
  13.   least of which is 32-bit registers and operations which can be used
  14.   to extend F-PC (F-TZ, etc.) into a 32 bit world.  This is the reason
  15.   PASM has been extended to create PASM386.
  16.  
  17.   The generated machine code was checked for compatability with
  18.   MicroSoft's MASM 5.1
  19.  
  20.  
  21. PASM386.SEQ  Version 1.0
  22.  
  23.   Supported
  24.         - 286/386 unqiue instructions
  25.         - Extended (32 bit) size registers and memory
  26.  
  27.   Not Supported
  28.         - ENTER, LEAVE
  29.         - Long (2 byte) offset conditional jumps
  30.         - Extended (32 bit) addressing
  31.         - MOV with CRx or DRx registers
  32.         - Protected mode instructions in general
  33.  
  34.   Updated 17sep89, Gene Czarcinski
  35.         - based on FTZ 3.x version: file dated 03/15/89
  36.           (compatible with OBESE)
  37.         - change to inline NEXT
  38.         - "cleanup" source (comments & form, NOT code),
  39.           shuffle code around to "group better" and make it
  40.           more readable (again, no code changes),
  41.           add documentation from PASM.HLP (it was not HELP in any case),
  42.           add more comments
  43.         - First, fixup the basic 8086 assembler
  44.                 . have IN/OUT check operands
  45.                 . fix MOVS (did not use 1AMI), add SCAS and CMPS
  46.         - add 386 "mode-code" - ASM.cpu Variable, etc.
  47.         - redo segment overrides, add 386 support
  48.         - Add structure for 386 registers and define the 386 regs
  49.         - add 386 unique instructions and modify existing instructions
  50.           to support 386 unique options (e.g., 32 bit operand size prefix)
  51.         - Fix 9MIF for processing shift instructions (BUGFIX) -- it would
  52.           NOT handle a memory address as the destination operand.  This
  53.           MAY cause compatibility problems (!) with code that wasn't correct
  54.           anyway:  ROL  ax # 1  was valid, now it is NOT
  55.           but:     ROL WORD zzz # 1  did NOT work and now it does.
  56.         - Oops, but it still does not work, for compatibility, do "swap"
  57.           that was done before IF (and only if) DEST is NOT specified
  58.           AND the SOURCE is a REG or INDEXED.
  59.  
  60.  
  61. PASM386.SEQ  Version 1.1
  62.  
  63.    Updated 30sep89, Gene Czarcinski
  64.         - Add support for the 8087/80287/80387(sx) Numerical Processor
  65.           ( based on the HFLOAT.SEQ code - Steve Pollack's ASM8087 with
  66.           Mark Smiley's modes) -- Code "merged" into Pasm386.
  67.  
  68. Pasm386.seq Version 1.2
  69.    Updated 30sep89, Gene Czarcinski
  70.         - fix support for 386 "extended size" operands - FFs INC/DEC
  71.  
  72. Pasm386.seq Version 1.3
  73.    Updated 25oct89, Gene Czarcinski
  74.         - update to F-PC (F-TZ) 3.50 Level
  75.           (some fixes, some new features/capabilities)
  76.           . add support for /LISTING
  77.           . use LOADLINE rather than ERRORLINE
  78.  
  79. Pasm386.seq Version 1.4, updated 08nov89, Gene Czarcinski
  80.         - merge help inline as comments and delete .HLP
  81.  
  82.  
  83.   Overview
  84.  
  85.           PASM.SEQ is an assembler which is based on an assembler
  86.         published in DDJ, February 1982 by Ray Duncan. That assembler
  87.         was subsequently modified by Robert L. Smith to repair bugs, and
  88.         support the Prefix assembler notation. I (Tom Zimmer) have made
  89.         additional modifications to allow switching syntaxes, and to
  90.         increase compatibility in POSTFIX mode with the F83 assembler.
  91.  
  92.  
  93.   PREFIX or POSTFIX ?
  94.  
  95.           PASM supports dual syntaxes. The words PREFIX and POSTFIX
  96.         switch between the two supported modes. The POSTFIX mode
  97.         is VERY similar to F83's CPU8086 assembler. PREFIX mode which is
  98.         the default mode, allows a syntax which is much closed to MASM.
  99.  
  100.  
  101.   Macros in PASM
  102.  
  103.           Another area of interest is macros, here is the definition of
  104.         the NEXT macro:
  105.  
  106.                 : NEXT  >PRE    JMP >NEXT A;    PRE> ;
  107.  
  108.           The macro itself is simply the sequence JMP >NEXT. The
  109.         surrounding words are used for support. Since PASM supports both
  110.         Sufix as well as Prefix notation, It is not know on entry to a
  111.         macro what mode is selected. The words >PRE and PRE> select
  112.         Prefix, and restore the previous mode so macros will always be
  113.         in Prefix notation. The A; after >NEXT, forces the assembly of
  114.         the JMP instruction before the mode switch.
  115.  
  116.  
  117.   Why Dual Syntax
  118.  
  119.           The assembler supports Prefix syntax, in an attempt to provide
  120.         a syntax which is more readable to programmers of other
  121.         languages. It supports Postfix syntax to prevent alienating the
  122.         established base of F83 users.
  123.  
  124.           The prefix notation is I think more readable, and certainly
  125.         will be more familiar to programmers of other languages. Please
  126.         consider writting any new assembly code you need in the Prefix
  127.         mode.
  128.  
  129.  
  130.   Syntax Comparison
  131.  
  132.  
  133.         PREFIX                  POSTFIX                 MASM
  134.  
  135.         AAA                     AAA                     AAA
  136.         ADC AX, SI              SI AX ADC               ADC AX,SI
  137.         ADC DX, 0 [SI]          0 [SI] DX ADC           ADC DX,0[SI]
  138.         ADC 2 [BX+SI], DI       DI 2 [BX+SI] ADC        ADC 2[BX][SI],DI
  139.         ADC MEM BX              BX MEM #) ADC           ADC MEM,BX
  140.         ADC AL, # 5             5 # AL ADC              ADC AL,5
  141.         AND AX, BX              BX AX AND               AND AX,BX
  142.         AND CX, MEM             CX MEM #) AND           AND CX,MEM
  143.         AND DL, # 3             3 # DL AND              AND DL,3
  144.         CALL NAME               NAME #) CALL            CALL NAME
  145.         CALL FAR [] NAME        FAR [] NAME #) CALL     ?????
  146.         CMP DX, BX              BX DX CMP               CMP DX,BX
  147.         CMP 2 [BP], SI          SI 2 [BP] CMP           CMP [BP+2],SI
  148.         DEC BP                  BP DEC                  DEC BP
  149.         DEC MEM                 MEM DEC                 DEC MEM
  150.         DEC 3 [SI]              3 [SI] DEC              DEC 3[SI]
  151.         DIV CL                  CL DIV                  DIV CL
  152.         DIV MEM                 MEM DIV                 DIV MEM
  153.         IN PORT# WORD           WORD PORT# IN           IN AX,PORT#
  154.         IN PORT#                PORT# IN                IN AL,PORT#
  155.         IN AX, DX               DX AX IN                IN AX,DX
  156.         INC MEM                 BYTE MEM INC            INC MEM BYTE
  157.         INC MEM WORD            MEM #) INC              INC MEM WORD
  158.         INT 16                  16 INT                  INT 16
  159.         JA NAME                 NAME JA                 JA NAME
  160.         JNBE NAME               NAME #) JNBE            JNBE NAME
  161.         JMP NAME                NAME #) JMP             JMP
  162.         LODSW                   AX LODS                 LODS WORD
  163.         LODSB                   AL LODS                 LODS BYTE
  164.         LOOP NAME               NAME #) LOOP            LOOP NAME
  165.         MOV AX, BX              BX AX MOV               MOV AX,BX
  166.         MOV AH, AL              AL AH MOV               MOV AH,AL
  167.         MOV BP, 0 [BX]          0 [BX] BP MOV           MOV BP,0[BX]
  168.         MOV ES: BP, SI          ES: BP SI MOV           MOV ES:BP,SI
  169.         MOVSW                   AX MOVS                 MOVS WORD
  170.         POP DX                  DX POP                  POP DX
  171.         POPF                    POPF                    POPF
  172.         PUSH SI                 SI PUSH                 PUSH SI
  173.         REP                     REP                     REP
  174.         RET                     RET                     RET
  175.         ROL AX, # 1             AX ROL                  ROL AX,1
  176.         ROL AX, CL              AX CL ROL               ROL AX,CL
  177.         SHL AX, # 1             AX SHL                  SHL AX,1
  178.         XCHG AX, BP             BP AX XCHG              XCHG AX,BP
  179.         XOR CX, DX              DX, CX XOR              XOR CX,DX
  180.  
  181.   PASM defaults to Prefix notation, but can be switched to F83 style
  182. Postfix notation with the word POSTFIX. To revert back to Prefix notation,
  183. use PREFIX.
  184.  
  185.   See the file ASSEM.TXT for a further description of the syntax.
  186.  
  187.  
  188. Some comments about the Internals of the Assembler
  189. ==================================================
  190.  
  191.         1. Although this was originally based on Duncan's 8086
  192.         assembler, Robert L. Smith and Tom Zimmer have modified
  193.         this assembler to handle PREFIX notation.  This version
  194.         is highly dependent in Zimmer's Forth (F-PC, F-TZ, etc.).
  195.         It is interesting to note how much of Duncan's original
  196.         assembler still exists in this package.  In fact, this
  197.         assembler seems to be closer to Duncan's original than
  198.         assembler in Laxon&Perry's F83.
  199.  
  200.         2. This assembler depends on the Kernel functions:
  201.              RUN, DEFER, CREATE, and DOES>
  202.         for its functioning.  DEFER is used (among other things)
  203.         to provide the hooks for the meta-compilation process.
  204.         CREATE and DOES> provide the capability to create the defining
  205.         words which define the instructions as well as the register
  206.         notations.  RUN and DEFER are used to create the capability
  207.         to handle the PREFIX notation.
  208.  
  209.         3. The Local Labels, Inline-NEXT, and INLINE code functions
  210.         are built on top of the basic assembler.
  211.  
  212.         4. The register operand functions define a set of words which
  213.         use the register names as the definition names.  At run-time,
  214.         these definitions store values into a set of variables to
  215.         indicate what registers have been specified and what their
  216.         order was.  These information is used to complete the
  217.         instruction at "instruction build" time.
  218.  
  219.         5. The basic process of the assembler uses the CREATE DOES>
  220.         construct to create the code to handle both the register
  221.         definitions and the instruction definitions.  Each set of
  222.         registers or instructions are grouped into categories and
  223.         a defining word is created for each category.  These defining
  224.         words create the definitions (one for each register specification
  225.         or instruction) which (at run-time) creates the code which
  226.         is the equivalent instruction.  My, how powerful this is in
  227.         that the whole assembler is created using only FORTH (no CODE
  228.         definitions).
  229.  
  230.         6.  The original POSTFIX format process is fairly easy to understand.
  231.         A defining word is created for each instruction category.  This
  232.         word contains the fixed (e.g., opcode) portion of the instruction
  233.         as data in the CREATE part of the defining word (the address of
  234.         this data is passed to the run-time or DOES> code).  Immediate data
  235.         or the addresses of VARIABLEs are placed on the stack.  The register
  236.         functions set other (internal) variables to values which indicate
  237.         the register, register size, etc.  The register specifications,
  238.         immediate data, addresses, etc. must be place before the instruction.
  239.         When the instruction-word is executed, it uses the data from the
  240.         stack or internal variables together with the pre-compiled "opcode"
  241.         data to assemble the instruction into memory.
  242.  
  243.         7. The new PREFIX format modifies the process slightly - the
  244.         instruction-word now occurs BEFORE the operand information.
  245.         To accomodate this format, the instruction-word saves the
  246.         address of passed data and the address of a subroutine to
  247.         build the instruction into a special (internal) variable: APRIOR.
  248.         Execution of the save information is executed at a deferred time -
  249.         this time can be when the next assembly instruction mnemonic occurs,
  250.         when the END-CODE function is executed or at the end of a physical
  251.         line.  At the "deferred time", the instruction has all of the
  252.         information necessary to build the correct code.
  253.  
  254.  
  255.  
  256. comment;
  257.  
  258.  
  259. ONLY FORTH ALSO DEFINITIONS
  260.  
  261. 0 VALUE ?LISTING
  262. 0 VALUE LRUNSAVE
  263. 0 VALUE LINESTRT
  264.  
  265. DEFER LIHERE    ' HERE IS LIHERE
  266. DEFER LIC@      ' C@   IS LIC@
  267.  
  268. : <LRUN>        ( -- )
  269.                 LIHERE =: LINESTRT
  270.                 <RUN>
  271.                 BASE @ >R HEX
  272.                 CR LINESTRT 4 U.R SPACE
  273.                 LIHERE
  274.                 IF      LINESTRT LIHERE OVER - 5 MIN BOUNDS
  275.                         ?DO     I LIC@ 0 <# # # BL HOLD #> TYPE
  276.                         LOOP
  277.                 THEN    22 #OUT @ - SPACES
  278.                 TIB #TIB @ TYPE
  279.                 R> BASE ! ;
  280.  
  281. : /LISTING      ( -- )
  282. \       Enable "listing" output when assembling/compiling
  283.                 ON> ?LISTING
  284.                 LRUNSAVE ABORT" Already LISTING!"
  285.                 @> RUN =: LRUNSAVE
  286.                 ['] <LRUN> IS RUN ;
  287.  
  288. : /NOLISTING    ( -- )
  289. \       Disable "listing" output when assembling/compiling
  290.                 OFF> ?LISTING
  291.                 LRUNSAVE IS RUN
  292.                 OFF> LRUNSAVE ;
  293.  
  294. DEFER .INST     ' NOOP IS .INST
  295.  
  296.  
  297. ONLY FORTH ALSO ASSEMBLER DEFINITIONS ALSO
  298.  
  299.  
  300. 2VARIABLE APRIOR  4 ALLOT       \ PREFIX's deferred-instruction save area
  301.  
  302.         ' DROP APRIOR ! ' DROP APRIOR 4 + !
  303.  
  304.  
  305. : <A;!>         ( A1 A2 --- )           \ Set up assembly instruction
  306.                 APRIOR 4 + 2! ;         \ completion function
  307.  
  308. : <A;>          ( --- )
  309. \       Completes the assembly of the previous instruction (used in
  310. \       INLINE coding).
  311.                 APRIOR 2@ EXECUTE       \ perform assembly completion
  312.                 APRIOR 4 + 2@ APRIOR 2! \ SET UP FOR NEXT PREVIOUS
  313.                 ['] DROP APRIOR 4 + !   \ Make it not care if it is redone.
  314.                 .INST
  315. \                LIHERE =: LINESTRT
  316.                 ;
  317.  
  318. : <RUN-A;>      ( --- )                 \ make sure we complete instruction
  319.                 ?LISTING
  320.                 IF      LIHERE =: LINESTRT
  321.                         <RUN> <A;>
  322.                         BASE @ >R HEX
  323.                         CR LINESTRT 4 U.R SPACE
  324.                         LIHERE
  325.                         IF      LINESTRT LIHERE OVER - 5 MIN BOUNDS
  326.                                 ?DO     I LIC@ 0 <# # # BL HOLD #> TYPE
  327.                                 LOOP
  328.                         THEN    22 #OUT @ - SPACES
  329.                         TIB #TIB @ TYPE
  330.                         R> BASE !
  331.                 ELSE    <RUN> <A;>      \ at the end of each line.
  332.                 THEN    ;
  333.  
  334. VARIABLE POSTVAR                        \ is this post fix notation?
  335.  
  336. Variable ASM.cpu                        \ Determines Assembler Mode
  337.  
  338. Variable ASM.warn                       \ Switch for warning messages
  339.    ASM.warn off
  340.  
  341.  
  342. FORTH DEFINITIONS
  343.  
  344. DEFER A;!       ' <A;!>    IS A;!
  345. DEFER A;        ' <A;>     IS A;
  346. \       Completes the assembly of the previous instruction (used in
  347. \       INLINE coding).
  348.  
  349. DEFER RUN-A;    ' <RUN-A;> IS RUN-A;
  350.  
  351. : PREFIX        ( --- )
  352. \       Assert prefix mode for the following code definitions.
  353.                 ['] <A;!>    IS A;!
  354.                 ['] <A;>     IS A;
  355.                 ['] <RUN-A;> IS RUN-A;  POSTVAR OFF ;
  356.  
  357. : POSTFIX       ( --- )
  358. \       Assert posrfix mode for the following code definitions.
  359.                 ['] EXECUTE  IS A;!
  360.                 ['] NOOP     IS A;
  361.                 ['] <RUN>    IS RUN-A;  POSTVAR ON ;
  362.  
  363. PREFIX          \ Default is PREFIX assembler.
  364.  
  365. : >PRE          2R> POSTVAR @ >R 2>R PREFIX ;    \ SAVE AND SET PREFIX
  366. \       Restore the previously saved setting of prefix/postfix mode.
  367.  
  368. : PRE>          2R> R> IF POSTFIX THEN 2>R ;     \ RESTORE PREVIOUS FIX
  369. \       Save current prefix/postfix setting and set prefix mode.
  370.  
  371. : ASM.8086      ( --- )
  372. \       DEFAULT -- generate only 8086/8088 code
  373.                 ASM.cpu off ;
  374.  
  375. : ASM.386       ( --- )
  376. \       Generate 80386/80386SX code.  This will also generate those
  377. \       instruction which only work on the 80286.
  378.                 ASM.cpu ON  ;
  379.  
  380. ASM.8086                \ default
  381.  
  382.  
  383.  
  384. ASSEMBLER DEFINITIONS
  385.  
  386.         DEFER C,         FORTH ' C,     ASSEMBLER IS C,
  387.         DEFER ,          FORTH ' ,      ASSEMBLER IS ,
  388.         DEFER HERE       FORTH ' HERE   ASSEMBLER IS HERE
  389.                                                              ' HERE IS LIHERE
  390.         DEFER TC!       FORTH ' C!      ASSEMBLER IS TC!
  391.         DEFER TC@       FORTH ' C@      ASSEMBLER IS TC@
  392.                                                              ' TC@  IS LIC@
  393.         DEFER T!        FORTH ' !       ASSEMBLER IS T!
  394.  
  395.         DEFER ?>MARK
  396.         DEFER ?>RESOLVE
  397.         DEFER ?<MARK
  398.         DEFER ?<RESOLVE
  399.  
  400. comment:
  401.  
  402.         The assembler contains the following routines for labels,
  403.         with +/- 127 byte offsets. They are used as follows:
  404.  
  405.                 CLEAR_LABELS    \ Reset label mechanism
  406.  
  407.                 SUB AX, AX
  408.                 JNE 2 $         \ Jump on not equal to label # 2
  409.                 ...
  410.                 ...             \ You can have up to 127 bytes between
  411.                 ...
  412.            2 $: MOV AX, BX      \ Destination of labeled jump.
  413.  
  414.         A total of 32 short labels are currently supported.
  415.  
  416.         The assembler also supports ONE long label.
  417.  
  418.         Use L$ as follows:      \ Usable with JMP or CALL
  419.  
  420.                 JMP L$          \ Does a long jump to L$:
  421.                 ...
  422.                 ...             \ A bunch of bytes occur between these
  423.                 ...             \ instructions
  424.                 ...
  425.             L$: MOV X, X        \ Destination of long jump
  426. comment;
  427.  
  428. \ ===========================================================================
  429. \               BEGIN LOCAL LABELS SECTION:
  430. \ ===========================================================================
  431.  
  432.            \ "max-llabs" defines the maximum number of local labels
  433.            \ allowed (per CODE word or LABEL word).  The labels may be
  434.            \ any of the values 0, 1, ..., (max-llabs - 1)
  435.  
  436. $20 value max-llabs
  437.   5 value b/llab
  438. false value ll-global?     \ are local labels available globally?
  439.  
  440.  
  441.            \ The local label table consists of one line per entry.
  442.            \ Each line consists of:
  443.            \
  444.            \     1.  The label dictionary location,  ( 2 bytes)
  445.            \
  446.            \     2.  a pointer to the location of the first forward
  447.            \         reference (if any), and         ( 2 bytes)
  448.            \
  449.            \     3.  an "ever referenced?" flag.     ( 1 byte )
  450.  
  451. create %llab[] max-llabs b/llab * allot
  452.  
  453. %llab[] value llab[]            \ default to %llab[] array
  454.  
  455. \          This flag is set if local labels are ever used (i.e., the
  456. \          "$" or the "$:" word is used within a CODE word or a LABEL
  457. \          word).  The idea is simply to add a smidgen more time to the
  458. \          "$" and "$:" words to save time later when checking for
  459. \          local label errors when END-CODE is called.
  460.  
  461. false value ll-used?
  462.  
  463. : llab-init     ( -- )
  464. \       Clear the local label mechanism to a clean or unused state in
  465. \       preparation for using local labels.  This word need only be
  466. \       used in the GLOBAL_REFS mode.  In LOCAL_REFS mode, the
  467. \       CLEAR_LABELS function is performed automatically.
  468.                 llab[]  max-llabs b/llab * erase
  469.                 false !> ll-used? ;
  470.  
  471. ' LLAB-INIT ALIAS CLEAR_LABELS
  472.  
  473.  
  474. headerless              \ ***************************************************
  475.  
  476.  
  477.            \ Given a label number, returns pointer to line in table.
  478.            \ Aborts if label out of range.
  479.  
  480. : llab>line  ( n -- ^line )
  481.   dup max-llabs 1- u> abort" Bad Label"
  482.   b/llab * llab[] + ;
  483.  
  484.            \ Translates a label reference to the appropriate dictionary
  485.            \ location and sets the "ever referenced?" flag.
  486.            \
  487.            \ If the reference is a forward reference, then a linked list
  488.            \ of the forward references themselves is built using the
  489.            \ dictionary byte locations where the jump offsets are
  490.            \ "compiled".  The reason for using this technique at all is
  491.            \ that it allows an arbitrary number of forward references per
  492.            \ label to be made (within the jump offset limitations of
  493.            \ course) and that it requires table space only for the linked
  494.            \ list head pointer.  The technique is eloquent if convoluted
  495.            \ and, as a minimum, needs explanation.
  496.  
  497. headers                 \ ***************************************************
  498.  
  499. : $  ( n1 -- n2 )
  500.   true !> ll-used?          \ set "labels used?" flag
  501.   llab>line 1 over 4 + c!   \ set "ever referenced?" flag
  502.   dup @ IF      \ if the label is already defined:
  503.     @           \   then return it for resolution
  504.   ELSE          \ otherwise:
  505.     2+          \   move to head of list pointer
  506.     dup @ >r    \   save old head of list on rstack
  507.     here swap ! \   set new head of list
  508.     r>          \   retrieve old head of list
  509.     dup 0= IF   \   if list is empty:
  510.       here +    \     pass current dictionary location
  511.     THEN        \   end-if
  512.   THEN ;        \ end-if
  513.  
  514. headerless              \ ***************************************************
  515.  
  516.  
  517.  
  518.            \ Resolves all local label forward references for a given
  519.            \ label.
  520.  
  521. : >res  ( ^line -- )
  522.   2+ @ dup 0= IF    \ if nothing to resolve
  523.     drop exit       \   then exit
  524.   THEN
  525.   1+ BEGIN          \ stack contains directory address of
  526.                     \   displacement to be resolved
  527.     dup TC@ >r       \ save link for now -- 3.50
  528.     here over - 1-  \ calculate displacement
  529.     dup $7f > abort" Branch out of range"
  530.     over TC!         \   and put in jump instruction -- 3.50
  531.     r>              \ now ready for next link
  532.     $fe over <> WHILE   \ $fe value signifies end of list
  533.     $ff00 or        \ sign extend since link is backward
  534.     + 2+            \ now move to next item on list
  535.   REPEAT 2drop ;
  536.  
  537. : $:f  ( n -- )     \ defines a local label
  538.   true !> ll-used?  \ set "labels used?" flag
  539.   llab>line
  540.   dup @ 0<> abort" Label can't be multiply defined"
  541.   dup >res          \ resolve forward references if needed
  542.   here swap ! ;     \ and set label for subsequent refs
  543.  
  544. headers                 \ ***************************************************
  545.  
  546. : $:  ( n -- )      \ allow use as prefix/postfix
  547.   ['] $:f a;! a; ;
  548.  
  549. headerless              \ ***************************************************
  550.  
  551. : _ll-errs?  ( -- )  \ final error checking for local labels
  552.   false max-llabs 0 DO  \ check each label
  553.     i b/llab * llab[] +
  554.     dup 4 + c@ 0<> IF   \ if jumps to label
  555.       @ 0= IF           \   and no label to jump to
  556.         cr ." jump(s) to label " i .
  557.           ." and label not defined"
  558.         drop true       \ set error flag
  559.       THEN
  560.     ELSE                \ if no jumps to label
  561.       @ 0<> IF          \   and label defined
  562.         cr ." warning - label " i .
  563.            ." defined, but no jumps to it"
  564.       THEN
  565.     THEN
  566.   LOOP
  567.   IF abort THEN ;       \ abort if fatal error
  568.  
  569. : ll-errs?  ( -- )      \ final error checking for local labels
  570.   ll-used? IF _ll-errs? THEN ;
  571.  
  572. \ ===========================================================================
  573. \                END LOCAL LABELS SECTION:
  574. \ ===========================================================================
  575.  
  576. headers                 \ ***************************************************
  577.  
  578. : L$            ( --- a1 )              \ Pass a1 to L$:
  579.                 0 A; HERE ;
  580.  
  581. : L$:           ( a1 --- )              \ a1 = addr passed by L$
  582.                 A; HERE OVER - SWAP 2- T! ;
  583.  
  584. \ ===========================================================================
  585. \          End of Local Label definitions
  586. \ ===========================================================================
  587.  
  588. FORTH DEFINITIONS
  589.  
  590. headerless              \ ***************************************************
  591.  
  592. ' <RUN> VALUE ARUNSAVE  \ -- 3.50
  593.  
  594. : DOASSEM       ( --- )
  595.                 @> RUN =: ARUNSAVE              \ -- 3.50
  596.                   ['] RUN-A; IS RUN
  597.                 0 ['] DROP A;!
  598.                 APRIOR 4 + 2@ APRIOR 2!
  599.                 LIHERE =: LINESTRT              \ -- 3.50
  600.                 ll-global? 0=
  601.                 if      llab-init               \ in case labels used
  602.                 then
  603.                 ALSO ASSEMBLER ;
  604.  
  605. ' DOASSEM IS SETASSEM
  606.  
  607. headers                 \ ***************************************************
  608.  
  609.  
  610. : LOCAL_REF     ( --- )
  611. \       Set the mode so that local labels will NOT cross CODE word
  612. \       boundaries.  The local label mechanism is cleared each time
  613. \       a new CODE word is started.  This is the default mode.
  614.                 OFF> LL-GLOBAL? ;       LOCAL_REF
  615.                                         \ default to LOCAL references only
  616.  
  617. : GLOBAL_REF    ( --- )
  618. \       Set the mode so that local labels can cross CODE definition
  619. \       boundaries.  All local label definitions will be available
  620. \       and the mechanism is NOT reset at the beginning of a CODE
  621. \       definition.  The local label mechanism must be reset with
  622. \       the CLEAR_LABELS function before using this mode.
  623.                 ON> LL-GLOBAL? ;
  624.  
  625. : LABEL         ( NAME --- )            \ Really just a constant addr
  626. \       Start an assembly routine or mark the current code address
  627. \       to be referenced later.
  628.                 SETASSEM CREATE ;
  629.  
  630. : CODE          ( NAME --- )
  631. \       Define "name" as a new code definition. Assembly language
  632. \       follows, terminated by END-CODE.
  633.                 LABEL -3 DP +! HIDE ;
  634.  
  635. ASSEMBLER DEFINITIONS
  636.  
  637. : END-CODE
  638. \       Terminates CODE definitions.
  639.                 ll-global? 0=
  640.                 if      ll-errs?        \ check for local label errors
  641.                 then
  642.                 ARUNSAVE IS RUN         \ -- 3.50
  643.                 PREVIOUS A; REVEAL ;
  644.  
  645. ' END-CODE ALIAS C;
  646.  
  647. headerless              \ ***************************************************
  648.  
  649.  
  650. \ ===========================================================================
  651. \          Errors detected during assembly, ABORT
  652. \ ===========================================================================
  653.  
  654. : ERROR3        ( --- )
  655.                 ['] DROP APRIOR 4 + !   \ Make it not care if it is redone.
  656.                 TRUE ABORT"  Illegal Operand "  ;
  657.  
  658. : ERROR4        ( f1 --- )
  659.                 IF
  660.                    ['] DROP APRIOR 4 + !   \ Make it not care if it is redone.
  661.                    TRUE ABORT"  Illegal Operand Range"
  662.                 THEN ;
  663.  
  664. : ERROR5        ( f1 --- )
  665.                 IF
  666.                    ['] DROP APRIOR 4 + !   \ Make it not care if it is redone.
  667.                    TRUE ABORT"  Illegal Operand Register"
  668.                 THEN ;
  669. : Error6        ( f --- )               \ Wrong Reg specified
  670.                 IF
  671.                    ['] DROP APRIOR 4 + !   \ Make it not care if it is redone.
  672.                    TRUE abort" Bad IN/OUT Register"
  673.                 THEN ;
  674.  
  675.  
  676. : ?ORDERERROR   ( F1 --- )
  677.                 IF      ['] DROP APRIOR 4 + !
  678.                         TRUE ABORT" Wrong Operand Order! "
  679.                 THEN    ;
  680.  
  681. : WarnMsg       ( --- )
  682.                 CR ." file=" .seqhandle
  683.                 ."  at line " BASE @ Decimal LOADLINE @ U. Base ! CR ;
  684.  
  685. : Chk.386       ( --- )
  686.                 ASM.cpu @ not abort" Invalid Instruction/Operand" ;
  687.  
  688.  
  689.  
  690.  
  691.  
  692.  
  693.  
  694.  
  695.  
  696.  
  697. \ ===========================================================================
  698. \ ===========================================================================
  699. \          Functions, etc. to support Operands
  700. \ ===========================================================================
  701. \ ===========================================================================
  702.  
  703.  
  704.  
  705. \ ===========================================================================
  706. \          Flags, Switches, etc. to define the operand
  707. \
  708. \                For Width:  0=byte, 1=word, -1=Special
  709. \ ===========================================================================
  710.  
  711.         VARIABLE <TD>           \ Destination Addressing Type
  712.         VARIABLE <TS>           \ Source      Addressing Type
  713.         VARIABLE <RD>           \ Destination Register
  714.         VARIABLE <RS>           \ Source      Register
  715.         VARIABLE <W>            \             Word/Byte Flag
  716.         VARIABLE <WD>           \ Destination Width (Word/Byte Flag)
  717.         VARIABLE <WS>           \ Source      Width (Word/Byte Flag)
  718.         VARIABLE <WD2>          \ Destination Width (Word/Byte Flag) #2
  719.         VARIABLE <WS2>          \ Source      Width (Word/Byte Flag) #2
  720.         VARIABLE <OD>           \ Destination Offset
  721.         VARIABLE <OS>           \ Source      Offset
  722.         VARIABLE <D>            \       Direction Flag for R/M
  723.         VARIABLE <FR>           \       FAR Flag
  724.         VARIABLE <ND>           \       [] Indiect flag for Jump/Call
  725.         VARIABLE <DST>          \ Destination Processed Flag
  726.         VARIABLE <SST>          \ Source      Processed Flag
  727.         VARIABLE <ID>           \       Immediate Data Flag
  728.         VARIABLE <E>            \             386 Extended Processing Flag
  729.         VARIABLE <ES>           \ Source      386 Extended Processing Flag
  730.         VARIABLE <ED>           \ Destination 386 Extended Processing Flag
  731.         VARIABLE <es2>          \ Source      386 Extended Processing Flag #2
  732.         VARIABLE <ed2>          \ Destination 386 Extended Processing Flag #2
  733.         Variable <I1>           \ ... Temporary Storage for first 16 bits of immediate data
  734.         Variable <I2>           \ ... Temporary Storage for last  16 bits of immediate data (that is, 32 bit data)
  735.         VARIABLE <FW>           \ NPX ("F") word-type
  736.  
  737.  
  738. \ ===========================================================================
  739. \          Equates to Addressing Modes
  740. \ ===========================================================================
  741.  
  742.         0 CONSTANT DIRECT
  743.         1 CONSTANT IMMED
  744.         2 CONSTANT REG8
  745.         3 CONSTANT REG16
  746.         4 CONSTANT INDEXED
  747.         5 CONSTANT SEGREG
  748.  
  749.  
  750. \ ===========================================================================
  751. \          Functions to Build and then Do Processing for Registers
  752. \ ===========================================================================
  753.  
  754. : <SREG>        ( A1 --- )
  755.                 POSTVAR @ IF      <DST> OFF       \ Only reset dest if postfix
  756.                           THEN
  757.                 <SST> ON
  758.                 DUP C@
  759.                 DUP $FF = IF
  760.                      DROP
  761.                 ELSE
  762.                      dup <ws2> !
  763.                      DUP <W> ! <WS> !
  764.                 THEN
  765.                 1+ DUP C@ <TS> !
  766.                 1+ dup C@ <RS> !
  767.                 1+     C@ dup <ES> ! <es2> !
  768.                 <TS> @ 4 = IF <OS> ! THEN ;
  769.  
  770. : <DREG>        ( A1 --- )
  771.                 <DST> ON
  772.                 DUP C@ DUP $FF = IF
  773.                      DROP
  774.                 ELSE
  775.                      dup <wd2> !
  776.                      DUP <W> !  <WD> !
  777.                 THEN
  778.                 1+ DUP C@ <TD> !
  779.                 1+ DUP C@ <RD> !
  780.                 1+     C@ dup <ED> ! <ed2> !
  781.                 <TD> @ 4 = IF <OD> ! THEN ;
  782.  
  783. \ Destination Register processing.
  784.  
  785. : DREG          CREATE C, C, C, C,                      \ Store input parameters
  786.                 DOES>
  787.                 POSTVAR @ IF   <SREG>                   \ Source if PostFix
  788.                           ELSE <DREG>                   \ but Dest if PreFix
  789.                           THEN    ;
  790.  
  791. \ Source Register processing.
  792.  
  793. : SREG          CREATE C, C, C, C,                      \ store input parameters
  794.                 DOES>
  795.                 POSTVAR @ IF   <SST> @ IF   <DREG>      \ if PostFix Mode & source defined, then dest
  796.                                                         \ (this provides F83 compatability)
  797.                                        ELSE <SREG>      \ else is source
  798.                                        THEN
  799.                           ELSE <SREG>                   \ else is source
  800.                           THEN    ;
  801.  
  802.  
  803. headers                 \ ***************************************************
  804.  
  805.  
  806.  
  807. \ ===========================================================================
  808. \          Initialize all variables and flags
  809. \ ===========================================================================
  810.  
  811. : RESET   0 <W>   ! 0 <OS>  ! 0 <RD>  !
  812.           0 <TD>  ! 0 <TS>  ! 0 <OD>  !
  813.           0 <D>   ! 0 <WD>  ! 0 <RS>  ! 0 <FR>  ! 0 <ND>  !
  814.           0 <E>   ! 0 <ED>  ! 0 <ES>  !
  815.           0 <es2> ! 0 <ed2> ! 0 <ws2> ! 0 <wd2> !
  816.           0 <DST> ! 0 <SST> ! 0 <WS>  ! 0 <ID>  ! ;
  817.  
  818. \ ===========================================================================
  819. \          Source Register Definitions
  820. \ ===========================================================================
  821.  
  822. \ E  Reg  Type W        Name
  823.   0  0    2    0  SREG  AL                              \ Low  Byte
  824.   0  1    2    0  SREG  CL
  825.   0  2    2    0  SREG  DL
  826.   0  3    2    0  SREG  BL
  827.   0  4    2    0  SREG  AH                              \ High Byte
  828.   0  5    2    0  SREG  CH
  829.   0  6    2    0  SREG  DH
  830.   0  7    2    0  SREG  BH
  831.   0  0    3    1  SREG  AX                              \ Full Word
  832.   0  1    3    1  SREG  CX
  833.   0  2    3    1  SREG  DX
  834.   0  3    3    1  SREG  BX
  835.   0  4    3    1  SREG  SP                              \ Ptr Regs
  836.   0  5    3    1  SREG  BP              ' BP ALIAS RP
  837.   0  6    3    1  SREG  SI              ' SI alias IP
  838.   0  7    3    1  SREG  DI
  839.  
  840.   3  0    3    1  SREG EAX                              \ 32 bit regs
  841.   3  1    3    1  SREG ECX
  842.   3  2    3    1  SREG EDX
  843.   3  3    3    1  SREG EBX
  844.   3  4    3    1  SREG ESP
  845.   3  5    3    1  SREG EBP
  846.   3  6    3    1  SREG ESI
  847.   3  7    3    1  SREG EDI
  848.  
  849.   0  0    4   -1  SREG  [BX+SI]                         \ Indirect/Indexed
  850.                                         ' [BX+SI] alias [SI+BX]
  851.                                         ' [BX+SI] alias [IP+BX]
  852.                                         ' [BX+SI] alias [BX+IP]
  853.   0  1    4   -1  SREG  [BX+DI]
  854.                                         ' [BX+DI] alias [DI+BX]
  855.   0  2    4   -1  SREG  [BP+SI]
  856.                                         ' [BP+SI] ALIAS [SI+BP]
  857.                                         ' [BP+SI] ALIAS [BP+IP]
  858.                                         ' [BP+SI] ALIAS [RP+IP]
  859.                                         ' [BP+SI] ALIAS [IP+BP]
  860.                                         ' [BP+SI] ALIAS [IP+RP]
  861.   0  3    4   -1  SREG  [BP+DI]
  862.                                         ' [BP+DI] alias [DI+BP]
  863.                                         ' [BP+DI] ALIAS [RP+DI]
  864.                                         ' [BP+DI] ALIAS [DI+RP]
  865.   0  4    4   -1  SREG  [SI]            ' [SI] alias [IP]
  866.   0  5    4   -1  SREG  [DI]
  867.   0  6    4   -1  SREG  [BP]            ' [BP] ALIAS [RP]
  868.   0  7    4   -1  SREG  [BX]
  869.  
  870.   0  0    5   -1  SREG  ES                              \ Segment Regs
  871.   0  1    5   -1  SREG  CS
  872.   0  2    5   -1  SREG  SS
  873.   0  3    5   -1  SREG  DS
  874.   9  4    5   -1  SREG  FS                              \ 386 Extra Seg Regs
  875.   9  5    5   -1  SREG  GS
  876.  
  877.   0  0    6    1  SREG  ST
  878.   0  0    6    1  SREG  ST0
  879.   0  0    6    1  SREG  ST(0)
  880.   0  1    6    1  SREG  ST1
  881.   0  1    6    1  SREG  ST(1)
  882.   0  2    6    1  SREG  ST2
  883.   0  2    6    1  SREG  ST(2)
  884.   0  3    6    1  SREG  ST3
  885.   0  3    6    1  SREG  ST(3)
  886.   0  4    6    1  SREG  ST4
  887.   0  4    6    1  SREG  ST(4)
  888.   0  5    6    1  SREG  ST5
  889.   0  5    6    1  SREG  ST(5)
  890.   0  6    6    1  SREG  ST6
  891.   0  6    6    1  SREG  ST(6)
  892.   0  7    6    1  SREG  ST7
  893.   0  7    6    1  SREG  ST(7)
  894.  
  895. \ ===========================================================================
  896. \          Destination Register Definitions
  897. \               - Note the comma after the register specification.
  898. \ ===========================================================================
  899.  
  900. \ E  Reg  Type W        Name
  901.   0  0    2    0  DREG  AL,                             \ Low  Byte
  902.   0  1    2    0  DREG  CL,
  903.   0  2    2    0  DREG  DL,
  904.   0  3    2    0  DREG  BL,
  905.   0  4    2    0  DREG  AH,                             \ High Byte
  906.   0  5    2    0  DREG  CH,
  907.   0  6    2    0  DREG  DH,
  908.   0  7    2    0  DREG  BH,
  909.   0  0    3    1  DREG  AX,                             \ Full Word
  910.   0  1    3    1  DREG  CX,
  911.   0  2    3    1  DREG  DX,
  912.   0  3    3    1  DREG  BX,
  913.   0  4    3    1  DREG  SP,                             \ Ptr  Regs
  914.   0  5    3    1  DREG  BP,             ' BP, ALIAS RP,
  915.   0  6    3    1  DREG  SI,             ' SI, ALIAS IP,
  916.   0  7    3    1  DREG  DI,
  917.  
  918.   3  0    3    1  DREG EAX,                             \ 32 bit regs
  919.   3  1    3    1  DREG ECX,
  920.   3  2    3    1  DREG EDX,
  921.   3  3    3    1  DREG EBX,
  922.   3  4    3    1  DREG ESP,
  923.   3  5    3    1  DREG EBP,
  924.   3  6    3    1  DREG ESI,
  925.   3  7    3    1  DREG EDI,
  926.  
  927.   0  0    4   -1  DREG  [BX+SI],                        \ Indirect/Indexed
  928.                                         ' [BX+SI], alias [SI+BX],
  929.                                         ' [BX+SI], alias [BX+IP],
  930.                                         ' [BX+SI], alias [IP+BX],
  931.   0  1    4   -1  DREG  [BX+DI],
  932.                                         ' [BX+DI], alias [DI+BX],
  933.   0  2    4   -1  DREG  [BP+SI],
  934.                                         ' [BP+SI], alias [SI+BP],
  935.                                         ' [BP+SI], alias [BP+IP],
  936.                                         ' [BP+SI], alias [IP+BP],
  937.   0  3    4   -1  DREG  [BP+DI],
  938.                                         ' [BP+DI], alias [DI+BP],
  939.   0  4    4   -1  DREG  [SI],           ' [SI], ALIAS [IP],
  940.   0  5    4   -1  DREG  [DI],
  941.   0  6    4   -1  DREG  [BP],           ' [BP], ALIAS [RP],
  942.   0  7    4   -1  DREG  [BX],
  943.  
  944.   0  0    5   -1  DREG  ES,                             \ Segment Regs
  945.   0  1    5   -1  DREG  CS,
  946.   0  2    5   -1  DREG  SS,
  947.   0  3    5   -1  DREG  DS,
  948.   9  4    5   -1  DREG  FS,                             \ 386 extra seg regs
  949.   9  5    5   -1  DREG  GS,
  950.  
  951.   0  0    6    1  DREG  ST,
  952.   0  0    6    1  DREG  ST0,
  953.   0  0    6    1  DREG  ST(0),
  954.   0  1    6    1  DREG  ST1,
  955.   0  1    6    1  DREG  ST(1),
  956.   0  2    6    1  DREG  ST2,
  957.   0  2    6    1  DREG  ST(2),
  958.   0  3    6    1  DREG  ST3,
  959.   0  3    6    1  DREG  ST(3),
  960.   0  4    6    1  DREG  ST4,
  961.   0  4    6    1  DREG  ST(4),
  962.   0  5    6    1  DREG  ST5,
  963.   0  5    6    1  DREG  ST(5),
  964.   0  6    6    1  DREG  ST6,
  965.   0  6    6    1  DREG  ST(6),
  966.   0  7    6    1  DREG  ST7,
  967.   0  7    6    1  DREG  ST(7),
  968.  
  969. \ ===========================================================================
  970. \
  971. \ ===========================================================================
  972.  
  973. : WORD-TYPE CREATE C, DOES> C@ <FW> ! ;
  974.  
  975. $01 WORD-TYPE REAL*4
  976. $03 WORD-TYPE INTEGER*4
  977. $2B WORD-TYPE TEMP_REAL
  978. $05 WORD-TYPE REAL*8
  979. $07 WORD-TYPE INTEGER*2
  980. $27 WORD-TYPE BCD
  981. $2F WORD-TYPE INTEGER*8
  982.  
  983. VARIABLE WAIT? WAIT? ON
  984.  
  985. : NOWAIT
  986.                 WAIT? OFF ;
  987.  
  988.  
  989. headerless              \ ***************************************************
  990.  
  991.  
  992. \ ===========================================================================
  993. \          Miscellaneous Operators
  994. \ ===========================================================================
  995.  
  996.         : TS@     <TS> @ ;              \ fetch source      addr type
  997.         : TD@     <TD> @ ;              \ fetch destination addr type
  998.         : RD@     <RD> @ ;              \ fetch destination register code
  999.         : RS@     <RS> @ ;              \ fetch source      register code
  1000.         : ED@     <ED> @ ;              \ Fetch Destination Extended Mode
  1001.         : ES@     <ES> @ ;              \ Fetch Source      Extended Mode
  1002.         : +D      <D> @ 2* + ;          \ merge direction flag into opcode
  1003.         : +W      <W> @ + ;             \ fetch word/byte flag
  1004.         : +RD     <RD> @ + ;            \ merge destination register code
  1005.         : +RS     <RS> @ + ;            \ merge source      register code
  1006.         : MOD1    $3F AND $40 OR ;      \ set mod field to 01
  1007.         : MOD2    $3F AND $80 OR ;      \ set mod field to 10
  1008.         : MOD3    $3F AND $C0 OR ;      \ set mod field to 11
  1009.  
  1010.         : RS0    <RS> @ 8* ;
  1011.         : RSD    RS0 +RD ;
  1012.         : MD,    RS0 6 + C, ;
  1013.         : MS,    RD@ 8* 6 + C, ;
  1014.         : RDS    RD@ 8* +RS ;
  1015.         : CXD,   C@ MOD3 +RD C, ;
  1016.         : CXS,   C@ MOD3 +RS C, ;
  1017.  
  1018.  
  1019. \ ===========================================================================
  1020. \          Generate Prefix Byte for 386 32-bit Operand Size
  1021. \ ===========================================================================
  1022.  
  1023. : ESprefix      ( n1 -- )
  1024.                 3 = IF  Chk.386 $66 C,  1 <W> !
  1025.                     THEN ;
  1026.  
  1027. \ ===========================================================================
  1028. \          Operand Functions
  1029. \ ===========================================================================
  1030.  
  1031. : D>S           ( --- )                 \ Move destination to source.
  1032.                 <ED> @ <ES> !
  1033.                 <TD> @ <TS> !
  1034.                 <RD> @ <RS> !
  1035.                 <OD> @ <OS> ! ;
  1036.  
  1037. : ?D>S          ( --- )                 \ Move Dest to Src if postfix
  1038.                 <TS> @ 0=               \ If no source specified
  1039.                 POSTVAR @ 0<> AND       \ and we are in postfix mode
  1040.                 IF      D>S             \ Move destination to source
  1041.                 THEN    ;
  1042.  
  1043. : ?D><S         ( --- )                 \ If no destinatiion specified
  1044.                 <DST> @ IF              \ yet, then swap source and dest.
  1045.                         <TD> <TS> 2DUP @ SWAP @ ROT ! SWAP !
  1046.                         <RD> <RS> 2DUP @ SWAP @ ROT ! SWAP !
  1047.                         <OD> <OS> 2DUP @ SWAP @ ROT ! SWAP !
  1048.                         <ED> <ES> 2DUP @ SWAP @ ROT ! SWAP !
  1049.                         THEN
  1050.                 <DST> OFF ;
  1051.  
  1052. \ ===========================================================================
  1053. \          Register Type Tests
  1054. \ ===========================================================================
  1055.  
  1056. : REG?     REG8 OVER = SWAP REG16 = OR ;        \ Test if this is regular reg
  1057.  
  1058. : DREG?   TD@ REG? ;                            \ do reg test for destination
  1059.  
  1060. : ADREG?  DREG? RD@ ( 3 AND ) 0= AND ;          \ check if dest is AL or AX
  1061.  
  1062. : ASREG?  TS@ REG? RS@ ( 3 AND ) 0= AND ;       \ check if source is AL or AX
  1063.  
  1064. : SUBREG  C@ $38 AND ;
  1065.  
  1066. \ ===========================================================================
  1067. \          Init. Direction Pointer
  1068. \ ===========================================================================
  1069.  
  1070. : DSET    TS@ DUP INDEXED = SWAP DIRECT = OR NEGATE <D> ! ;
  1071.  
  1072. \ ===========================================================================
  1073. \          Calculate, Check, and Store 8-bit offset for Jumps, Loops, etc.
  1074. \ ===========================================================================
  1075.  
  1076. : OFFSET8,     HERE 1+ - DUP ABS OVER 0< + $7F >
  1077.                Error4 C, ;
  1078.  
  1079. \ ===========================================================================
  1080. \          Calculate & Store 16-bit offset for Jumps, Loops, etc.
  1081. \ ===========================================================================
  1082.  
  1083. : OFFSET16,    HERE 2+ - , ;
  1084.  
  1085. \ ===========================================================================
  1086. \          Calculate and store displacement for MEM/REG Instructions.
  1087. \ ===========================================================================
  1088.  
  1089. : DISP,         <D> @ IF
  1090.                      <OS>
  1091.                 ELSE
  1092.                      <OD>
  1093.                 THEN
  1094.  
  1095.                 @ DUP IF
  1096.                         DUP ABS $7F
  1097.                         > IF
  1098.                                 SWAP MOD2 C, ,
  1099.                         ELSE
  1100.                                 SWAP MOD1 C, C,
  1101.                         THEN
  1102.                 ELSE
  1103.                         DROP
  1104.                         DUP 7 AND 6 = IF
  1105.                                 MOD1 C, 0
  1106.                         THEN
  1107.                         C,
  1108.                 THEN ;
  1109.  
  1110. \ ===========================================================================
  1111. \          Calculate the M/R 2nd operator byte
  1112. \ ===========================================================================
  1113.  
  1114. : M/RS,
  1115.           $38 AND                               \ the REG part of ModRegR/M
  1116.  
  1117.           TS@ CASE
  1118.  
  1119.              DIRECT  OF
  1120.                         $06 + C, ,
  1121.                      ENDOF
  1122.  
  1123.              REG8    OF
  1124.                         $C0 + +RS C,
  1125.                      ENDOF
  1126.  
  1127.              REG16   OF
  1128.                         $C0 + +RS C,
  1129.                      ENDOF
  1130.  
  1131.              INDEXED OF
  1132.                         <OS> @ 0= RS@ 6 <> AND
  1133.                         IF
  1134.                                 +RS C,
  1135.                         ELSE
  1136.                                 <OS> @ $80 + $100
  1137.                                 U< IF
  1138.                                        $40 + +RS C, <OS> @ C,
  1139.                                 ELSE
  1140.                                        $80 + +RS C, <OS> @ ,
  1141.                                 THEN
  1142.                         THEN
  1143.                      ENDOF
  1144.  
  1145.              ERROR3  drop
  1146.           ENDCASE ;
  1147.  
  1148.  
  1149. : M/RD,         D>S M/RS, ;     \ Copy Dest to Source so ?/RS can process it
  1150.  
  1151.  
  1152. : 8/16,         <W> @ IF , ELSE C, THEN ;
  1153.  
  1154.  
  1155.  
  1156. \ ===========================================================================
  1157. \          Words to build the instructions:
  1158. \
  1159. \ "Stack Pictures"
  1160. \
  1161. \             ( A1 --- )        no operands
  1162. \             ( A1 --- )        just register operands
  1163. \          ( N1 A1 --- )        regs with immediate number operand
  1164. \          ( A2 A1 --- )        memory operand
  1165. \          ( A2 A1 --- )        memory and regs operands
  1166. \       ( A2 N1 A1 --- )        memory and immediate number operands
  1167. \       ( A2 N1 A1 --- )        memory, regs, and immediate number operands
  1168. \          ( D1 A1 --- )        regs with immediate DOUBLE number (32 bit)
  1169. \       ( A2 D1 A1 --- )        memory and immediate DOUBLE number (32 bits)
  1170. \       ( A2 D1 A1 --- )        memory, regs, and immediate DOUBLE number (32 bits)
  1171. \
  1172. \        A1 - points to the run-time op-code parameter list
  1173. \        A2 - an operand (16 bit) memory address
  1174. \        N1 - a 16 bit immediate data number
  1175. \        D1 - a 32 bit immediate data double number
  1176. \
  1177. \ ===========================================================================
  1178.  
  1179. \ Single Byte Instruction -- NO operands
  1180.  
  1181. : 1MIF          ( A1 --- )
  1182.                 C@ C, RESET ;
  1183.  
  1184. : 1MI     CREATE C, DOES> ['] 1MIF A;! A; ;
  1185.  
  1186.  
  1187. \ Conditional Jumps, Loops -- 1 byte plus 8-bit offset
  1188.  
  1189. : 2MIF          ( A1 --- )
  1190.                 C@ C, OFFSET8, RESET ;
  1191.  
  1192. : 2MI     CREATE C, DOES> ['] 2MIF A;! A; ;
  1193.  
  1194.  
  1195. \ Special case single byte instruction for LODS AX, STOS AX, SCAS AX and CMPS AX
  1196.  
  1197. : 3MIF         ( A1 --- )
  1198.                 ES@  ESprefix                   \ 386 EAX
  1199.                 C@ +W C,
  1200.                 RESET ;
  1201.  
  1202. : 3MI      CREATE C, DOES> ['] 3MIF A;! A; ;
  1203.  
  1204.  
  1205. \ IntraSegment Jump/Call -- 16-bit offset or reg/mem
  1206. \ Intersegment Jump, Call -- via FAR [] structure
  1207.  
  1208. : 5MIF          ( A1 --- )
  1209.                 ?D>S TS@
  1210.           CASE
  1211.                 DIRECT  OF  <ND> @
  1212.                             IF   $FF C, C@ <FR> @
  1213.                                  IF  8 +  THEN  M/RS,
  1214.                             ELSE <FR> @
  1215.                                  IF  2+ C@ C, , ,
  1216.                                  ELSE  OVER HERE 3 + - $80 + $100 U<
  1217.                                          OVER C@ $20 = AND
  1218.                                          <WD> @ 0= AND
  1219.                                          IF  DROP $EB C, OFFSET8,
  1220.                                          ELSE 1+ C@ C, OFFSET16,
  1221.                                          THEN
  1222.                                  THEN
  1223.                             THEN
  1224.                        ENDOF
  1225.                REG16   OF   $FF C, CXS,
  1226.                        ENDOF
  1227.                INDEXED OF   DSET $FF C, C@ <FR> @
  1228.                             IF  8 + THEN
  1229.                             +RS DISP,
  1230.                        ENDOF
  1231.                ERROR3
  1232.           ENDCASE
  1233.           RESET ;
  1234.  
  1235. : 5MI     CREATE C, C, C, DOES> ['] 5MIF A;! A; ;
  1236.  
  1237.  
  1238. \ IN and OUT
  1239.  
  1240. : 6MIF          ( A1 --- )
  1241.                 DUP C@ 2 AND            \ IN or OUT?
  1242.                    IF   <WS> @             \ This is an OUT
  1243.                         rd@ td@            \ to check for DX
  1244.                         Asreg? not Error6  \ source not AL or AX
  1245.                         ADREG? ?ORDERERROR
  1246.                    ELSE <WD> @             \ This is an IN
  1247.                         rs@ ts@            \ to check for DX
  1248.                         Adreg? not Error6  \ dest   not AL or AX
  1249.                         ASREG? ?ORDERERROR
  1250.                    THEN
  1251.                 <ID> @     \ WAS THERE IMMEDIATE DATA ?
  1252.                    IF
  1253.                      2DROP              \ DX check info
  1254.                      SWAP
  1255.                      C@ + ( +W ) C,             \ yes, use it as port#
  1256.                      dup $FF U> Error4 C,       \ make sure data is OK
  1257.                    ELSE
  1258.                      REG16 = swap 2 = AND not Error6  \ make sure reg is DX
  1259.                      SWAP
  1260.                      1+ C@ + ( +W ) C,          \ no, DX contains port#
  1261.                    THEN
  1262.                 RESET ;
  1263.  
  1264.  
  1265. : 6MI     CREATE C, C, DOES> ['] 6MIF A;! A; ;
  1266.  
  1267.  
  1268.  
  1269. \ Basic Arithmetic:  ADC, ADD, SBB, SUB  (1)
  1270. \ Basic Logical:     AND, OR,  XOR       (2)
  1271. \ Basic Compare:     CMP                 (1)
  1272. \ Basic Test:        TEST                (2)
  1273. \
  1274. \ NOTE:  These instructions assume the immediate data is placed on the
  1275. \        top-of-stack.  When 7MIF is entered, any immediate data is
  1276. \        "just behind" A1.  This is true for both Prefix and Postfix modes.
  1277.  
  1278. : 7MIF2                                 \ Register/Memory Operand
  1279.                 C@ TS@ REG? IF                  \ NOT Immediate Data
  1280.                    +W C, RS@ 8* M/RD,           \ Op2 is register
  1281.                 ELSE
  1282.                    $84                          \ Op2 is memory
  1283.                    OVER - IF
  1284.                         2 OR
  1285.                    THEN
  1286.                    +W C,
  1287.                    TD@ REG? IF
  1288.                         RD@ 8* M/RS,
  1289.                    ELSE
  1290.                         ERROR3
  1291.                    THEN
  1292.                 THEN ;
  1293.  
  1294. : 7MIF3                                 \ Immed data Short Form with A-reg
  1295.                 2+ C@ +W C, TD@ REG8 =           \ Yes, use short form
  1296.                    IF
  1297.                         <I1> @ C,                \ One byte
  1298.                    ELSE
  1299.                         <I1> @ ,                 \ two bytes
  1300.                         ED@ 3 = IF <I2> @ , THEN \ four bytes
  1301.                    THEN ;
  1302.  
  1303. : 7MIF4                                 \ Immed data long form with reg/mem
  1304.  
  1305.                     dup 3 + C@ CASE
  1306.                         1 OF                            \ ADC, ADD, SBB, SUB
  1307.                                 DUP 1+ C@ +W            \ basic opcode
  1308.                                 <W> @ IF
  1309.                                      ED@ 3 = IF         \ 32 bits Immed data
  1310.                                         C,              \ basic opcode
  1311.                                         C@ M/RD,        \ Instr type & ModRM
  1312.                                         <I1> @ ,        \ 16 bits of immediate data
  1313.                                         <I2> @ ,        \ 16 more for 32 total
  1314.                                      ELSE
  1315.                                         <I1> @ $80 +    \ look for special case
  1316.                                         $100 U< IF
  1317.                                            2 OR C,      \ special case opcode
  1318.                                            C@ M/RD,     \ instr + ModRM
  1319.                                            <I1> @ C,    \ ** 1 byte data
  1320.                                         ELSE
  1321.                                            C,           \ opcode
  1322.                                            C@ M/RD,     \ instr + ModRM
  1323.                                            <I1> @ ,     \ 2 bytes data
  1324.                                         THEN
  1325.                                      THEN
  1326.                                 ELSE
  1327.                                      C,                 \ basic opcode
  1328.                                      C@ M/RD,           \ Instr type & ModRM
  1329.                                      <I1> @ C,          \  8 bits of immediate data
  1330.                                 THEN
  1331.                           ENDOF
  1332.                         2 OF                            \ AND, OR, XOR, CMP, TEST
  1333.                                 DUP 1+ C@ +W            \ basic opcode
  1334.                                 <W> @ IF
  1335.                                      C,                 \ basic opcode
  1336.                                      C@ M/RD,           \ Instr type & ModRM
  1337.                                      <I1> @ ,           \ 16 bits of immediate data
  1338.                                      ED@ 3 = IF         \ total 32 bits
  1339.                                           <I2> @ ,
  1340.                                      THEN
  1341.                                 ELSE
  1342.                                      C,                 \ basic opcode
  1343.                                      C@ M/RD,           \ Instr type & ModRM
  1344.                                      <I1> @ C,          \  8 bits of immediate data
  1345.                                 THEN
  1346.                           ENDOF
  1347.                     ENDCASE ;
  1348.  
  1349. : 7MIF    ( A1 --- )
  1350.           ES@ ED@   OR ESprefix                 \ E-mode if either source or dest
  1351.  
  1352.           TS@ IMMED = IF
  1353.                swap <I1> !                      \ save the immediate data values
  1354.                ED@ 3 = IF swap <I2> ! THEN      \ (including any 32 bit data)
  1355.                ADREG? IF                        \ Operand is Immediate data
  1356.                       7MIF3                     \ Is EAX, AX or AL used?
  1357.                ELSE   7MIF4                     \ Not AX or AL, use long form
  1358.                THEN
  1359.           ELSE                                  \ No Immed data
  1360.                7MIF2
  1361.           THEN
  1362.  
  1363.           RESET ;
  1364.  
  1365. : 7MI     CREATE C, C, C, C, DOES> ['] 7MIF A;! A; ;
  1366.  
  1367.  
  1368. \ DIV, IDIV, IMUL, MUL, NOT, NEG
  1369. \               Only Register/Memory Format is supported
  1370. \               with instr-code part of ModR/M byte
  1371.  
  1372. : 8MIF          ( A1 --- )
  1373.                 ?D>S
  1374.                 ES@ ESprefix                            \ 386 extended regs
  1375.                 DUP 1+ C@ +W C,                         \ opcode
  1376.                 C@ M/RS,                                \ ModR/M with instr-code
  1377.                 RESET ;
  1378.  
  1379. : 8MI     CREATE C, C, DOES> ['] 8MIF A;! A; ;
  1380.  
  1381.  
  1382. \ Shift Rotate Instructions:  ROL, ROR, RCL, RCR, SHL/SAL, SHR, SAR -- 16 & 32 bit
  1383. \
  1384. \               The "source" operand should be CL or an immediate number
  1385. \               (1 if 8086 or any number up to 31 if 386).
  1386.  
  1387.  
  1388. : 9MIF2
  1389.                 TS@ 2 = RS@ 1 = AND IF          \ Test if source is the CL reg
  1390.                      2+ C,                      \ set opcode
  1391.                      C@                         \ determines which instr. - ROL, RCL, etc.
  1392.                      M/RD,                      \ set the ModR/M byte (with instr. code)
  1393.                      exit
  1394.                 THEN
  1395.  
  1396.                 <id> @ 0= IF                    \ Old form -- for compatability
  1397.                      ASM.warn @ IF
  1398.                          cr ." Warning: Possible Immediate Error"
  1399.                          WarnMsg
  1400.                      THEN
  1401.                      C, NIP                     \ old form, for compatability
  1402.                      C@                         \ determines which instr. - ROL, RCL, etc.
  1403.                      M/RD,                      \ set the ModR/M byte (with instr. code)
  1404.                      exit
  1405.                 THEN
  1406.  
  1407.                 <id> @ 0<> IF                   \ immediate number specified
  1408.                    rot                          \ get the value of immediate
  1409.                    dup 1 = IF                   \ check for special case of 1
  1410.                         drop                    \ trash the number 1
  1411.                         C,                      \ set opcode
  1412.                         C@                      \ determines which instr. - ROL, RCL, etc.
  1413.                         M/RD,                   \ set the ModR/M byte (with instr. code)
  1414.                    ELSE
  1415.                         Chk.386                 \ only valid for 386
  1416.                         <i1> !                  \ save for later
  1417.                         $C1 AND C,              \ set opcode
  1418.                         C@ M/RD,                \ set ModR/M and instr. code
  1419.                         <i1> @ C,               \ and finally the immediate byte
  1420.                    THEN
  1421.                    exit
  1422.                 THEN
  1423.  
  1424.                 ERROR3  ;                       \ should not occur
  1425.  
  1426. : 9MIF          ( A1 --- )
  1427.  
  1428.                 <DST> @ 0=
  1429.                 TS@ REG?
  1430.                 TS@ INDEXED =  OR  AND  IF
  1431.                       1 <DST> !  ?D><S
  1432.                       1 <TS>  !  1 <SST> !
  1433.                       1 swap
  1434.                       <W> @ <WD> !
  1435.                 ELSE
  1436.                       POSTVAR @ IF              \ If postfix, reverse
  1437.                               ?D><S             \ the operands
  1438.                               <WS> @ <WD> !     \ Correct word mode
  1439.                       THEN
  1440.                 THEN
  1441.  
  1442.                 ED@ ESprefix                    \ 32-bit reg prefix
  1443.                 $D0 <WD> @ +                    \ get the basic opcode and merger in the word/byte bit
  1444.                 9MIF2
  1445.                 RESET ;
  1446.  
  1447. : 9MI           CREATE C, DOES> ['] 9MIF A;! A; ;
  1448.  
  1449.  
  1450. \ Two Byte Instructions with NO operands -- AAD, AAM
  1451.  
  1452. : 10MIF         ( A1 --- )
  1453.                 DUP 1+ C@ C, C@ C,
  1454.                 RESET ;
  1455.  
  1456. : 10MI          CREATE C, C, DOES> ['] 10MIF A;! A; ;
  1457.  
  1458.  
  1459. \ DEC, INC
  1460.  
  1461. : 11MIF         ( A1 --- )
  1462.                 ?D>S                                    \ make source & dest the same
  1463.                 TS@ REG? <W> @ 0<> AND                  \ Determine if Word or Byte
  1464.                    IF   C@ +RS C,                       \ Word-Register, use short form
  1465.                    ELSE                                 \ use regular form
  1466.                         ES@ ED@ or ESprefix             \ 386 Extended mode Prefix
  1467.                         $FE +W C,                       \ $FE for byte, $FF for word
  1468.                         1+ C@                           \ next byte for modifier
  1469.                         M/RS,                           \ then generate ModRM
  1470.                    THEN
  1471.                 RESET ;
  1472.  
  1473. : 11MI          CREATE C, C, DOES> ['] 11MIF A;! A; ;
  1474.  
  1475.  
  1476. \ XCHG - this has only two forms: reg with accumulator
  1477. \                                 reg with reg/memory
  1478.  
  1479. : 13MIF         ( A1 --- )
  1480.                 ES@ ED@ or ESprefix             \ On 386 only, 32 bit operations
  1481.                 DROP TS@ REG? TD@ REG? AND      \ Both are registers
  1482.                      RS@ 0= RD@ 0= OR AND       \ Either register is AX
  1483.                      <W> @ 1 = AND              \ And it is AX not AL.
  1484.                 IF                              \ Reg with assumulator
  1485.                      RS@ 0=
  1486.                         IF      RD@
  1487.                         ELSE    RS@
  1488.                         THEN
  1489.                      $90 + C,                  \ Short opcode
  1490.                 ELSE                            \ reg/Mem with register
  1491.                      $86 +W
  1492.                      TS@ REG? 0=
  1493.                         IF TD@ REG? 0=
  1494.                              IF   ERROR3
  1495.                              ELSE C,
  1496.                                   RD@ 8* M/RS,
  1497.                              THEN
  1498.                         ELSE
  1499.                              C, RS@ 8* M/RD,
  1500.                         THEN
  1501.                 THEN
  1502.                 RESET ;
  1503.  
  1504. : 13MI    CREATE DOES> ['] 13MIF A;! A; ;
  1505.  
  1506.  
  1507. \ 8086 Segment Control - LEA, LDS, LES
  1508.  
  1509. : 14MIF         ( A1 --- )
  1510.                 C@ C,
  1511.                 TD@ REG?
  1512.                    IF   RD@ 8* M/RS,
  1513.                    ELSE ERROR3
  1514.                    THEN
  1515.                 RESET ;
  1516.  
  1517. : 14MI    CREATE C, DOES> ['] 14MIF A;! A; ;
  1518.  
  1519.  
  1520. \ INT -- Int 3 is handled as a special case
  1521. \     -- the numeric value of the interrupt is taken off the stack
  1522.  
  1523. : 15MIF         ( A1 --- )
  1524.                 DROP                    \ no parms passed
  1525.                 dup $FF U> Error4       \ Validate Interrupt Number
  1526.                 DUP 3 =                 \ check for Int 3
  1527.                    IF   DROP $CC C,     \ Special one-byte code for Int 3
  1528.                    ELSE $CD C, C,       \ normal 2-byte code
  1529.                    THEN
  1530.                 RESET ;
  1531.  
  1532. : 15MI    CREATE DOES> ['] 15MIF A;! A; ;
  1533.  
  1534.  
  1535. \ Segment override - do it now for PostFix or PreFix -- this is different so
  1536. \                    that it allows the segment override (e.g., ES:) to
  1537. \                    be placed anywhere in the instruction.  For example,
  1538. \                       ES:  ADD  AX, [BX]
  1539. \                    and
  1540. \                            ADD  ES:  AX, [BX}
  1541. \                    are equivalent.
  1542.  
  1543. : 30MI    CREATE C, DOES> C@ C, ;               \ 8086  version
  1544.  
  1545. : 31MI    CREATE C, DOES> chk.386 C@ C, ;       \ 80386 version
  1546.  
  1547. \ 386 Single Byte Instruction -- NO operands
  1548.  
  1549. : 32MIF         Chk.386
  1550.                 C@ C, RESET ;
  1551.  
  1552. : 32MI    CREATE C, DOES> ['] 32MIF A;! A; ;
  1553.  
  1554.  
  1555. \ 386 Two Byte Instructions with NO operands
  1556.  
  1557. : 33MIF         Chk.386
  1558.                 DUP 1+ C@ C, C@ C, RESET ;
  1559.  
  1560. : 33MI          CREATE C, C, DOES> ['] 33MIF A;! A; ;
  1561.  
  1562.  
  1563. \ 386 Segment Control - LFS, LGS, LSS
  1564.  
  1565. : 34MIF         Chk.386
  1566.                 DUP 1+ C@ C, C@ C,
  1567.                 TD@ REG?
  1568.                    IF   RD@ 8* M/RS,
  1569.                    ELSE ERROR3
  1570.                    THEN
  1571.                 RESET ;
  1572.  
  1573. : 34MI    CREATE C, C, DOES> ['] 34MIF A;! A; ;
  1574.  
  1575.  
  1576. \ PUSH
  1577.  
  1578. : 35MIF
  1579.                 ?D>S TS@
  1580.           CASE
  1581.                 SEGREG  OF                              \ SEGMENT Reg
  1582.                            ES@ 9 = IF   DROP            \ Test if 386 reg
  1583.                                         Chk.386
  1584.                                         $0F C,          \ First byte
  1585.                                         $80 RS@ 8*
  1586.                                         + C,
  1587.                                    ELSE                 \ 8086/386 Reg
  1588.                                         C@ RS@ 8* + C,
  1589.                                    THEN
  1590.                         ENDOF
  1591.                 REG16   OF                              \ 16 bit REGISTER
  1592.                            ES@ ESprefix                 \ for 32 bit regs
  1593.                            1+ C@ +RS C,
  1594.                         ENDOF
  1595.                 REG8    OF ERROR3                       \ 8 BIT ILLEGAL
  1596.                         ENDOF
  1597.                 IMMED   OF Chk.386                      \ Immediate Data OK for 386
  1598.                            drop                         \ ignore passed parms
  1599.                            dup $ff >
  1600.                                IF   $68 C, ,            \ 2-bytes immediate data
  1601.                                ELSE $6A C, C,           \ 1-byte
  1602.                                THEN
  1603.                         ENDOF
  1604.                      DROP 2+ C@ DUP C,                  \ Memory
  1605.                      $30 AND M/RS,
  1606.           ENDCASE
  1607.           RESET ;
  1608.  
  1609. : 35MI    CREATE C, C, C, DOES> ['] 35MIF A;! A; ;
  1610.  
  1611.  
  1612. \ POP
  1613.  
  1614. : 36MIF
  1615.                 ?D>S TS@
  1616.           CASE
  1617.                 SEGREG  OF                              \ SEGMENT Reg
  1618.                            ES@ 9 = IF   DROP            \ Test if 386 reg
  1619.                                         Chk.386
  1620.                                         $0F C,          \ First byte
  1621.                                         $81 RS@ 8*
  1622.                                         + C,
  1623.                                    ELSE                 \ 8086/386 Reg
  1624.                                         RS@ 1 = Error5  \ CS is invalid
  1625.                                         C@ RS@ 8* + C,
  1626.                                    THEN
  1627.                         ENDOF
  1628.                 REG16   OF                              \ 16 bit REGISTER
  1629.                         ES@ ESprefix                    \ for 32 bit reg
  1630.                         1+ C@ +RS C,
  1631.                         ENDOF
  1632.                 REG8    OF ERROR3                       \ 8 BIT ILLEGAL
  1633.                         ENDOF
  1634.                 IMMED   OF Error3                       \ Immediate Data Bad for POP
  1635.                         ENDOF
  1636.                      DROP 2+ C@ DUP C,                  \ Memory
  1637.                      $30 AND M/RS,
  1638.           ENDCASE
  1639.           RESET ;
  1640.  
  1641. : 36MI    CREATE C, C, C, DOES> ['] 36MIF A;! A; ;
  1642.  
  1643.  
  1644. \ The SETcc instructions
  1645.  
  1646. : 37MIF         Chk.386                                 \ 386 only
  1647.                 ?D>S                                    \ make source & dest the same
  1648.                 TS@ REG16 <> <W> @ 0=  AND              \ 8-bit reg or memory operands only
  1649.                    IF
  1650.                         $0f C, C@ C,                    \ opcode
  1651.                         0 M/RS,                         \ then generate ModRM
  1652.                    ELSE
  1653.                         Error3
  1654.                    THEN
  1655.                 RESET ;
  1656.  
  1657. : 37MI          CREATE C, DOES> ['] 37MIF A;! A; ;
  1658.  
  1659. \ 386 Two Opcode plus ModRegR/M Byte
  1660.  
  1661. : 38MIF         Chk.386 ED@ ESprefix
  1662.                 dup 1+ C@ C, C@ C,                      \ Opcode
  1663.                 td@ reg16 =                             \ D must be reg16
  1664.                    IF   rd@ 8* M/RS,
  1665.                    ELSE Error5
  1666.                    THEN
  1667.                 RESET ;
  1668.  
  1669. : 38MI          CREATE C, C, DOES> ['] 38MIF A;! A; ;
  1670.  
  1671.  
  1672. \ Special case single byte instruction for 386 INS and OUTS
  1673.  
  1674. : 39MIF         Chk.386
  1675.                 ES@  ESprefix                   \ 386 EAX
  1676.                 C@ +W C,
  1677.                 RESET ;
  1678.  
  1679. : 39MI     CREATE C, DOES> ['] 39MIF A;! A; ;
  1680.  
  1681.  
  1682.  
  1683. \ MOV -- reg/reg, reg/mem, or reg/immediate
  1684.  
  1685. : 40MIF2                                \ Actually generate code
  1686.  
  1687.             TD@ SEGREG =                        \ Dest  is Seg Reg
  1688.                 IF
  1689.                      RD@ 1 = Error5             \ CS is not valid
  1690.                      ED@ 0<> IF Chk.386         \ Make sure 386 is valid
  1691.                              THEN
  1692.                      $8E C,  RD@ 8* M/RS,
  1693.                      EXIT
  1694.                 THEN
  1695.  
  1696.             TS@ SEGREG =                        \ Source is Seg Reg
  1697.                 IF
  1698.                      ED@ 0<> IF Chk.386         \ Make sure 386 is valid
  1699.                              THEN
  1700.                      $8C C,  RS@ 8* M/RD,
  1701.                      EXIT
  1702.                 THEN
  1703.  
  1704.             TS@ IMMED =                         \ Dest Reg AND Immed
  1705.             TD@ REG?
  1706.             AND
  1707.                 IF
  1708.                      ED@ ESprefix
  1709.                      $16 +W 8* +RD C, 8/16,
  1710.                      ED@ 3 = IF , THEN          \ 32 bits
  1711.                      EXIT
  1712.                 THEN
  1713.  
  1714.             TS@ 0= TD@ 0= OR                    \ Short form -
  1715.             ADREG? ASREG? OR                    \ Memory to/from Accumulator
  1716.             AND
  1717.                 IF
  1718.                      ES@ ED@ or ESprefix        \ 386 32 bit Ac
  1719.                      $A0 +W TS@ IF 2+ THEN      \ Opcode
  1720.                      C,                         \ set opcode
  1721.                      ,                          \ and address
  1722.                      EXIT
  1723.                 THEN
  1724.  
  1725.             TS@ IMMED =                         \ Immed to reg/mem
  1726.                 IF      postvar @               \ *****  09/26/88 18:33:25.98  *******  ZIMMER ***********
  1727.                         TD@ INDEXED <>
  1728.                         AND IF
  1729.                                 swap <I1> !     \ save first 16 bits immed
  1730.                                 swap
  1731.                         ELSE
  1732.                                 <I1> !          \ save first 16 bits immed
  1733.                         THEN
  1734.                         ED@ 3 = IF <I2> ! THEN  \ save second 16 bits immed (32 total)
  1735.                         ED@ ESprefix
  1736.                         $C6 +W C,               \ Opcode
  1737.                         0 M/RD,                 \ Reg/Mem dest
  1738.                         <I1> @ 8/16,            \ Set immediate data
  1739.                         ED@ 3 = IF <I2> @ , THEN  \ if extended, store 16 more bits
  1740.                      EXIT
  1741.                 THEN
  1742.  
  1743.             $88 +W                              \ Opcode for reg/mem
  1744.             TD@ REG?
  1745.                 IF
  1746.                      ED@ ESprefix
  1747.                      2+ C,                      \ memory to register
  1748.                      RD@ 8* M/RS,
  1749.                      EXIT
  1750.                 THEN
  1751.  
  1752.             TS@ REG?
  1753.                 IF
  1754.                      ES@ ESprefix
  1755.                      C,                         \ register to memory
  1756.                      RS@ 8* M/RD,
  1757.                      EXIT
  1758.                 THEN
  1759.  
  1760.             ERROR3 ;                      \ Error if we get this far
  1761.  
  1762.  
  1763. : 40MIF                                 \ nest to use "EXIT" above
  1764.                 DROP                    \ opcodes are inline
  1765.                 40MIF2                  \ do-it
  1766.                 RESET ;
  1767.  
  1768.  
  1769. : 40MI    CREATE DOES> ['] 40MIF A;! A; ;
  1770.  
  1771.  
  1772. \ 386 Double Shift Instructions:  SHLD and SHRD
  1773.  
  1774.  
  1775. : 41MIF         Chk.386                 \ 386 only instruction
  1776.                 ED@ ESprefix            \ 32 bit operand regs
  1777.  
  1778.                 TD@ REG8 = IF           \ assume the source reg is right, # trashes <TS>
  1779.                         Error5
  1780.                 THEN
  1781.                 $0F C,                  \ 2-byte opcode
  1782.                 C@                      \ 2nd byte of op-code
  1783.  
  1784.                 <ID> @ IF               \ immediate 8-bit number
  1785.                         C,              \ set opcode
  1786.                         <i1> !          \ save immediate number
  1787.                         RS@ 8* M/RD,    \ process ModRegR/M
  1788.                         <i1> @ C,       \ finally, set the immediate number
  1789.                 ELSE                    \ uses CL reg (assumed if no immediate data)
  1790.                         1+ C,           \ set opcode
  1791.                         RS@ 8* M/RD,    \ process ModRegR/M
  1792.                 THEN
  1793.                 RESET ;
  1794.  
  1795. : 41MI    CREATE C, DOES> ['] 41MIF A;! A; ;
  1796.  
  1797.  
  1798. \ 386 Extended moves - move with extension - MOVSX and MOVZX
  1799. \
  1800. \ Supported Forms:
  1801. \               MOVSX   AX, BL
  1802. \               MOVSX   AX, BX
  1803. \               MOVSX  EAX, BL
  1804. \               MOVSX  EAX, BX
  1805. \               MOVSX   AX, ZZZ         \ word
  1806. \               MOVSX   AX, ZZZ  BYTE   \ byte
  1807. \               MOVSX  EAX, ZZZ         \ word
  1808. \               MOVSX  EAX, ZZZ  BYTE   \ byte
  1809.  
  1810. : 42MIF         Chk.386                 \ 386 only instruction
  1811.                 <W> @ swap              \ get width and save
  1812.                 <ed2> @ ESprefix        \ 32 bit operand regs
  1813.  
  1814.                 TD@ REG8 = IF           \ assume the source reg is right, # trashes <TS>
  1815.                         Error5
  1816.                 THEN
  1817.  
  1818.                 $0f C,                  \ set two-byte opcode
  1819.                 C@ + C,
  1820.                 RD@ 8* M/RS,            \ set ModRegR/M byte
  1821.                 RESET ;
  1822.  
  1823. : 42MI    CREATE C, DOES> ['] 42MIF A;! A; ;
  1824.  
  1825.  
  1826. \ 386 Bit Test Instructions
  1827.  
  1828. : 43MIF         Chk.386 ED@ ESprefix
  1829.  
  1830.                 $0f C,                                  \ 2-byte Opcode
  1831.                 <ID> @ 0<> IF
  1832.                         swap <i1> !
  1833.                         dup 1+ C@ C,
  1834.                         C@  M/RD,
  1835.                         <i1> @ C,                       \ 8 bits of immediate data
  1836.                 ELSE
  1837.                         C@ C,
  1838.                         RS@ 8* M/RD,
  1839.                 THEN
  1840.  
  1841.                 RESET ;
  1842.  
  1843. : 43MI          CREATE C, C, DOES> ['] 43MIF A;! A; ;
  1844.  
  1845.  
  1846. \ ===========================================================================
  1847. \          Numerical Processor Support
  1848. \ ===========================================================================
  1849.  
  1850. : COMP-WAIT                             \ The 8087 needs a WAIT inserted for synchronization
  1851.                                         \ and the 287/387 does not.
  1852.                 ASM.cpu @ if
  1853.                         exit
  1854.                 then
  1855.                 WAIT? @ IF
  1856.                      $9B C, ( WAIT )
  1857.                 THEN
  1858.                 WAIT? ON ;
  1859.  
  1860. : ESC,  ( n -- )
  1861.         $D8 OR C, ;
  1862.  
  1863. \ ===========================================================================
  1864.  
  1865. : 1FPF
  1866.         COMP-WAIT
  1867.         DUP 1+ C@ ESC,
  1868.         C@ C,
  1869.         RESET ;
  1870.  
  1871. : 1FP   CREATE C, C,
  1872.         DOES> ['] 1FPF A;!  A; ;
  1873.  
  1874. : 2FPF
  1875.         COMP-WAIT
  1876.         DUP 1+ C@ ESC,
  1877.         C@ M/RS,
  1878.         RESET ;
  1879.  
  1880. : 2FP
  1881.         CREATE C, C,
  1882.         DOES>  ['] 2FPF A;! A; ;
  1883.  
  1884. \ Fld, Fst, Fstp
  1885.  
  1886. : 3FPF
  1887.         COMP-WAIT
  1888.         TS@ 6 = IF                      \ stack-reg specified
  1889.                 DUP 1+ C@ ESC,
  1890.                 C@ RS@ OR C,
  1891.         ELSE                            \ memory specified (need to check mem type)
  1892.                 <FW> @  7 AND ESC,
  1893.                 <FW> @ $f8 AND 0= if    \ regular real*4, real*8, int*2, int*4
  1894.                         2+ C@ M/RS,
  1895.                 else
  1896.                    3 + C@
  1897.                    dup 0= if Error3 then
  1898.                    <FW> @ $F8 AND
  1899.                    OR M/RS,
  1900.                 then
  1901.         THEN
  1902.         RESET ;
  1903.  
  1904. : 3FP
  1905.         CREATE C, C, C, C,
  1906.         DOES>  ['] 3FPF A;! A;  ;
  1907.  
  1908. : 4FPF
  1909.         COMP-WAIT
  1910.         DUP 1+ C@ ESC,
  1911.         C@ RS@ OR C,
  1912.         RESET ;
  1913.  
  1914. : 4FP
  1915.         CREATE C, C,
  1916.         DOES>  ['] 4FPF A;! A;  ;
  1917.  
  1918.  
  1919. : 5FPF
  1920.         COMP-WAIT
  1921.         6 ESC,
  1922.         C@ RD@ OR C,
  1923.         RESET ;
  1924.  
  1925. : 5FP
  1926.         CREATE C,
  1927.         DOES>  ['] 5FPF A;! A; ;
  1928.  
  1929. \ Fcom, Fcomp (similar to 7FP)
  1930.  
  1931. : 6FPF
  1932.         COMP-WAIT
  1933.         TS@ 6 = IF                      \ stack-regs (only ST(i) is valid)
  1934.                 0 ESC,
  1935.                 C@ RS@ OR C,
  1936.         ELSE                            \ for memory (Real*4, Real*8, Int*4, Int*2)
  1937.                 <FW> @  6 AND ESC,
  1938.                 1+ C@ M/RS,
  1939.         THEN
  1940.         RESET ;
  1941.  
  1942. : 6FP
  1943.         CREATE C, C,
  1944.         DOES>  ['] 6FPF A;! A; ;
  1945.  
  1946. \ Fadd, Fmul, Fsub, Fsubr, Fdiv, Fdivr
  1947.  
  1948. : 7FPF
  1949.         COMP-WAIT
  1950.         TS@ 6 = IF                      \ for stack-regs
  1951.                 RD@ 0= IF
  1952.                       0 ESC,
  1953.                       C@ RS@ OR C,
  1954.                 ELSE
  1955.                       4 ESC,
  1956.                       C@ RD@ OR C,
  1957.                 THEN
  1958.         ELSE                            \ for memory (Real*4, Real*8, Int*4, Int*2)
  1959.                 <FW> @  6 AND ESC,
  1960.                 1+ C@ M/RS,
  1961.         THEN
  1962.         RESET ;
  1963.  
  1964. : 7FP
  1965.         CREATE C, C,
  1966.         DOES>  ['] 7FPF A;! A; ;
  1967.  
  1968. : 8FPF
  1969.         Chk.386
  1970.         DUP 1+ C@ ESC,
  1971.         C@ C,
  1972.         RESET ;
  1973.  
  1974. : 8FP   CREATE C, C,
  1975.         DOES> ['] 8FPF A;!  A; ;
  1976.  
  1977. : 9FPF
  1978.         Chk.386
  1979.         DUP 1+ C@ ESC,
  1980.         C@ RS@ OR C,
  1981.         RESET ;
  1982.  
  1983. : 9FP
  1984.         CREATE C, C,
  1985.         DOES>  ['] 9FPF A;! A;  ;
  1986.  
  1987.  
  1988.  
  1989. headers                 \ ***************************************************
  1990.  
  1991. \ ===========================================================================
  1992. \          Now let's create the actual instructions.
  1993. \ ===========================================================================
  1994.  
  1995.  
  1996.                                         \ Segment (prefix) Overrides
  1997.         $26         30MI   ES:
  1998.         $2E         30MI   CS:
  1999.         $36         30MI   SS:
  2000.         $3E         30MI   DS:
  2001.         $64         31MI   FS:
  2002.         $65         31MI   GS:
  2003.  
  2004.  
  2005.         $37          1MI   AAA          \ ASCII Adjust after Addition
  2006.         $D5 $0A     10MI   AAD          \ ASCII Adjust after Division
  2007.         $D4 $0A     10MI   AAM          \ ASCII Adjust after Multiplication
  2008.         $3F          1MI   AAS          \ ASCII Adjust after Subtraction
  2009.     $01 $14 $80 $10  7MI   ADC          \ Add with Carry
  2010.     $01 $04 $80 $00  7MI   ADD          \ Integer Addition
  2011.     $02 $24 $80 $20  7MI   AND          \ (logical) and
  2012.  
  2013.         $0F $BC     38MI   BSF          \ 386 Scan Bit Forward
  2014.         $0F $BD     38MI   BSR          \ 386 Scan Bit Reverse
  2015.         $BA $A3     43MI   BT           \ 386 Bit Test
  2016.         $BA $BB     43MI   BTC          \ 386 Bit Test and Complement
  2017.         $BA $B3     43MI   BTR          \ 386 Bit Test and Reset
  2018.         $BA $AB     43MI   BTS          \ 386 Bit Test and Set
  2019.  
  2020.         $9A $E8 $10  5MI   CALL         \ Call Procedure
  2021.         $98          1MI   CBW          \ Convert Byte to Word
  2022.         $F8          1MI   CLC          \ Clear Carry Flag
  2023.         $FC          1MI   CLD          \ Clear Direction Flag (increasing)
  2024.         $FA          1MI   CLI          \ Clear Interrupt Flag (Disable)
  2025.         $0F $06     33MI   CLTS         \ 386 Clear Task Switched Flag
  2026.         $F5          1MI   CMC          \ Complement Carry Flag
  2027.     $01 $3C $80 $38  7MI   CMP          \ Compare
  2028.         $A6          3MI   CMPS         \ Compare         String
  2029.         $A6          1MI   CMPSB        \ Compare (byte)  String
  2030.         $66 $A7     33MI   CMPSD        \ Compare (Dword) String
  2031.         $A7          1MI   CMPSW        \ Compare (word)  String
  2032.         $99          1MI   CWD          \ Convert Word to Dword
  2033.  
  2034.         $27          1MI   DAA          \ Decimal Adjust after Addition
  2035.         $2F          1MI   DAS          \ Decimal Adjust after Subtraction
  2036.         $08 $48     11MI   DEC          \ Decrement
  2037.         $F6 $30      8MI   DIV          \ Unsigned divide
  2038.  
  2039.               1 $F0  1FP   F2XM1        \ x87 (2**x)-1
  2040.               1 $E1  1FP   FABS         \ x87 absolute value
  2041.               1 $E1  1FP   FABS,        \ x87 - for compatability
  2042.             $00 $C0  7FP   FADD         \ x87 Add (real/integer)
  2043.                 $C0  5FP   FADDP        \ x87 Add Real and Pop
  2044.               1 $E0  1FP   FCHS         \ x87 Change Sign
  2045.               3 $E2  1FP   FCLEX        \ x87 Clear Exceptions
  2046.             $10 $D0  6FP   FCOM         \ x87 Compare (real/integer)
  2047.             $18 $D8  6FP   FCOMP        \ x87 Compare (real/integer and pop
  2048.               6 $D9  1FP   FCOMPP       \ x87 Compare Real and Pop twice
  2049.               1 $FF  8FP   FCOS         \ 387 Cosine of ST(0)
  2050.               1 $F6  1FP   FDECSTP      \ x87 Decrement stack pointer
  2051.               3 $E1  1FP   FDISI        \ 8087 DISABLE interrupts
  2052.             $30 $F0  7FP   FDIV         \ x87 Divide (real/integer)
  2053.                 $F0  5FP   FDIVP        \ x87 Divide Real and Pop
  2054.             $38 $F8  7FP   FDIVR        \ x87 Divide (real/integer) REVERSE
  2055.                 $F8  5FP   FDIVRP       \ x87 Divide Real Reverse and Pop
  2056.               3 $E0  1FP   FENI         \ 8087 ENABLE interrupts
  2057.               5 $C0  4FP   FFREE        \ x87 Free Register
  2058.               1 $F7  1FP   FINCSTP      \ x87 Increment Stack pointer
  2059.               3 $E3  1FP   FINIT        \ x87 Initialize Processor
  2060.    $20  $00   1 $C0  3FP   FLD          \ x87 Load (real/integer/bcd/temp_real)
  2061.               1 $E8  1FP   FLD1         \ x87 Load +1.0
  2062.               1 $28  2FP   FLDCW        \ x87 Load control word
  2063.               1 $20  2FP   FLDENV       \ x87 Load environment
  2064.               1 $EA  1FP   FLDL2E       \ x87 Load LOG2(e)
  2065.               1 $E9  1FP   FLDL2T       \ x87 Load LOG2(10)
  2066.               1 $EC  1FP   FLDLG2       \ x87 Load LOG10(2)
  2067.               1 $ED  1FP   FLDLN2       \ x87 Load LOGe(2)
  2068.               1 $EB  1FP   FLDPI        \ x87 Load pi
  2069.               1 $EE  1FP   FLDZ         \ x87 Load +0.0
  2070.             $08 $C8  7FP   FMUL         \ x87 Multiply (real/integer)
  2071.                 $C8  5FP   FMULP        \ x87 Multiply Real and Pop
  2072.               1 $D0  1FP   FNOP         \ x87 no-operation
  2073.               1 $F3  1FP   FPATAN       \ x87 Partial Arctangent
  2074.               1 $F8  1FP   FPREM        \ x87 Partial Remainder
  2075.               1 $F5  8FP   FPREM1       \ 387 Partial Remainder
  2076.               1 $F2  1FP   FPTAN        \ x87 Partial Tangent
  2077.               1 $FC  1FP   FRNDINT      \ x87 Round to Integer
  2078.               5 $20  2FP   FRSTOR       \ x87 Restore saved state
  2079.               5 $30  2FP   FSAVE        \ x87 Save state
  2080.               1 $FD  1FP   FSCALE       \ x87 Scale
  2081.               1 $FE  8FP   FSIN         \ 387 Sine of ST(0)
  2082.               1 $FB  8FP   FSINCOS      \ 387 Sine and Cosine of ST(0)
  2083.               1 $FA  1FP   FSQRT        \ x87 Square root
  2084.               1 $FA  1FP   FSQRT,       \ x87 -- for compat.
  2085.    $00  $10   5 $D0  3FP   FST          \ x87 Store (real/integer)
  2086.               1 $38  2FP   FSTCW        \ x87 Store control word
  2087.               1 $30  2FP   FSTENV       \ x87 Store environment
  2088.    $30  $18   5 $D8  3FP   FSTP         \ x87 Store (real/integer/BCD/temp_real) and Pop
  2089.               5 $38  2FP   FSTSW        \ x87 Store status word
  2090.             $20 $E0  7FP   FSUB         \ x87 Subtract (real/integer)
  2091.                 $E0  5FP   FSUBP        \ x87 Subtract real and pop
  2092.             $28 $E8  7FP   FSUBR        \ x87 Subtract (real/integer) REVERSE
  2093.                 $E8  5FP   FSUBRP       \ x87 Subtract real reverse and Pop
  2094.               1 $E4  1FP   FTST         \ x87 Test stack top against +0.0
  2095.               5 $E0  9FP   FUCOM        \ 387 unordered compare
  2096.               5 $E8  9FP   FUCOMP       \ 387 unordered compare and pop
  2097.               2 $E9  8FP   FUCOMPP      \ 387 unordered Compare and Pop Twice
  2098.               1 $E5  1FP   FXAM         \ x87 Examine stack top
  2099.               1 $C8  4FP   FXCH         \ x87 Exchange registers
  2100.               1 $F4  1FP   FXTRACT      \ x87 Extract exponent and significant
  2101.               1 $F1  1FP   FYL2X        \ x87 Y*(LOG2(X))
  2102.               1 $F9  1FP   FYL2XP1      \ x87 Y*(LOG2(X+1))
  2103.  
  2104.         $F4          1MI   HLT          \ Halt Processor !
  2105.  
  2106.         $F6 $38      8MI   IDIV         \ (integer) Signed Divide
  2107.         $F6 $28      8MI   IMUL         \ (integer) Signed Multiply
  2108.         $EC $E4      6MI   IN           \ Input from an I/O Port
  2109.         $00 $40     11MI   INC          \ Increment
  2110.         $6C         39MI   INS          \ 386 Input          String - DX port
  2111.         $6C         32MI   INSB         \ 386 Input  (byte)  String - DX port
  2112.         $66 $6D     33MI   INSD         \ 386 Input  (Dword) String - DX port
  2113.         $6D         32MI   INSW         \ 386 Input  (word)  String - DX port
  2114.                     15MI   INT          \ Call to Software-Interrupt Procedure
  2115.         $CE          1MI   INTO         \ On Overflow, call interrupt procedure
  2116.         $CF          1MI   IRET         \ Interrupt Return - restore 16 bit regs
  2117.     $66 $CF         33MI   IRETD        \ 386 Interrupt Return - restore 32 bit regs (protected mode)
  2118.  
  2119.         $77          2MI   JA           \ Jump if Above                (CF=0 and ZF=0)
  2120.         $73          2MI   JAE          \ Jump if Above or Equal       (CF=0)
  2121.         $72          2MI   JB           \ Jump if Below                (CF=1)
  2122.         $76          2MI   JBE          \ Jump if Below or Equal       (CF=1 or ZF=1)
  2123.         $72          2MI   JC           \ Jump if Carry                (CF=1)
  2124.         $E3          2MI   JCXZ         \ Jump if CX Register is Zero
  2125.         $74          2MI   JE           \ Jump if Equal                (ZF=1)
  2126.         $7F          2MI   JG           \ Jump if Greater              (ZF=0 and SF=OF)
  2127.         $7D          2MI   JGE          \ Jump if Greater of Equal     (SF=OF)
  2128.         $7C          2MI   JL           \ Jump if Less                 (SF<>OF)
  2129.         $7E          2MI   JLE          \ Jump if Less or Equal        (ZF=1 or SF<>OF)
  2130.         $EA $E9 $20  5MI   JMP          \ Unconditional JUMP
  2131.         $76          2MI   JNA          \ Jump if Not Above            (CF=1 and ZF=1)
  2132.         $72          2MI   JNAE         \ Jump if Not Above or Equal   (CF=1)
  2133.         $73          2MI   JNB          \ Jump if Not Below            (CF=0)
  2134.         $77          2MI   JNBE         \ Jump if Not Below or Equal   (CF=0 and ZF=0)
  2135.         $73          2MI   JNC          \ Jump if Not Carry            (CF=0)
  2136.         $75          2MI   JNE          \ Jump if Not Equal            (ZF=0)
  2137.         $7E          2MI   JNG          \ Jump if Not Greater          (ZF=1 or SF<>OF)
  2138.         $7C          2MI   JNGE         \ Jump if Not Greater or Equal (SF<>OF)
  2139.         $7D          2MI   JNL          \ Jump if Not Less             (SF=OF)
  2140.         $7F          2MI   JNLE         \ Jump if Not Less or Equal    (ZF=0 and SF=OF)
  2141.         $71          2MI   JNO          \ Jump if Not Overflow         (OF=0)
  2142.         $7B          2MI   JNP          \ Jump if Not Parity           (PF=0)
  2143.         $79          2MI   JNS          \ Jump if Not Sign             (SF=0)
  2144.         $75          2MI   JNZ          \ Jump if Not Zero             (ZF=0)
  2145.         $70          2MI   JO           \ Jump if Overflow             (OF=1)
  2146.         $7A          2MI   JP           \ Jump if Parity               (PF=1)
  2147.         $7A          2MI   JPE          \ Jump if Parity Even          (PF=1)
  2148.         $7B          2MI   JPO          \ Jump if Parity Odd           (PF=0)
  2149.         $78          2MI   JS           \ Jump if Sign                 (SF=1)
  2150.         $74          2MI   JZ           \ Jump if Zero                 (ZF=1)
  2151.  
  2152.         $9F          1MI   LAHF         \ Load Flags into AH register
  2153.         $C5         14MI   LDS          \ Load pointer into DS register
  2154.         $8D         14MI   LEA          \ Load Effective Address
  2155.         $C4         14MI   LES          \ Load pointer into ES register
  2156.         $0F $B4     34MI   LFS          \ 386 Segment Register Load
  2157.         $0F $B5     34MI   LGS          \ 386 Segment Register Load
  2158.         $F0          1MI   LOCK         \ Bus Lock
  2159.         $AC          3MI   LODS         \ Load         String
  2160.         $AC          1MI   LODSB        \ Load (byte)  String
  2161.         $66 $AD     33MI   LODSD        \ Load (Dword) String
  2162.         $AD          1MI   LODSW        \ Load (word)  String
  2163.         $E2          2MI   LOOP         \ Loop with CX as counter
  2164.         $E1          2MI   LOOPE        \ Loop with CX as counter and Equal
  2165.         $E0          2MI   LOOPNE       \ Loop with CX as Counter and NOT Equal
  2166.         $E0          2MI   LOOPNZ       \ Loop with CX as Counter and NOT Zero
  2167.         $E1          2MI   LOOPZ        \ Loop with CX as Counter and Zero
  2168.         $0F $B2     34MI   LSS          \ 386 Segment Register Load
  2169.  
  2170.                     40MI   MOV          \ Move
  2171.         $A4          3MI   MOVS         \ Move         String
  2172.         $A4          1MI   MOVSB        \ Move (byte)  String
  2173.         $66 $A5     33MI   MOVSD        \ Move (Dword) String
  2174.         $A5          1MI   MOVSW        \ Move (word)  String
  2175.         $BE         42MI   MOVSX        \ 386 move to reg with Sign Extension
  2176.         $B6         42MI   MOVZX        \ 386 move to reg with Zero Extension
  2177.         $F6 $20      8MI   MUL          \ Unsigned Multiply
  2178.  
  2179.         $F6 $18      8MI   NEG          \ Negate
  2180.         $90          1MI   NOP          \ No Operation
  2181.         $F6 $10      8MI   NOT          \ (Logical) Not
  2182.  
  2183.     $02 $0C $80 $08  7MI   OR           \ (logical) Or
  2184.         $EE $E6      6MI   OUT          \ Write to I/O Port
  2185.         $6E         39MI   OUTS         \ 386 Output         String - DX port
  2186.         $6E         32MI   OUTSB        \ 386 Output (byte)  String - DX port
  2187.         $66 $6F     33MI   OUTSD        \ 386 Output (Dword) String - DX port
  2188.         $6F         32MI   OUTSW        \ 386 Output (word)  String - DX port
  2189.  
  2190. $8F $58 $07         36MI   POP          \ Pop off Stack
  2191.         $61         32MI   POPA         \ 386 Pop All 16 bit Registers
  2192.     $66 $61         33MI   POPAD        \ 386 Pop All 32 bit Registers
  2193.         $9D          1MI   POPF         \ Pop Flags off Stack
  2194.     $66 $9D         33MI   POPFD        \ 386 Pop 32 bit Flags off Stack
  2195. $FF $50 $06         35MI   PUSH         \ Push onto Stack
  2196.         $60         32MI   PUSHA        \ 386 Push All 16 bit Registers
  2197.     $66 $60         33MI   PUSHAD       \ 386 Push All 16 bit Registers
  2198.         $9C          1MI   PUSHF        \ Push Flags onto Stack
  2199.     $66 $9C         33MI   PUSHFD       \ 386 Push 32 bit Flags onto Stack
  2200.  
  2201.         $10          9MI   RCL          \ Rotate through Carry Left
  2202.         $18          9MI   RCR          \ Rotate through Carry Right
  2203.         $F3          1MI   REP          \ Repeat
  2204.         $F3          1MI   REPE         \ Repeat while Equal
  2205.         $F2          1MI   REPNE        \ Repeat while Not Equal
  2206.         $F2          1MI   REPNZ        \ Repeat while Not Zero
  2207.         $F3          1MI   REPZ         \ Repeat while Zero
  2208.         $C3          1MI   RET          \ Return from Procedure
  2209.         $CB          1MI   RETF         \ Return from Inter-Segment Procedure
  2210.         $00          9MI   ROL          \ Rotate Left
  2211.         $08          9MI   ROR          \ Rotate Right
  2212.  
  2213.         $9E          1MI   SAHF         \ Store AH into Flags
  2214.         $20          9MI   SAL          \ Shift Arithmetic Left
  2215.         $38          9MI   SAR          \ Shift Arithmetic Right
  2216.     $01 $1C $80 $18  7MI   SBB          \ Subtract with Borrow
  2217.         $AE          3MI   SCAS         \ Scan         String
  2218.         $AE          1MI   SCASB        \ Scan (byte)  String
  2219.         $66 $AF     33MI   SCASD        \ Scan (Dword) String
  2220.         $AF          1MI   SCASW        \ Scan (word)  String
  2221.         $97         37MI   SETA         \ 386 SET if Above                (CF=0 and ZF=0)
  2222.         $93         37MI   SETAE        \ 386 SET if Above or Equal       (CF=0)
  2223.         $92         37MI   SETB         \ 386 SET if Below                (CF=1)
  2224.         $96         37MI   SETBE        \ 386 SET if Below or Equal       (CF=1 or ZF=1)
  2225.         $92         37MI   SETC         \ 386 SET if Carry                (CF=1)
  2226.         $94         37MI   SETE         \ 386 SET if Equal                (ZF=1)
  2227.         $9F         37MI   SETG         \ 386 SET if Greater              (ZF=0 and SF=OF)
  2228.         $9D         37MI   SETGE        \ 386 SET if Greater of Equal     (SF=OF)
  2229.         $9C         37MI   SETL         \ 386 SET if Less                 (SF<>OF)
  2230.         $9E         37MI   SETLE        \ 386 SET if Less or Equal        (ZF=1 or SF<>OF)
  2231.         $96         37MI   SETNA        \ 386 SET if Not Above            (CF=1 and ZF=1)
  2232.         $92         37MI   SETNAE       \ 386 SET if Not Above or Equal   (CF=1)
  2233.         $93         37MI   SETNB        \ 386 SET if Not Below            (CF=0)
  2234.         $97         37MI   SETNBE       \ 386 SET if Not Below or Equal   (CF=0 and ZF=0)
  2235.         $93         37MI   SETNC        \ 386 SET if Not Carry            (CF=0)
  2236.         $95         37MI   SETNE        \ 386 SET if Not Equal            (ZF=0)
  2237.         $9E         37MI   SETNG        \ 386 SET if Not Greater          (ZF=1 or SF<>OF)
  2238.         $9C         37MI   SETNGE       \ 386 SET if Not Greater or Equal (SF<>OF)
  2239.         $9D         37MI   SETNL        \ 386 SET if Not Less             (SF=OF)
  2240.         $9F         37MI   SETNLE       \ 386 SET if Not Less or Equal    (ZF=0 and SF=OF)
  2241.         $91         37MI   SETNO        \ 386 SET if Not Overflow         (OF=0)
  2242.         $9B         37MI   SETNP        \ 386 SET if Not Parity           (PF=0)
  2243.         $99         37MI   SETNS        \ 386 SET if Not Sign             (SF=0)
  2244.         $95         37MI   SETNZ        \ 386 SET if Not Zero             (ZF=0)
  2245.         $90         37MI   SETO         \ 386 SET if Overflow             (OF=1)
  2246.         $9A         37MI   SETP         \ 386 SET if Parity               (PF=1)
  2247.         $9A         37MI   SETPE        \ 386 SET if Parity Even          (PF=1)
  2248.         $9B         37MI   SETPO        \ 386 SET if Parity Odd           (PF=0)
  2249.         $98         37MI   SETS         \ 386 SET if Sign                 (SF=1)
  2250.         $94         37MI   SETZ         \ 386 SET if Zero                 (ZF=1)
  2251.         $20          9MI   SHL          \ Shift (logical) Left
  2252.         $A4         41MI   SHLD         \ 386 Shift Left  Double
  2253.         $28          9MI   SHR          \ Shift (logical) Right
  2254.         $AC         41MI   SHRD         \ 386 Shift Right Double
  2255.         $F9          1MI   STC          \ Set Carry Flag
  2256.         $FD          1MI   STD          \ Set Direction Flag (decreasing)
  2257.         $FB          1MI   STI          \ Set Interrupt Flag (enable)
  2258.         $AA          3MI   STOS         \ Store         String
  2259.         $AA          1MI   STOSB        \ Store (byte)  String
  2260.         $66 $AB     33MI   STOSD        \ Store (Dword) String
  2261.         $AB          1MI   STOSW        \ Store (word)  String
  2262.     $01 $2C $80 $28  7MI   SUB          \ Subtract
  2263.  
  2264.     $02 $A8 $F6 $84  7MI   TEST         \ Logical Compare
  2265.  
  2266.         $9B          1MI   WAIT         \ Wait for Coprocessor
  2267.  
  2268.                     13MI   XCHG         \ Exchange
  2269.         $D7          1MI   XLAT         \ Table Lookup Translation
  2270.     $02 $34 $80 $30  7MI   XOR          \ (logical) Exclusive Or
  2271.  
  2272.  
  2273. \ ===========================================================================
  2274. \       For Floating Point Processor
  2275. \ ===========================================================================
  2276.  
  2277. : WSS:  ( -- )
  2278.         WAIT SS: NOWAIT ;
  2279.  
  2280. : WCS:  ( -- )
  2281.         WAIT CS: NOWAIT ;
  2282.  
  2283. : WDS:  ( -- )
  2284.         WAIT DS: NOWAIT ;
  2285.  
  2286. : WES:  ( -- )
  2287.         WAIT ES: NOWAIT ;
  2288.  
  2289.  
  2290.  
  2291. \ ===========================================================================
  2292. \          The jump mnemonics:
  2293. \ ===========================================================================
  2294.  
  2295.         ' jmp  alias j          ( JMP  )
  2296.         ' jne  alias j0<>       ( JNE  )
  2297.         ' jz   alias j0=        ( JZ   )
  2298.         ' jns  alias j0>=       ( JNS  )
  2299.         ' js   alias j0<        ( JS   )
  2300.         ' jne  alias j<>        ( JNE  )
  2301.         ' jz   alias j=         ( JZ   )
  2302.         ' jnl  alias j>=        ( JNL  )
  2303.         ' jnge alias j<         ( JNGE )
  2304.         ' jnle alias j>         ( JNLE )
  2305.         ' jng  alias j<=        ( JNG  )
  2306.         ' jnc  alias ju>=       ( JNC  )
  2307.         ' jnae alias ju<        ( JNAE )
  2308.         ' jnbe alias ju>        ( JNBE )
  2309.         ' jna  alias ju<=       ( JNA  )
  2310.  
  2311.  
  2312. \ ===========================================================================
  2313. \          Operand Modifiers
  2314. \ ===========================================================================
  2315.  
  2316.  
  2317. : FAR     1 <FR> ! ;                            \ for intersegment jump/call
  2318.  
  2319.  
  2320. : BYTE    0 <W> !   0 <WD> ! 0 <ED> ! ;         \ force  byte size mode
  2321.  
  2322. : WORD    1 <W> !   1 <WD> ! 0 <ED> ! ;         \ force  word size mode
  2323.  
  2324. : DWORD   1 <W> !   1 <WD> ! 3 <ED> ! ;         \ force Dword size mode
  2325.  
  2326.  
  2327. : #       1 <TS> ! -1 <SST> ! 1 <ID> ! ;        \ set immediate data flag
  2328.                                                 \ to indicate immediate data
  2329.                                                 \ is on the stack
  2330.  
  2331.  
  2332. : #)      ( ?D><S ) -1 <SST> !   \ Swap source and dest if no dest spec'ed.
  2333.           1 <W> ! ;                \ Default to word mode
  2334.  
  2335.  
  2336. : []      0 <W> !  1 <ND> ! ;                   \ for indirect jump/call
  2337.  
  2338. : 3*      DUP 2* + ;            \ *** Who knows what this is for,
  2339.                                 \ *** it is NOT used in the standard system.
  2340.  
  2341. \ ===========================================================================
  2342. \          MACROS for NEXT, 1PUSH, and 2PUSH.
  2343. \ ===========================================================================
  2344.  
  2345.  
  2346. VARIABLE INLN           \ Flag to determine if we are compiling IN_LINE next.
  2347.  
  2348. : INLINEON      INLN ON ;
  2349. \       turns generation of inline NEXT on.
  2350.  
  2351. : INLINEOFF     INLN OFF ;      INLINEON        \ Default to INLINE NEXT.
  2352. \       turns generation of inline NEXT off.
  2353.  
  2354.  
  2355. : NEXT          ( -- )
  2356.                 >PRE
  2357.                 INLN @
  2358.                 IF      LODSW ES: JMP AX    A;
  2359.                 ELSE              JMP >NEXT A;
  2360.                 THEN
  2361.                 PRE> ;
  2362.  
  2363.  
  2364. : 1PUSH         ( -- )
  2365.                 >PRE
  2366.                 INLN @
  2367.                 IF      PUSH AX LODSW ES: JMP AX       A;
  2368.                 ELSE                      JMP >NEXT 1- A;
  2369.                 THEN
  2370.                 PRE> ;
  2371.  
  2372.  
  2373. : 2PUSH         ( -- )
  2374.                 >PRE
  2375.                 INLN @
  2376.                 IF      PUSH DX PUSH AX LODSW ES: JMP AX       A;
  2377.                 ELSE                              JMP >NEXT 2- A;
  2378.                 THEN
  2379.                 PRE> ;
  2380.  
  2381.  
  2382.  
  2383.  
  2384. \ ===========================================================================
  2385. \          Control  Constructs
  2386. \ ===========================================================================
  2387.  
  2388.  
  2389.  
  2390. headerless              \ ***************************************************
  2391.  
  2392. : A?>MARK    ( -- f addr ) TRUE   HERE   0 C,   ;
  2393. : A?>RESOLVE ( f addr -- ) HERE OVER 1+ - SWAP TC! ?CONDITION ;
  2394. : A?<MARK    ( -- f addr ) TRUE   HERE   ;
  2395. : A?<RESOLVE ( f addr -- ) HERE 1+ -  C,   ?CONDITION   ;
  2396. ' A?>MARK    ASSEMBLER IS ?>MARK
  2397. ' A?>RESOLVE ASSEMBLER IS ?>RESOLVE
  2398. ' A?<MARK    ASSEMBLER IS ?<MARK
  2399. ' A?<RESOLVE ASSEMBLER IS ?<RESOLVE
  2400.  
  2401.  
  2402. headers                 \ ***************************************************
  2403.  
  2404.         $75 CONSTANT 0=   $74 CONSTANT 0<>   $79 CONSTANT 0<
  2405.         $78 CONSTANT 0>=  $7D CONSTANT <     $7C CONSTANT >=
  2406.         $7F CONSTANT <=   $7E CONSTANT >     $73 CONSTANT U<
  2407.         $72 CONSTANT U>=  $77 CONSTANT U<=   $76 CONSTANT U>
  2408.         $70 CONSTANT OV<> $71 CONSTANT OV
  2409.         $E3 CONSTANT CX<>0
  2410.         $7A CONSTANT PO   $7B CONSTANT PE
  2411.  
  2412.  
  2413.         : BEGIN ( - a f )
  2414.                 A; ?<MARK ;
  2415.  
  2416.         : UNTIL ( a f n - )
  2417.                 >R A; R> C, ?<RESOLVE A; ;      \ ** added A;
  2418.  
  2419.         : AGAIN ( a f - )
  2420.                 $EB UNTIL ;
  2421.  
  2422.         : IF    ( n - A f )
  2423.                 >R A; R> C, ?>MARK A; ;         \ ** added A;
  2424.  
  2425.         : FORWARD ( - A f )
  2426.                 $EB IF ;
  2427.  
  2428.         : THEN  ( A f - )
  2429.                 A; ?>RESOLVE ;
  2430.  
  2431.         : AFT   ( a f - a f A f )
  2432.                 2DROP FORWARD BEGIN 2SWAP ;
  2433.  
  2434.         : ELSE  ( A f - A f )
  2435.                 FORWARD 2SWAP THEN ;
  2436.  
  2437.         : REPEAT ( A f a f - )
  2438.                 A; AGAIN THEN ;
  2439.  
  2440.         : CONTINUE (  a f A f - a f )
  2441.                 2OVER REPEAT ;
  2442.  
  2443.         : WHILE ( a f - A f a f )
  2444.                 IF 2SWAP ;
  2445.  
  2446.  
  2447.  
  2448. \ ===========================================================================
  2449. \          Functions to permit assembler code inside of a Colon Definition
  2450. \ ===========================================================================
  2451.  
  2452. FORTH DEFINITIONS
  2453.  
  2454. : INLINE        [COMPILE] [ SETASSEM HERE X, ; IMMEDIATE
  2455. \       Starts an assembly language sequence in the middle of a : (colon)
  2456. \       definition. Assembly code instructions follow until the sequence
  2457. \       is terminated by END-INLINE. The sequence of assembly instructions
  2458. \       normally includes NEXT, 1PUSH, or 2PUSH just prior to the word
  2459. \       END-INLINE.
  2460.  
  2461. ASSEMBLER DEFINITIONS
  2462.  
  2463. : END-INLINE    [ ASSEMBLER ] END-CODE ] ;
  2464. \       Terminates a sequence of assembly instructions started with
  2465. \       INLINE in the middle of a : (colon) definition. Compilation of
  2466. \       the : (colon) definition resumes after END-INLINE is encountered
  2467.  
  2468. COMMENT:
  2469.         \ Here is an example of how to use INLINE and END-INLINE to add
  2470.         \ assembly code in the middle of a CODE definition.
  2471.  
  2472.         : TEST  ( --- )
  2473.                 5 0
  2474.                 DO I
  2475.                         INLINE
  2476.                                 pop ax
  2477.                                 add ax, # 23
  2478.                                 1push
  2479.                         END-INLINE
  2480.                         .
  2481.                 LOOP ;
  2482. COMMENT;
  2483.  
  2484. behead                  \ ***************************************************
  2485.  
  2486. ONLY FORTH DEFINITIONS ALSO
  2487.  
  2488. DECIMAL
  2489.  
  2490.