home .. products .. mforth .. source code ..
assembler.asm
; Copyright (c) 2011, Michael Alyn Miller <malyn@strangeGizmo.com>.
; All rights reserved.
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
;
; 1. Redistributions of source code must retain the above copyright notice
;    unmodified, this list of conditions, and the following disclaimer.
; 2. Redistributions in binary form must reproduce the above copyright notice,
;    this list of conditions and the following disclaimer in the documentation
;    and/or other materials provided with the distribution.
; 3. Neither the name of Michael Alyn Miller nor the names of the contributors
;    to this software may be used to endorse or promote products derived from
;    this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
; THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.


; ======================================================================
; Assembler Words
; ======================================================================

; ----------------------------------------------------------------------
; END-CODE [MFORTH] ( -- )
;
; End the current code definition.  If the data-space pointer is not
; aligned, reserve enough data space to align it.  Restore the previous
; search order.
;
; ---
; : END-CODE ( -- )   PREVIOUS ;

            LINKTO(LINK_ASSEMBLER,0,8,'E',"DOC-DNE")
ENDCODE:    JMP     ENTER
            .WORD   PREVIOUS
            .WORD   EXIT


; ----------------------------------------------------------------------
; NEXT [MFORTH] ( -- )
;
; Compile the code for NEXT into the current code definition.

            LINKTO(ENDCODE,0,4,'T',"XEN")
asmNEXT:    JMP     ENTER
#IFNDEF PROFILER
            .WORD   asmLHLX
            .WORD   asmOpD,asmINX
            .WORD   asmOpD,asmINX
            .WORD   asmPCHL
#ELSE
            .WORD   LIT,PROFILENEXT,asmJMP
#ENDIF
            .WORD   EXIT


; ----------------------------------------------------------------------
; ROMCALL [MFORTH] ( addr -- )
;
; Call the Main ROM routine identified by addr.

            LINKTO(asmNEXT,0,7,'L',"LACMOR")
asmROMCALL:     JMP  ENTER
            .WORD   LIT,STDCALL,asmCALL
            .WORD   COMMA
            .WORD   EXIT


; ----------------------------------------------------------------------
; RESTOREREGS [MFORTH] ( -- )
;
; Restore BC and DE (corrupts HL).

            LINKTO(asmROMCALL,0,11,'S',"GEREROTSER")
asmRESTOREREGS:JMP  ENTER
            .WORD   LIT,SAVEB,asmLHLD
            .WORD   asmOpH,asmOpB,asmMOV
            .WORD   asmOpL,asmOpC,asmMOV
            .WORD   LIT,SAVED,asmLHLD
            .WORD   asmXCHG
            .WORD   EXIT


; ----------------------------------------------------------------------
; SAVEREGS [MFORTH] ( -- )
;
; Save BC and DE (corrupts HL).

            LINKTO(asmRESTOREREGS,0,8,'S',"GEREVAS")
asmSAVEREGS:JMP     ENTER
            .WORD   asmOpB,asmOpH,asmMOV
            .WORD   asmOpC,asmOpL,asmMOV
            .WORD   LIT,SAVEB,asmSHLD
            .WORD   asmXCHG
            .WORD   LIT,SAVED,asmSHLD
            .WORD   EXIT



; ======================================================================
; Control Flow Words
; ======================================================================

            LINKTO(asmSAVEREGS,0,2,'=',"0")
asmZEROEQUALS:JMP   ENTER
            .WORD   LIT,$C2,EXIT

            LINKTO(asmZEROEQUALS,0,2,'>',"0")
asmZEROGREATER:JMP  ENTER
            .WORD   LIT,$FA,EXIT

            LINKTO(asmZEROGREATER,0,2,'<',"0")
asmZEROLESS:JMP     ENTER
            .WORD   LIT,$F2,EXIT

            LINKTO(asmZEROLESS,0,3,'>',"<0")
asmZERONOTEQUALS:JMP ENTER
            .WORD   LIT,$CA,EXIT

            LINKTO(asmZERONOTEQUALS,0,2,'C',"C")
