Quantum Forth Z80 (versión 2)

Descripción del contenido de la página

Ensamblador del microprocesador Z80, escrito en Forth para QL.

Etiquetas:

Esta tercera versión se acerca más al enfoque de un ensamblador escrito en Forth: crea palabras para los registros y las condiciones, y usa cálculos en lugar de palabras específicas. Tiene el problema de que algunos cálculos dependen de la profundidad de la pila, lo que no es fiable y puede ocasionar errores.

Código fuente

El fichero original de 1988 estaba escrito para Computer One Forth, en formato de fichero de bloques de Forth, y con la codificación de caracteres de QL. Para facilitar su publicación y reutilización, lo convertí en un fichero de texto de formato estándar y codificado con UTF-8.
\ QUANTUM FORTH Z80 v2

\ Copyright (C) 1988 Marcos Cruz (programandala.net)
\ Licencia/Permesilo/License:
\ http://programandala.net/license

\ http://programandala.net/es.programa.quantum_forth_z80.html

\ 1988: Escrito para el Forth de Computer One de Sinclair QL.
\ 2015-03-13: Convertido del formato de bloques original a fichero
\ estándar. Textos y comentarios corregidos. Pequeños cambios de
\ formato.

\ Ejemplo de ensamblador

\        16384 ORG
\        " QL" DEFM
\        DI
\        23 # AA % 100101 DEFW
\        B AND
\        3 A BIT
\        EI
\        2 B RES
\        7 (IY+ 4 BIT
\        0 (IX+ -23 SET
\        (IY+ 7 DEC
\        20 # FF DEFB
\        THE_END

\ HERRAMIENTAS .................................................

: TASK ;
: .TIEMPO .DATE .TIME ;
: GEMINI10X PRINTER
  0 55 27 11 0 67 27 3 82 27 3 78 27 13 0 DO EMIT LOOP
  CONSOLE ;
: LLIST ( P1,P2--)
  PRINTER .TIEMPO CR 1+ SWAP
  DO
    16 0
    DO
      I J DUP 0 <# # # # #> TYPE OVER 0 <# # # #> TYPE SPACE
      .LINE CR
    LOOP
  LOOP CR .TIEMPO CR CONSOLE
  ;

\ MANEJO DE LA PILA ............................................

: DEPTH2/      DEPTH 2 / ;
: VACIA_PILA   S0 @ SP! ;
: TEXTO->PILA  DUP COUNT ROT + DO I C@ -1 +LOOP ;
: GIRA_PILA    PAD DEPTH2/ 1- 2DUP SWAP C! OVER + SWAP 1+ SWAP
               DO I C! -1 +LOOP PAD TEXTO->PILA ;

\ MANEJO DE NÚMEROS DE 32 BITS .................................

: NUMERO       BL WORD NUMBER ;
: NUM          NUMERO DROP DECIMAL ;

\ VARIABLES Y CONSTANTES .......................................

VARIABLE DIR_ZX

NUMERO 983040 2CONSTANT DIR0_QL

\ BANDERAS .....................................................

: BANDERA      CREATE 1 ALLOT DOES> ;
BANDERA PASADA
BANDERA LISTADO
: PON-BANDERA  SWAP C! ;
: SI           1 PON-BANDERA ;
: NO           0 PON-BANDERA ;

\ FUNCIONES ....................................................

: PASADA0? PASADA C@ 0= ;
: LISTADO? LISTADO C@ ;
: DIR_QL DIR0_QL DIR_ZX @ 0 D+ ;
: $ DIR_ZX @ ;
: 8* 8 * ;

\ COMPRUEBA EN LA PASADA 0 .....................................

: COMPRUEBA
  2DUP +
  DEPTH2/ 3 - 2DUP
  > 033 ?ERROR
  < 034 ?ERROR
  2 * + DIR_ZX +!
  ;

\ IMPRIMIR DIRECCIÓN Y CÓDIGO OBJETO ...........................

: .DIR_ZX
  CR DIR_ZX @
  DUP 0 <# # # # # # #> TYPE SPACE
  HEX 0 <# # # # # #> TYPE SPACE
  DECIMAL
  ;
: .XX
  LISTADO?
  IF
    DUP HEX 0 <# # # #> TYPE DECIMAL
  ENDIF
  DIR_QL
  ;

\ GUARDA EN LA PASADA 1 ........................................

: G, .XX C!L 1 DIR_ZX +! ;
: G,, DUP 255 AND G, -8 ASHIFT 255 AND G, ;
: GUARDA
  LISTADO? IF .DIR_ZX ENDIF
  SWAP >R
  DUP
  IF 0 DO G,, LOOP
  ELSE DROP
  ENDIF
  R>
  DUP
  IF 0 DO G, LOOP
  ENDIF
  ;

\ OPCODE LISTO PARA GUARDAR ....................................

: OPCODE
  PASADA0?
  IF
    COMPRUEBA
  ELSE
    GUARDA
  ENDIF
  VACIA_PILA
  ;
: 20O 2 0 OPCODE ;
: 21O 2 1 OPCODE ;
: 30O 3 0 OPCODE ;
: 40O 4 0 OPCODE ;

\ ENSAMBLA/COMPILA .............................................

\ : COMPILA 2 LOAD ; \ obsoleto

: ENSAMBLA
  0 DIR_ZX !
  PASADA NO
  CR
  ." QUANTUM FORTH Z80 por Marcos Cruz, 1988" CR
  ." Inicio ensamblado " .TIEMPO CR
  COMPILA
  ;

\ CONTROL DE ETIQUETAS .........................................

: EQU PASADA0? IF CONSTANT ELSE DROP ENDIF ;
: ? PASADA0? IF BL WORD ENDIF ; ( precede a las etiquetas)
: ] $ EQU ;

\ DIRECTIVAS TRANSPARENTES .....................................

: IDEFB DEPTH2/ 0 OPCODE ;
: IDEFW DEPTH2/ 0 SWAP OPCODE ;
: " 34 WORD TEXTO->PILA ;

\ DIRECTIVAS DE ENSAMBLADOR ....................................
: ORG $ - DUP 0< 38 ?ERROR DIR_ZX +! ;
: DEFS DIR_ZX +! ;
: DEFB GIRA_PILA IDEFB ;
: DEFW GIRA_PILA IDEFW ;
: DEFM IDEFB ;
: THE_END
  PASADA0?
  IF
    ." Pasada 0 completa " .TIEMPO PASADA SI
    0 DIR_ZX ! COMPILA
  ENDIF
  CR ." Pasada 1 completa " .TIEMPO CR
  CONSOLE DECIMAL QUIT
  ;

\ COMANDOS DEL ENSAMBLADOR .....................................

: *S BEGIN ?TERMINAL UNTIL ;
: *E CR CR CR ;
: *H *E 34 WORD COUNT TYPE ;
: *L+ LISTADO SI ;
: *L- LISTADO NO ;

\ OPERADORES Y SISTEMAS DE NUMERACIÓN ..........................

: % BINARY NUM ;
: # HEX NUM ;
: && AND ;
: || OR ;
: XX XOR ;

\ NEMÓNICOS TRANSPARENTES ......................................

: OO 1 0 OPCODE ;

: OOXX 20O ;

: JRXX
  SWAP $ 2+ -
  DUP 127 > 36 ?ERROR
  DUP -128 < 37 ?ERROR
  OOXX
  ;

: OOXXXX 1 1 OPCODE ;

: CBOO 203 20O ;

: DDOO 221 20O ;
: DDOOXX 221 30O ;
: DDCBXXOO SWAP 203 221 40O ;
: DDOOXXXX 221 21O ;

: FDOO 253 20O ;
: FDOOXX 253 30O ;
: FDCBXXOO SWAP 203 253 40O ;
: FDOOXXXX 253 21O ;

: EDOO 237 20O ;
: EDOOXXXX 237 21O ;

\ REGISTROS SIMPLES ............................................

256 CONSTANT B
257 CONSTANT C
258 CONSTANT D
259 CONSTANT E
260 CONSTANT H
261 CONSTANT L
262 CONSTANT (HL)
263 CONSTANT A
264 CONSTANT (IX+
265 CONSTANT (IY+
266 CONSTANT (IX)
267 CONSTANT (IY)
: B- B - ;

\ REGISTROS DOBLES .............................................

268 CONSTANT AF
269 CONSTANT BC
270 CONSTANT DE
271 CONSTANT HL
272 CONSTANT SP
273 CONSTANT IX
274 CONSTANT IY
275 CONSTANT (C)

: BC- BC - ;

\ FLAGS ........................................................

275 CONSTANT NZ
276 CONSTANT Z
277 CONSTANT NC
278 CONSTANT C
279 CONSTANT PO
280 CONSTANT PE
281 CONSTANT P
282 CONSTANT M

: NZ- NZ - ;

\ PROVOCAR ERRORES .............................................

: ERR_REGI   041 DUP ?ERROR ;
: ERR_PIL    040 DUP ?ERROR ;
: ?ERR_REG   0= 038 ?ERROR ;
: ERR_REG    0 ?ERR_REG ;

\ COMPROBAR RANGOS .............................................

: ENTRE?     ( n,min,max--n,f)
             2 PICK >= SWAP 2 PICK <= AND ;
: A-(IY+?    B (IY+ ENTRE? ;
: A-L?ERR    B A ENTRE? OVER (HL) <> AND ?ERR_REG ;
: A-(HL)?ERR B A ENTRE? ?ERR_REG ;
: BC-IY?ERR  BC IY ENTRE? ?ERR_REG ;
: HL-IY?ERR  HL IY ENTRE? OVER SP <> AND ?ERR_REG ;
: 0-7?ERR    0 7 ENTRE? NOT 39 ?ERROR ;
: 8BITS?     A-(IY+? IF 1 ELSE BC-IY?ERR 0 ENDIF ;
: PORT?ERR   0 255 ENTRE? 044 ?ERROR ;

\ ENTRADA/SALIDA ...............................................

: IND           170 EDOO ;
: INI           162 EDOO ;
: INIR          172 EDOO ;
: INDR          186 EDOO ;
: OTDR          187 EDOO ;
: OTIR          179 EDOO ;
: OUTD          171 EDOO ;
: OUTI          163 EDOO ;

: IN DUP (C) = IF DROP A-L?ERR B- 8* 064 + EDOO
               ELSE SWAP A = ?ERR_REG 0 255 ENTRE? 43 ?ERROR
                    219 OOXX
               ENDIF
  ;
: OUT           IF
                     ELSE SWAP A = IF PORT?ERR 211 211 OOXX
                                   ELSE ERR_REG
                                   ENDIF
                     ENDIF
                     ;

\ GIROS/CAMBIOS ................................................

: CASE(RI+
  CASE
    (IX+ OF DDCBXXOO ENDOF
    (IY+ OF FDCBXXOO ENDOF
    ERR_REGI
  ENDCASE
  ;

: GIRO
  DEPTH2/
  CASE
    2 OF SWAP                   ( OPC_B,REG)
         A-(HL)?ERR
         B-                     ( OPC_B,NRE)
         +                      ( OPC_R)
         CBOO ENDOF
    3 OF 6 +                    ( REG,DESP,OPC_R)
         ROT                    ( DESP,OPC_R,REG)
         CASE(RI+ ENDOF
    ERR_PIL
    ENDCASE
  ;

: RL    016 GIRO ;
: RLA   023 OO ;
: RLC   000 GIRO ;
: RLCA  007 OO ;
: RLD   111 EDOO ;
: RR    024 GIRO ;
: RRA   031 OO ;
: RRC   008 GIRO ;
: RRCA  015 OO ;
: RRD   103 EDOO ;
: SLA   032 GIRO ;
: SRA   040 GIRO ;
: SRL   056 GIRO ;

\ BITS .........................................................

: BSRT
  DEPTH2/
  CASE
  3 OF SWAP A-(HL)?ERR          ( BIT,OPC_B,REG)
       B-                       ( BIT,OPC_B,NREG)
       +                        ( BIT,OPC_R)
       SWAP 0-7?ERR             ( OPC_R,BIT)
       8 * +                    ( OPC_RB)
       CBOO ENDOF
  4 OF 6 + 3 ROLL 0-7?ERR       ( REG,DESP,OPC_B,BIT)
       8 * +                    ( REG,DESP,OPC_IB)
       ROT                      ( DESP,OPC_IB,REG)
       CASE(RI+ ENDOF
  ERR_PIL
  ENDCASE
  ;

: BIT 064 BSRT ;

: RES 128 BSRT ;

: SET 192 BSRT ;

\ CONTROL/ARITMÉTICA GENERAL ...................................

: CCF   063 OO ;
: CPL   047 OO ;
: DAA   039 OO ;
: DI    243 OO ;
: EI    251 OO ;
: HALT  118 OO ;
: IM CASE 0 OF 070 EDOO ENDOF
          1 OF 086 EDOO ENDOF
          2 OF 094 EDOO ENDOF 42 DUP ?ERROR ENDCASE ;
: NE    068 EDOO ;
: NOP   000 OO ;
: SCF   055 OO ;

\ INTERCAMBIO/BLOQUES ..........................................

: EX_DE,HL      235 OO ;
: EX_AF,AF      008 OO ;
: EXX           217 OO ;
: EX(SP), HL-IY?ERR 227 SWAP
  CASE HL OF OO ENDOF IX OF DDOO ENDOF IY OF FDOO ENDOF ERR_REG
  ENDCASE ;
: LDD   168 EDOO ;
: LDDR  184 EDOO ;
: LDI   160 EDOO ;
: LDIR  176 EDOO ;
: CPP   169 EDOO ;
: CPDR  185 EDOO ;
: CPI   161 EDOO ;
: CPIR  177 EDOO ;

\ LÓGICAS ......................................................

: LOGIC
  DEPTH2/
  CASE
  2 OF SWAP                     ( OPC_B,REG/N)
       DUP                      ( OPC_B,REG/N,REG/N)
       B <                      ( OPC_B,REG/N,FLAG)
       IF                       ( OPC_B,N)
         SWAP                   ( N,OPC_B)
         070 +                  ( N,OPC_N)
         OOXX
       ELSE A-(HL)?ERR          ( OPC_B,REG)
         B- +                   ( OPC_R)
         OO
       ENDIF ENDOF

  3 OF                          ( REG,DESP,OPC_B)
       6 +                      ( REG,DESP,OPC_I)
       ROT                      ( DESP,OPC_I,REG)
       CASE                     ( DESP,OPC_I)
         (IX+ OF DDOO ENDOF
         (IY+ OF FDOO ENDOF
         ERR_REGI
       ENDCASE ENDOF
  ERR_PIL
  ENDCASE
  ;

: AND   160 LOGIC ;

: CP    184 LOGIC ;

: OR    176 LOGIC ;

: XOR   168 LOGIC ;

\ SALTOS, LLAMADAS Y RETORNOS ..................................

: RST 8 / 0 7 ENTRE? 42 ?ERROR 8* 199 + OO ;

: RETN 069 OO ;
: RETI 077 OO ;
: RET
  DEPTH2/
  CASE
    0 OF 201 OO ENDOF
    1 OF FLAG?ERR NZ- 8* 192 + ENDOF
    ERR_PIL
  ENDCASE
  ;

: JP
  DEPTH2/
  CASE
    1 OF 024 JRXX ENDOF
    2 OF SWAP NZ C ENTRE? 43 ?ERROR
         NZ- 8* 032 + JRXX ENDOF
    ERR_PIL
  ENDCASE
  ;

: JR
  DEPTH2/
  CASE
    1 OF DUP (HL) = IF DROP 233 OO ENDIF
         DUP (IX) = IF DROP 233 DDOO ENDIF
         DUP (IY) = IF DROP 233 FDOO ENDIF
         195 OOXXXX ENDOF
    2 OF SWAP
         FLAG?
         NZ- 8* 194 + OOXXXX ENDOF
    ERR_PIL
  ENDCASE
  ;

: DJNZ 016 JRXX ;

: CALL
  DEPTH2/
  CASE
    1 OF 205 OOXXXX ENDOF
    2 OF SWAP
         FLAG?
         NZ- 8* 196 + OOXXXX ENDOF
    ERR_PIL
  ENDCASE
  ;

\ PUSH/POP ....................................................

: PUSHPOP ( REG,OPC_B)
  SWAP    ( OPC_B,REG)
  CASE
    AF OF 241 + OO      ENDOF
    BC OF 193 + OO      ENDOF
    DE OF 209 + OO      ENDOF
    HL OF 225 + OO      ENDOF
    IX OF 225 + DDOO    ENDOF
    IY OF 225 + FDOO    ENDOF
    ERR_REG
  ENDCASE
  ;
: PUSH 4 PUSHPOP ;
: POP 0 PUSHPOP ;

\ INC/DEC ......................................................

: ID08 ( REG,OPC_B)
  SWAP ( OPC_B,REG)
  A-(HL)?ERR
  B- 8 * + OO
  ;

: ID16 ( REG,OPC_B)
  SWAP ( OPC_B,REG)
  DUP IX = IF DROP 032 + DDOO ENDIF
  DUP IY = IF DROP 032 + FDOO ENDIF
  BC-IY?ERR
  BC- 16 * + OO
  ;

: IDCASE(RI+ ( REG_I,DESP,OPC_B)
  ROT        ( DESP,OPC_B,REG_I)
  CASE
    (IX+ OF 053 + DDOOXX ENDOF
    (IY+ OF 053 + FDOOXX ENDOF
    ERR_REGI
  ENDCASE
  ;

: DEC
  DEPTH2/ CASE 2 OF 0 IDCASE(RI+   ENDOF
               1 OF 8BITS?
                    IF    005 ID08
                    ELSE  011 ID16
                    ENDIF          ENDOF ERR_PIL ENDCASE
  ;
: INC
  DEPTH2/ CASE 2 OF 1 IDCASE(RI+   ENDOF
               1 OF 8BITS?
                    IF    004 ID08
                    ELSE  003 ID16
                    ENDIF          ENDOF ERR_PIL ENDCASE
  ;

\ ADD/ADC ......................................................

: ADD/C_A(RI+ ( REG1,RI+,DESP,OPC_B)
  3 ROLL
  ACUMULADOR? ( RI+,DESP,OPC_B)
  134 +       ( RI+,DESP,OPC)
  ROT         ( DESP,OPC,RI+)
  CASE
    (IX+ OF DDOO ENDOF
    (IY+ OF FDOO ENDOF
    ERR_REGI
  ENDCASE
  ;

: ADD/C_16 ( REG2,OPC_B,REG1) ROT SWAP ( OPC_B,REG2,REG1)
  CASE HL OF CASE BC OF 009 + OO   ENDOF
                  DE OF 025 + OO   ENDOF
                  HL OF 041 + OO   ENDOF
                  SP OF 057 + OO   ENDOF ERR_REG ENDCASE ENDOF
       IX OF CASE BC OF 009 + DDOO ENDOF
                  DE OF 025 + DDOO ENDOF
                  IX OF 041 + DDOO ENDOF
                  SP OF 057 + DDOO ENDOF ERR_REG ENDCASE ENDOF
       IY OF CASE BC OF 009 + FDOO ENDOF
                  DE OF 025 + FDOO ENDOF
                  IY OF 041 + FDOO ENDOF
                  SP OF 057 + FDOO ENDOF ERR_REG ENDCASE ENDOF
  ERR_REG ENDCASE ;

: ADD/C_A ( REG2,OPC_B)
  SWAP    ( OPC_B,REG2)
  A-(HL)?
  IF
    B- + OO
  ELSE
    198 OOXX
  ENDIF
  ;

: ADD/C ( ...OPC_B)
  DEPTH2/
  CASE
    3 OF                               ( REG1,REG2,OPC_B)
         ROT                           ( REG2,OPC_B,REG1)
         DUP A = IF   DROP ADD/C_A
                 ELSE ADD/C_16 ENDIF ENDOF
    4 OF                               ( REG1,RI+,DESP,OPC_B)
         ADD/C_A(RI+ ENDOF
    ERR_PIL
  ENDCASE
  ;
: ADD 000 ADD/C ; \ XXX TODO
: ADC 000 ADD/C ; \ XXX TODO

Descarga

Todas las versiones del programa pueden descargarse desde la sección de descargas de su página principal.