asmCC:      JMP     ENTER
            .WORD   LIT,$DA,EXIT

            LINKTO(asmCC,0,2,'S',"C")
asmCS:      JMP     ENTER
            .WORD   LIT,$D2,EXIT

            LINKTO(asmCS,0,5,'N',"IGEB")
asmBEGIN:   JMP     ENTER
            .WORD   HERE,EXIT

            LINKTO(asmBEGIN,0,4,'E',"SLE")
asmELSE:    JMP     ENTER
            .WORD   LIT,$C3,asmIF,SWAP,asmTHEN,EXIT

            LINKTO(asmELSE,0,2,'F',"I")
asmIF:      JMP     ENTER
            .WORD   CCOMMA,HERE,ZERO,COMMA,EXIT

            LINKTO(asmIF,0,4,'N',"EHT")
asmTHEN:    JMP     ENTER
            .WORD   HERE,SWAP,STORE,EXIT

            LINKTO(asmTHEN,0,6,'T',"AEPER")
asmREPEAT:  JMP     ENTER
            .WORD   SWAP,LIT,$C3,CCOMMA,COMMA,asmTHEN,EXIT

            LINKTO(asmREPEAT,0,5,'L',"ITNU")
asmUNTIL:   JMP     ENTER
            .WORD   CCOMMA,COMMA,EXIT

            LINKTO(asmUNTIL,0,5,'E',"LIHW")
asmWHILE:   JMP     ENTER
            .WORD   asmIF,EXIT


; ======================================================================
; 8085 Assembly Instructions
; ======================================================================

; ----------------------------------------------------------------------
; Operands
;

#DEFINE     ASM_OP(value) LXI H,value\ PUSH H\ NEXT

            LINKTO(asmWHILE,0,1,'A',"")
asmOpA:     ASM_OP(7)

            LINKTO(asmOpA,0,1,'B',"")
asmOpB:     ASM_OP(0)

            LINKTO(asmOpB,0,1,'C',"")
asmOpC:     ASM_OP(1)

            LINKTO(asmOpC,0,1,'D',"")
asmOpD:     ASM_OP(2)

            LINKTO(asmOpD,0,1,'E',"")
asmOpE:     ASM_OP(3)

            LINKTO(asmOpE,0,1,'H',"")
asmOpH:     ASM_OP(4)

            LINKTO(asmOpH,0,1,'L',"")
asmOpL:     ASM_OP(5)

            LINKTO(asmOpL,0,1,'M',"")
asmOpM:     ASM_OP(6)

            LINKTO(asmOpM,0,3,'W',"SP")
asmOpPSW:   ASM_OP(6)

            LINKTO(asmOpPSW,0,2,'P',"S")
asmOpSP:    ASM_OP(6)


; ----------------------------------------------------------------------
; Zero-operand instructions
;

#DEFINE     ASM_ZERO_OP(opcode) JMP ENTER\ .WORD LIT,opcode,CCOMMA,EXIT

            LINKTO(asmOpSP,0,4,'R',"HSA")
asmASHR:    ASM_ZERO_OP($10)

            LINKTO(asmASHR,0,3,'A',"MC")
asmCMA:     ASM_ZERO_OP($2F)

            LINKTO(asmCMA,0,3,'C',"MC")
asmCMC:     ASM_ZERO_OP($3F)

            LINKTO(asmCMC,0,3,'A',"AD")
asmDAA:     ASM_ZERO_OP($27)

            LINKTO(asmDAA,0,2,'I',"D")
asmDI:      ASM_ZERO_OP($F3)

            LINKTO(asmDI,0,4,'B',"USD")
asmDSUB:    ASM_ZERO_OP($08)

            LINKTO(asmDSUB,0,2,'I',"E")
asmEI:      ASM_ZERO_OP($FB)

            LINKTO(asmEI,0,3,'T',"LH")
asmHLT:     ASM_ZERO_OP($76)

            LINKTO(asmHLT,0,4,'X',"LHL")
asmLHLX:    ASM_ZERO_OP($ED)

            LINKTO(asmLHLX,0,3,'P',"ON")
asmNOP:     ASM_ZERO_OP($00)

            LINKTO(asmNOP,0,4,'L',"HCP")
asmPCHL:    ASM_ZERO_OP($E9)

            LINKTO(asmPCHL,0,3,'L',"AR")
asmRAL:     ASM_ZERO_OP($17)

            LINKTO(asmRAL,0,3,'R',"AR")
asmRAR:     ASM_ZERO_OP($1F)

            LINKTO(asmRAR,0,4,'L',"EDR")
asmRDEL:    ASM_ZERO_OP($18)

            LINKTO(asmRDEL,0,3,'T',"ER")
asmRET:     ASM_ZERO_OP($C9)

            LINKTO(asmRET,0,3,'M',"IR")
asmRIM:     ASM_ZERO_OP($20)

            LINKTO(asmRIM,0,3,'C',"LR")
asmRLC:     ASM_ZERO_OP($07)

            LINKTO(asmRLC,0,3,'C',"RR")
asmRRC:     ASM_ZERO_OP($0F)

            LINKTO(asmRRC,0,4,'X',"LHS")
asmSHLX:    ASM_ZERO_OP($D9)

            LINKTO(asmSHLX,0,3,'M',"IS")
asmSIM:     ASM_ZERO_OP($30)

            LINKTO(asmSIM,0,4,'L',"HPS")
asmSPHL:    ASM_ZERO_OP($F9)

            LINKTO(asmSPHL,0,3,'C',"TS")
asmSTC:     ASM_ZERO_OP($37)

            LINKTO(asmSTC,0,4,'G',"HCX")
asmXCHG:    ASM_ZERO_OP($EB)

            LINKTO(asmXCHG,0,4,'L',"HTX")
asmXTHL:    ASM_ZERO_OP($E3)


; ----------------------------------------------------------------------
; Register instructions
;

#DEFINE     ASM_REG_OP(opcode) JMP ENTER\ .WORD LIT,opcode,PLUS,CCOMMA,EXIT

            LINKTO(asmXTHL,0,3,'C',"DA")
asmADC:     ASM_REG_OP($88)

            LINKTO(asmADC,0,3,'D',"DA")
asmADD:     ASM_REG_OP($80)

            LINKTO(asmADD,0,3,'A',"NA")
asmANA:     ASM_REG_OP($A0)

            LINKTO(asmANA,0,3,'P',"MC")
asmCMP:     ASM_REG_OP($B8)

            LINKTO(asmCMP,0,3,'R',"DC")
asmDCR:     JMP     ENTER
            .WORD   EIGHTSTAR,LIT,$05,PLUS,CCOMMA,EXIT

            LINKTO(asmDCR,0,3,'R',"NI")
asmINR:     JMP     ENTER
            .WORD   EIGHTSTAR,LIT,$04,PLUS,CCOMMA,EXIT

            LINKTO(asmINR,0,3,'A',"RO")
asmORA:     ASM_REG_OP($B0)

            LINKTO(asmORA,0,3,'B',"BS")
asmSBB:     ASM_REG_OP($98)

            LINKTO(asmSBB,0,3,'B',"US")
asmSUB:     ASM_REG_OP($90)

            LINKTO(asmSUB,0,3,'A',"RX")
asmXRA:     ASM_REG_OP($A8)


; ----------------------------------------------------------------------
; Register pair instructions
;

#DEFINE     ASM_REGPAIR_OP(opcode) JMP ENTER\ .WORD EIGHTSTAR,LIT,opcode,PLUS,CCOMMA,EXIT

            LINKTO(asmXRA,0,3,'D',"AD")
asmDAD:     ASM_REGPAIR_OP($09)

            LINKTO(asmDAD,0,3,'X',"CD")
asmDCX:     ASM_REGPAIR_OP($0B)

            LINKTO(asmDCX,0,3,'X',"NI")
asmINX:     ASM_REGPAIR_OP($03)

            LINKTO(asmINX,0,4,'X',"ADL")
asmLDAX:    ASM_REGPAIR_OP($0A)

            LINKTO(asmLDAX,0,3,'P',"OP")
asmPOP:     ASM_REGPAIR_OP($C1)

            LINKTO(asmPOP,0,4,'H',"SUP")
asmPUSH:    ASM_REGPAIR_OP($C5)

            LINKTO(asmPUSH,0,4,'X',"ATS")
asmSTAX:    ASM_REGPAIR_OP($02)


; ----------------------------------------------------------------------
; Byte operand instructions
;

#DEFINE     ASM_BYTE_OP(opcode) JMP ENTER\ .WORD LIT,opcode,CCOMMA,CCOMMA,EXIT

            LINKTO(asmSTAX,0,3,'I',"CA")
asmACI:     ASM_BYTE_OP($CE)

            LINKTO(asmACI,0,3,'I',"DA")
asmADI:     ASM_BYTE_OP($C6)

            LINKTO(asmADI,0,3,'I',"NA")
asmANI:     ASM_BYTE_OP($E6)

            LINKTO(asmANI,0,3,'I',"PC")
asmCPI:     ASM_BYTE_OP($FE)

            LINKTO(asmCPI,0,2,'N',"I")
asmIN:      ASM_BYTE_OP($DB)

            LINKTO(asmIN,0,3,'I',"RO")
asmORI:     ASM_BYTE_OP($F6)

            LINKTO(asmORI,0,3,'T',"UO")
asmOUT:     ASM_BYTE_OP($D3)

            LINKTO(asmOUT,0,3,'T',"SR")
asmRST:     JMP     ENTER
            .WORD   EIGHTSTAR,LIT,$C7,PLUS,CCOMMA,EXIT

            LINKTO(asmRST,0,3,'I',"BS")
asmSBI:     ASM_BYTE_OP($DE)

            LINKTO(asmSBI,0,3,'I',"US")
asmSUI:     ASM_BYTE_OP($D6)

            LINKTO(asmSUI,0,3,'I',"RX")
asmXRI:     ASM_BYTE_OP($EE)


; ----------------------------------------------------------------------
; Word operand instructions
;

#DEFINE     ASM_WORD_OP(opcode) JMP ENTER\ .WORD LIT,opcode,CCOMMA,COMMA,EXIT

            LINKTO(asmXRI,0,4,'L',"LAC")
asmCALL:    ASM_WORD_OP($CD)

            LINKTO(asmCALL,0,3,'P',"MJ")
asmJMP:     ASM_WORD_OP($C3)

            LINKTO(asmJMP,0,3,'A',"DL")
asmLDA:     ASM_WORD_OP($3A)

            LINKTO(asmLDA,0,4,'D',"LHL")
asmLHLD:    ASM_WORD_OP($2A)

            LINKTO(asmLHLD,0,4,'D',"LHS")
asmSHLD:    ASM_WORD_OP($22)

            LINKTO(asmSHLD,0,3,'A',"TS")
asmSTA:     ASM_WORD_OP($32)


; ----------------------------------------------------------------------
; Move and Load Immediate instructions
;

            LINKTO(asmSTA,0,3,'I',"XL")
asmLXI:     JMP     ENTER
            .WORD   EIGHTSTAR,ONEPLUS,CCOMMA,COMMA,EXIT

            LINKTO(asmLXI,0,3,'V',"OM")
asmMOV:     JMP     ENTER
            .WORD   EIGHTSTAR,LIT,$40,PLUS,PLUS,CCOMMA,EXIT

            LINKTO(asmMOV,0,3,'I',"VM")
LAST_ASSEMBLER:
asmMVI:     JMP     ENTER
            .WORD   EIGHTSTAR,LIT,$06,PLUS,CCOMMA,CCOMMA,EXIT