Document fait avec Nvu Document made with Nvu




Coeurs FORTH 16 et 32 bits

Version 2.0 du 2 Avril 2006
Les particularités du coeur 16 bits sont de couleur rouge
Les particularités du coeur 32 bits sont de couleur verte
Ecrit par jpb.forth

Table des registres
Format des registres
Table des instructions
Format des instructions
Instructions supplémentaires au F21
Initialisation
Interruptions
Code des instructions FORTH de base (coeur 16 bits)
Périphériques internes

Introduction

Le processeur FORTH présenté ici est basé sur le jeu d'instructions du F21 réalisé par la société Ultra Technology (5 bits) avec un bus de données 16 bits et un bus d'adresse 21 bits extensible à 32 (le bit A0 est toujours nul). Les piles de données et de retour sont intégrées au format 16 32 bits.

Les accès à la mémoire peuvent s'effectuer en mode 16 bits sur les adresses paires uniquement (bit A0 ignoré) ou en mode octet (8 bits) sachant que les bits 0 à 7 du bus des données(respectivement 8 à 15) sont sélectionnés lorsque le bit A0 est à 1 (respectivement à 0). Le mode d'accès est défini par l'état d'un bit de contrôle spécifique (bit B) et est initialisé à 16 bits. Lors d'accès à la mémoire externe, seuls les 16 bits de poids faibles de la pile de données sont tranférés. Les 16 bits de poids forts sont forcés à 0 en lecture, une instruction spécifique permet d'étendre le signe sur 32 bits.

Une zone de 65536 registres d'extensions maximum donne un accès indirect aux registres internes du processeur e aux périphériques intégrés afin d'optimiser les échanges avec ceux-ci.


Table des registres

Tous les registres sont définis sur 16 bits sauf précision:

Registres des données
Registres d'extension
Registres des adresses


PC (21 à 32 bits)

Page A (5 à 16 bits) PA
A (16 32 bits)
T (16 32 bits)
S (16 32 bits)
Pile des données
(254 éléments)
...

Page R (5 à 16 bits) PR

 

R (16 32 bits)
Pile de retour
(255 éléments)
...

Pointeurs des piles

Adresse de T PNTT
Adresse de R PNTR

Contrôle/Etat CE
CCCCCCCCCCCCCCCC
C
I
M
B
S
...
EMU MT

Interruption

Sauvegarde A
SA (16 32 bits)
Sauvegarde Page A SPA
Sauvegarde Page R SPR
Sauvegarde Contrôle/Etat SCE

Interfaces intégrés
TIMER
UART_BAUD
UART_CTRL
UART_DATA
Futurs interfaces
...

Image pile des données
(16 32 bits)

...
...
T
S
...
...

Image pile de retour
(16 32 bits)

...
...
R
...
...


Numéros des registres d'extension:

Numéro Registre
0 PA espace libre
1 PR espace libre
2 PNTT (512 à 767)
3 PNTR (768 à 1023)
4 CE
5 SA (16 32 bits)
6 SPA espace libre
7 SPR espace libre
8 SCE
9 à 255 espace libre
256
TIMER
257
UART_BAUD
258
UART_CTRL
259
UART_DATA
260 à 511 espace libre
512 à 767
Pile des données (16 32 bits)
768 à 1023
Pile de retour (16 32 bits)
1024 à 65535
espace libre

Format des registres

Le processeur est optimisé pour un bus de données de 16 bits et un bus d'adresse de 21 extensible à 32 bits. Le bit de poids faible du bus d'adresse (bit 0) permet au logiciel de différencier les octets pairs (bit 0 = 0) des octets impairs (bit 1 = 1) ce qui implique que cette information soi toujours présente dans les registres d'adresse. Ce bi est ignoré par les instruction lors d'accès à la mémoire qui demeure toujours sur 16 bits (le signal A0 ne sort pas du processeur). Les post incrémentations sont réalisées sur le bit 1 ce qui correspond à une addition de 2 au registre. Les instructions C@ et C! son émulées à partir des instructions du processeur (voir le code des instructions FORTH de base).

Le compteur de programme ou PC ne tient pas compte du bi 0. Les instructions sont toujours alignées sur les octets pairs qui constituent les bits 8 à 15 de ces dernières. Le PC est incrémenté de 2 unités à chaque nouvelle ligne de code (1 unité pour le bit 1). Les instructions de sauts relatifs ont un déplacement toujours multiple de 2.

Les registres d'extensions, tous de largeur 16 bits sauf A et les piles de données et de retour qui sont sur 32 bits, sont placés dans un espace mémoire spécifique du processeur pouvant s'étendre jusqu'à 65536 registres. Dans ce cas, le bit 0 est pris en compte car il n'y a pas d'accès possible à ces registres sous forme d'octet. Les bits 16 à 31 sont la copies du bit 15 (signe) dans le cas des registres 16 bits. Si leur contenu n'est que de 8 bits (octet de l'UART par exemple), ils sont placés sur les 8 bits de poids faibles du mot (bit 0 à 7) et les 8 24 bits de poids forts auront la valeur du bit 7 pour facilité le test du bit de signe.

Voici la représentation des formats des différents registres vis-à-vis des bus de données et d'adresses:

Bus de données
D15
D14
D13
D12
D11
D10
D9
D8
D7
D6
D5
D4
D3
D2
D1
D0

Registres de données (T, S et pile des données)
D31
D30
D29
D28
D27
D26
D25
D24
D23
D22
D21
D20
D19
D18
D17
D16
D15
D14
D13
D12
D11
D10
D9
D8
D7
D6
D5
D4
D3
D2
D1
D0

Registre Contrôle/Etat
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
C
I
M
B
S
-
-
-
-
-
-
-
-
-
EMU
MT
C correspond à la retenue (Carry)
I correspond à l'état de l'interruption (1 pour interruption en cours)
M correspond au masque d'interruption (1 pour interruption masquée)
B correspond au mode d'accès (1 pour octet et 0 pour mo de 16 bits)
S correspond à la disposition mémoire vive/mémoire morte (1 pour mémoire vive en 0x00000000)
MT indique si le code 19 est mulu lorsqu'il vaut 1 ou addc lorsqu'il vaut 0
EMU indique que le coeur est en émulation sous UNIX lorsqu'il vaut 1

Registres d'adresses (A, R et pile de retour)
A31
A30
A29
A28
A27
A26
A25
A24
A23
A22
A21
A20
A19
A18
A17
A16
A15
A14
A13
A12
A11
A10
A9
A8
A7
A6
A5
A4
A3
A2
A1
A0
Les bits A0 à A15 de la pile de retour sont aussi A16 à A31 pour les poids forts du PC en appel et retour de sous programme
(utilisation de la pile sur 2 niveaux par les instructions call, calla et ret)

L'état du bit A0 est ignoré lorsque le processeur est en mode d'accès sur 16 bits (B = 0)

Registres de pages (PA e PR)
A31
A30
A29
A28
A27
A26
A25
A24
A23
A22
A21
A20
A19
A18
A17
A16
A21 à A31 sont présents dans l'extension 32 bits

Compteur de programme PC
A31
A30
A29
A28
A27
A26
A25
A24
A23
A22
A21
A20
A19
A18
A17
A16
A15
A14
A13
A12
A11
A10
A9
A8
A7
A6
A5
A4
A3
A2
A1
A0
A0 est toujours à 0
A21 à A31 sont présents dans l'extension 32 bits

Table des instructions

Code Nom Description FORTH Retenue(C)
00000 jmp Branchement relatif inconditionnel ELSE inchangée
00001 jz Branchement relatif si T est égal à 0 DUP IF inchangée
00010 call Empilement de PC dans R (2 niveaux) et branchement relatif : inchangée
00011 jnc Branchement relatif si retenue est égale à 0 CARRY? IF inchangée
00100 fcw Lecture du registre d'extension pointé par R (16 bits de poids faibles) dans T, le pointeur est ensuite dépilé indéfini inchangée
00101 stcw Ecriture de T dans le registre d'extension pointé par R (16 bits de poids faibles), le pointeur est ensuite dépilé indéfini inchangée
00110 ret Dépilement de PC depuis R (2 niveaux) ; inchangée
00111 iret Dépilement de PC depuis R (2 niveaux) et récupération des registres sauvegardés par l'interruption indéfini récupérée
01000 ftchrp SI B = 1
ALORS lecture de l'octet pointé par [Page R, R] [R] et incrémentation par 1 de [Page R, R] [R]
SINON lecture du mot de 16 bits pointé par [Page R, R] [R] e incrémentation par 2 de [Page R, R] [R]
Les 16 bits de poids forts de T sont forcés à 0
BIT@
IF
 R@ C@
 R> 1+ >R
ELSE
 R@ @
 R> 2+ >R
THEN
inchangée
01001 ftchap SI B = 1
ALORS lecture de l'octet pointé par [Page A, A] [A] et incrémentation par 1 de [Page A, A] [A]
SINON lecture du mot de 16 bits pointé par [Page A, A] [A] et incrémentation par 2 de [Page A, A] [A]
Les 16 bits de poids forts de T sont forcés à 0
BIT@
IF
 A @ C@
 1 A +!
ELSE
 A @ @
 2 A +!
THEN
inchangée
01010 lit Lecture du mot pointé par PC et incrémentation par 2 de PC. Seuls les 16 bits de poids faibles de T sont chargés, les 16 bits de poids forts sont forcés à 0 LITERAL mise à zéro
01011 ftcha SI B = 1
ALORS lecture de l'octet pointé par [Page A, A] [A]
SINON lecture du mot de 16 bits pointé par [Page A, A] [A]
Les 16 bits de poids forts de T sont forcés à 0
BIT@
IF
 A @ C@
ELSE
 A @ @
THEN
inchangée
01100 strp SI B = 1
ALORS écriture de l'octet à l'adresse pointée par [Page R, R] [R] et incrémentation par 1 de [Page R, R] [R]
SINON écriture du mot de 16 bits à l'adresse pointée par [Page R, R] [R] et incrémentation par 2 de [Page R, R] [R]
Les 16 bits de poids forts de T sont forcés à 0
BIT@
IF
 R@ C!
 R> 1+ >R
ELSE
 R@ !
 R> 2+ >R
THEN
inchangée
01101 stap SI B = 1
ALORS écriture de l'octet à l'adresse pointée par [Page A, A] [A] et incrémentation par 1 de [Page A, A] [A]
SINON écriture du mot de 16 bits à l'adresse pointée par [Page A, A] [A] et incrémentation par 2 de [Page A, A] [A]
Les 16 bits de poids forts de T sont forcés à 0
BIT@
IF
 A @ C!
 1 A +!
ELSE
 A @ !
 2 A +!
THEN
inchangée
01110 swi
swab
Interruption logicielle
Permutation des 16 bits de poids forts avec les 16 bits de poids fables de T
indéfini
SWAB
inchangée
01111 sta SI B = 1
ALORS écriture de l'octet à l'adresse pointée par [Page A, A]
SINON écriture du mot de 16 bits à l'adresse pointée par [Page A, A]
BIT@
IF
 A @ C!
ELSE
 A @ !
THEN
inchangée
10000 com complément à 1 de T -1 XOR inchangée
10001 rolc Rotation à gauche de T avec C CARRY?
IF
 2* 1 OR
ELSE
 2*
THEN
bit 15 31 de T
10010 rorc Rotation à droite de T avec C CARRY?
IF
2/ 32768 2147483648
 OR
ELSE
2/ 32767 2147483647
 AND
THEN
bit 0 de T
10011
MT=0
addc Addition de S à T si le bit 0 de T est à 1 DUP 1 AND
IF
OVER +
THEN
calculée
10011
MT=1
mulu Multiplication non signée de T par R (16x16 32x32 bits) dans R;T (32 64 bits avec poids forts dans R) R> U* >R inchangée
10100 xorr Ou exclusif de S et de T dans T XOR inchangée
10101 andd Et logique de S et de T dans T AND inchangée
10110 ...
sxt
Réserve pour application future
Extension du bit de signe (15) sur les bits 16 à 31
...
DUP 32768 AND
IF
-32768 OR
ELSE
32767 AND
THEN
...
inchangée
10111 addd Addition de S et de T dans T + calculée
11000 pop Dépilement de R dans T R> inchangée
11001 popa Empilement de A dans T A @ inchangée
11010 dup Empilement de T dans T DUP inchangée
11011 over Empilement de S dans T OVER inchangée
11100 push Empilement de T dans R >R inchangée
11101 pusha Dépilement de T dans A A ! inchangée
11110 nop Délai d'un cycle machine NOP inchangée
11111 drop Dépilement de T DROP inchangée
 -
calla Empilement de PC dans R (2 niveaux) et saut à une adresse 32 bits en absolu : inchangée

BIT@ représente une pseudo instruction FORTH qui effectue la lecture de l'état du bit B dans le registre CE
A représente une pseudo variable FORTH destinée à contenir une adresse

Format des instructions

Les instructions sont définies dans une ligne de code constituée de 16 bits. Il y a 3 types de lignes de code:

Ligne avec 1 à 3 instructions:

Bit 15

Bit 0

Instruction 1 (5 bits) Instruction 2 (5 bits)
Instruction 3 (5 bits)
0

Dans le cas des instructions ret, iret et swi, si elles se trouvent en instruction 1 (respectivement instruction 2) les instructions 2 et 3 (respectivement 3) seront ignorées.

L'argument de l'instruction lit est placé dans le mot suivant.

Ligne avec 1 instruction de branchement relatif (jmp, jz, call et jnc):

Bit 15

Bit 0

Instruction (5 bits)
Déplacement signé (10 bits)
0

Le bit de poids forts du déplacement ou bit de signe (10) est étendu au bits 15 à 11 et à la page avant d'être ajoutés au registre PC (uniquement lorsque la condition est réalisée pour les instructions jz et jnc). Le déplacement est multiple de 2 et s'étend de -2048 à +2046 en octets (-1024 à +1024 en mots de 16 bits). Un déplacement de 0 correspond à la ligne suivante de l'instruction de saut.

Ligne avec 1 instruction pour appel de sous-programme en adressage absolu:

Bit 15

Bit 0

Poids faibles des adresses (A15 à A1)

1
Poids forts des adresses ou Page (A31 à A16)
Seuls les 5 bits de poids faibles (4 à 0) du second mot sont utilisés en mode d'adressage 21 bits.

Instructions supplémentaires au F21

iret

Cette instruction correspond au retour du programme d'interruption. Le PC est dépilé depuis la pile de retour (comme dans le cas de l'instruction "ret") et les registres Page A, A, Page R et CE sont remplacés par leurs équivalents sauvegardés.

fcw

Cette instruction permet d'empiler le contenu d'un registre d'extension dont le numéro (ou adresse) est contenu dans R (16 bits de poids faibles). Ce numéro est ensuite retiré de la pile de retour.

stcw

Cette instruction permet d'initialiser le contenu d'un registre d'extension avec T et dont le numéro (ou adresse) est contenu dans R (16 bits de poids faibles). Ce numéro est ensuite retiré de la pile de retour.

calla

Cette instruction permet de faire un appel de sous-programme en adressage absolu. PC est sauvegardés dans la pile de retour sur 2 niveaux et remplacé par les 2 valeurs contenues dans le code.

ftchrp, ftchap, ftcha, strp, stap et sta

Ces instructions possèdent un mode de fonctionnemen supplémentaire. Lorsque le bit B (pour "Byte") est à 0, les données sont transférées entre le bus externe et le registre T sur 16 bits (poids faibles) indépendamment de l'état du bi 0 des registres d'adresses. Lorsque le bit B est à 1, les données sont transférées sur 8 bits (octets) et selon la méthode suivante:

En lecture, si le bit 0 du registre d'adresse est à 0, les bits 15 à 8 du bus des données sont transférés dans les bits 7 à 0 de T. Si le bit 0 du registre d'adresse est à 1, les bits 7 à 0 du bus des données sont transférés dans les bits 7 à 0 de T. Les bits 15 à 8 du de T prennent la valeur du bit 7 afin de propager le bit de signe de l'octet lu (-256 à +255). Les bits 31 à 16 de T prennent la valeur du bit 15 pour les registres 16 bits.

En écriture, si le bit 0 du registre d'adresse es à 0, les bits 7 à 0 de T sont transférés dans les bits 15 à 8 du bus des données. Si le bi 0 du registre d'adresse est à 1, les bits 7 à 0 de T sont transférés dans les bits 7 à 0 du bus des données.

swi

Cette instruction permet de déclencher une interruption logicielle. Le PC est empilé dans la pile de retour (comme pour un "call") et les registres Page A, A, Page R et CE sont copiés dans leurs équivalents sauvegardés, le masque M est activé (mis à 1) et le bit B est mis à 0 (accès en mode 16 bits).

swab

Cette instruction permet de permuter les 16 bits de poids forts de T avec les 16 bits de poids faibles.

rolc et rorc

Ces deux instructions remplacent "shl" et "shr". Elles permettent d'étendre plus efficacement les opérations de décalage sur des nombres supérieurs à 16 32 bits (32, 48, ...). "shl" pourra être émulée par la séquence "dup addd" équivalent à l'instruction FORTH "2*" et "shr" par "dup rolc drop rorc" équivalen à "2/".

mulu

Cette instruction remplace addc lorsque MT=1. MT est le bit 0 du registre d'extension CE et à lecture seule, c'es une indication dépendante de l'implémentation du coeur. L'instruction mulu fait une multiplication non signée de T par R et place les 16 32 bits de poids forts du résulta dans R et les 16 32 bits de poids faible dans T.

sxt

Cette instruction étend le bit de signe (bit 15) de T sur ses 16 bits de poids forts.


Initialisation

Lorsque le signal RESET est appliqué au processeur, il se trouve en mode initialisation qui agit sur les différents registres de la manière suivante:

- PNTT pointe la base de la pile des données (512),
- PNTR pointe la base de la pile de retour (768),
- PA est mis à zéro,
- PR est mis à zéro,
- A est mis à zéro,
- C est mis à zéro,
- M est mis à 1 pour masquer les interruption,
- B est mis à zéro pour l'accès en mode 16 bits,
- PC est mis à zéro,
- S est mis à zéro pour placer la mémoire morte en 0x00000000 (mémoire vive en 0xFFF00000),
- MT dépend de l'architecture du coeur, 1 pour l'instruction mulu et 0 pour l'instruction addc (code 19),
- EMU est mis à 1 si le coeur est émulé sous UNIX.

A la fin de l'activation du signal RESET, le processeur démarre à l'adresse 0x00000000. Le programmeur dispose alors de 8 lignes de code (vecteur d'interruption placé à l'adresse 0x00000010) permettant une petite initialisation logicielle suivie du saut à l'adresse du programme principal.

Un signal de programmation marérielle externe (XMODEM) permet d'activer (lorsque XMODEM = 0) l'accès à la mémoire morte de 0x00000000 à 0x000001FF (512 octets ou 256 mots de 16 bits) afin que le processeur démarre sur une séquence de téléchargement du logiciel à partir de l'UART sous protocole XMODEM. Cette séquence effectue un saut à l'adresse 0xFFF00000 à la fin du transfert (le logiciel a donc été téléchargé à cette même adresse). Le processeur détecte une lecture à l'adresse 0xFFFXXXXX et inhibe alors l'accès à la mémoire morte pour laisser apparaître la mémoire FLASH.

L'émetteur est le système hôte (PC, MAC ou autre) et le récepteur est le processeur. La vitesse de l'UART est initialisée à 9600 Bauds.


Interruptions

Voici la liste des vecteurs d'interruption:

Vecteur (adresse) Interruption 
0x00000000  RESET (initialisation) 
0x00000010 Fonctions périphériques
0x00000020 Instruction "swi"
Réserve
0x00000030 Code opératoire incorrect
0x00000040 Débordemen de la pile des données
0x00000050 Débordemen de la pile de retour

La principale interruption du processeur est celle qui es déclenchée par le signal RESET. Celui-ci provoque l'initialisation décrite dans le paragraphe correspondant.

Le processeur possède une entrée d'interruption pour les fonctions périphériques internes et externes.

L'entrée en interruption est réalisée à la fin de l'exécution de la ligne de code en cours. Le processeur empile le PC dans la pile de retour et effectue la sauvegarde des registres A, PA, PR e CE en 1 seul cycle puis positionne le masque M d'interruption à 1 (les registres de sauvegarde sont respectivement SA, SPA, SPR et SCE). Le bit B est initialisé à 0 lors de l'entrée en interruption pour permettre le fonctionnement en accès 16 bits aux données correspondan au mode par défaut du processeur. Le registre PC est chargé avec l'adresse 0x00000010 qui pointe le programme d'interruption.

Si le programmeur décide d'autoriser d'autres interruptions à ce niveau, il doit sauvegarder les registres précédemmen cités avant de démasquer les interruptions. Une fois le programme terminé, il devra remasquer les interruptions et récupérer les registres précédants avant de lancer l'instruction iret.

Ceci permet de réduire au minimum le temps de réponse du processeur à une interruption.

L'instruction "swi" déclenche une interruption logicielle dont le vecteur est l'adresse 0x00000020. Cette interruption est exécutée quelque soit l'éta du masque M.

Une interruption est automatiquement déclenchée sur détection d'un code opératoire erroné. Le vecteur de cette interruption est 0x00000030.

Les piles des données et de retour ont une taille limités à 256 mots de 16 32 bits chacune. Leur initialisation positionne leur pointeur à 0x0200 (données) et 0x0300 (retour). Chaque insertion provoque une décrémentation du pointeur. Chaque extraction provoque une incrémentation du compteur. Une interruption est générée lorsque les 8 bits de poids faibles des compteurs passent de 0xFF à 0x00 en cas d'insertion ou de 0x00 à 0x01 en cas d'extraction. Les vecteurs sont 0x00000040 pour la pile des données et 0x00000050 pour la pile de retour.


Code des instructions FORTH de base (coeur 16 bits)

Voici l'implémentation des instructions FORTH de base avec le code machine du coeur en 16 bits:

( Evaluation des acces aux registres d'extension.
  Version 1.00 du 11 Novembre 2001.
  Ecrit par jpb.forth .
)

TELECHARGEMENT

RAZ_ASSEMBLEUR

ASSEMBLEUR
; Evaluation des acces aux registres d'extension.
; Version 1.00 du 11 Novembre 2001
; Ecrit par jpb.forth
;
; Declaration des registres d'extension
; =====================================
;
; Registres de pages
;
PA    EQU    0    ; page pour registre A
PR    EQU    1    ; page pour registre R
;
; Pointeurs des piles
;
PNTT    EQU    2    ; pointeur pile des donnees
PNTR    EQU    3    ; pointeur pile de retour
;
; Controle/Etat
;
CE    EQU    4    ; controle/etat
;
; Masques des differents bits du registre CE
;
MSQC    EQU    %1000000000000000    ; retenue
MSQI    EQU    %0100000000000000    ; etat inter.
MSQM    EQU    %0010000000000000    ; masque inter.
MSQB    EQU    %0001000000000000    ; mode octet
MSQS    EQU    %0000100000000000    ; select. memoire
;
; Sauvegardes interruption
;
SA    EQU    5    ; sauvegarde registre A
SPA    EQU    6    ; sauvegarde page A
SPR    EQU    7    ; sauvegarde page R
SCE    EQU    8    ; sauvegarde controle/etat
;
; Interfaces integres
;
TIMER    EQU    256    ; timer
UBAUD    EQU    257    ; vitesse UART
UCTRL    EQU    258    ; controle UART
UDATA    EQU    259    ; donnees UART
;
; Images des piles
;
DSTACK    EQU    512    ; pile des donnees
RSTACK    EQU    768    ; pile de retour
;
    ORG    0
;
RESET    JMP    TEST    ; Initialisation
;
    ORG    16
;
IRQ    IRET        ; Interruption materielle
;
    ORG    32
;
SWI    IRET        ; Interruption logicielle
;
    ORG    48
;
INSTERR    IRET        ; Instruction illegale
;
    ORG    64
;
DSERR    IRET        ; Debordement pile des donnees
;
    ORG    80
;
RSERR    IRET        ; Debordement pile de retour
;
    ORG    128
;
; Instructions de base
; ====================
;
DUP    DUP        ; n --> n,n
    RET
;
DROP    DROP        ; n --> -
    RET
;
SWAP    PUSH        ; n1,n2 --> n2,n1
    PUSHA        ; equivalent a "2 ROLL"
    POP
    POPA
    RET
;
OVER    OVER        ; n1,n2 --> n1,n2,n1
    RET
;
ROT    PUSH        ; n1,n2,n3 --> n2,n3,n1
    PUSH        ; equivalent a "3 ROLL"
    PUSHA
    POP
    POP
    POPA
    RET
;
PDIDUP    JZ    PDIDUP1    ; ?DUP n --> n,n ou 0
    DUP
PDIDUP1    RET
;
SR    PUSHA        ; >R n --> -
    POP
    POP
    POPA
    PUSH
    PUSH
    PUSH
    RET
;
RS    POP        ; R> - --> n
    POP
    POP
    PUSHA
    PUSH
    PUSH
    POPA
    RET
;
RF    POP        ; R@ - --> n
    POP
    POP
    DUP
    PUSHA
    PUSH
    PUSH
    PUSH
    POPA
    RET
;
PICK    LIT    #PNTT    ; n1 --> n2
    PUSH
    FCW
    ADDD
    PUSH
    FCW
    RET
;
POKE    LIT    #PNTT    ; n1,n2 --> -
    PUSH
    FCW
    ADDD
    PUSH
    STCW
    RET
;
ROLL    DUP        ; n --> -
    PUSH
    LIT    #PNTT
    PUSH
    FCW
    ADDD
    PUSHA
    POP
ROLLA    LIT    #-1
    ADDD
    JZ    ROLLB
    POPA
    PUSH
    FCW
    POPA
    DUP
    PUSH
    LIT    #-1
    ADDD
    DUP
    PUSHA
    PUSH
    FCW
    STCW
    POPA
    PUSH
    STCW
    JMP     ROLLA
ROLLB    DROP
    RET
;
DEPTH    LIT    #PNTT    ; n
    PUSH
    FCW
    COM
    LIT    #1
    ADDD
    LIT    #DSTACK+256
    ADDD
    RET
;           
; Multiplication non signee 8x8 --> 16 bits
;
M16    PUSH        ; n1,n2 --> n1*n2
    DUP
    ADDD
    DUP
    ADDD
    DUP
    ADDD
    DUP
    ADDD
    DUP
    ADDD
    DUP
    ADDD
    DUP
    ADDD
    DUP
    ADDD
    POP
    LIT    #255
    ANDD
    ADDC
    RORC
    ADDC
    RORC
    ADDC
    RORC
    ADDC
    RORC
    ADDC
    RORC
    ADDC
    RORC
    ADDC
    RORC
    ADDC
    RORC
    PUSH
    DROP
    POP
    RET
;           
; Multiplication non signee 16x16 --> 32 bits
;
M32    PUSH        ; n1,n2 --> (n1*n2)l,(n1*n2)h
    DUP
    DUP
    XORR
    POP
    LIT    #-1
    PUSHA        ; A = -1
    LIT    #16    ; n1,0,n2,cnt=16
M321    PUSH
    PUSH
    OVER
    RORC
    DROP
    JNC    M322
    POP
    DUP
    PUSH
    ADDD
M322    RORC
    PUSH
    RORC
    POP
    POP
    POP
    POPA
    ADDD
    JZ    M323
    JMP    M321
M323    DROP        ; (n1*n2)l,(n1*n2)h,n2,0
    DROP
    RET
;           
; Division non signee 32/16 --> 16 et 16 bits
; quotient et reste
;
D32    COM        ; nl,nh,d --> r,q
    LIT    #1    ; r = mod(nh_nl,d)
    DUP        ; q = div(nh_nl,d)
    PUSHA        ; A = 1
    ADDD       
    LIT    #16    ; nl,nh,-d,cnt=16
D321    PUSH
    PUSH
    PUSH
    DUP
    ADDD
    POP
    ROLC
    DUP
    POP   
    DUP
    PUSH
    ADDD        ; nl,nh,nh-d
    JNC    D324
    PUSH        ; si nh >= d
    DROP
    POPA
    ADDD
    POP
    POP
    JMP    D325
D324    DROP        ; si nh < d
    POP
D325    POP
    LIT    #-1    ; nl',nh',-d,cnt,-1
    ADDD
    JZ    D326
    JMP    D321
D326    DROP        ; q,r,-d,0
    DROP
    CALL    SWAP    ; r,q pour compatibilite FORTH
    RET
;
    ORG    512
;
; Vecteurs pour simulation
; le commentaire donne l'etat attendu de la pile des donnees
;
TEST    LIT    #1    ; 1
    CALL    DUP    ; 1,1
    CALL    DROP    ; 1
    CALL    DUP    ; 1,1
    CALL    OVER    ; 1,1,1
    ADDD        ; 1,2
    CALL    DUP    ; 1,2,2
    LIT    #3    ; 1,2,2,3
    CALL    PICK    ; 1,2,2,1
    ADDD        ; 1,2,3
    CALL    SWAP    ; 1,3,2
    CALL    ROT    ; 3,2,1
    CALL    SR    ; 3,2
    CALL    SWAP    ; 2,3
    CALL    RF    ; 2,3,1
    CALL    OVER    ; 2,3,1,3
    CALL    ROLL    ; 3,1,2
    CALL    ROT    ; 1,2,3
    CALL    DUP    ; 1,2,3,3
    CALL    RS    ; 1,2,3,3,1
    ADDD        ; 1,2,3,4
    LIT    #0    ; 1,2,3,4,0
    CALL    PDIDUP    ; 1,2,3,4,0
    ADDD        ; 1,2,3,4
    CALL    PDIDUP    ; 1,2,3,4,4
    LIT    #5    ; 1,2,3,4,4,5
    CALL    PICK    ; 1,2,3,4,4,1
    ADDD        ; 1,2,3,4,5
    CALL    OVER    ; 1,2,3,4,5,4
    CALL    POKE    ; 1,5,3,4
    CALL    DUP    ; 1,5,3,4,4
    CALL    PICK    ; 1,5,3,4,1
    CALL    DUP    ; 1,5,3,4,1,1
    ADDD        ; 1,5,3,4,2
    CALL    OVER    ; 1,5,3,4,2,4
    CALL    POKE    ; 1,2,3,4
    CALL    DEPTH    ; 1,2,3,4,4
    CALL    M16    ; 1,2,3,16
    CALL    M32    ; 1,2,48,0
    LIT    #2    ; 1,2,48,0,2
    CALL    D32    ; 1,2,0,24
    CALL    DUP    ; 1,2,0,24,24
    CALL    M16    ; 1,2,0,576
    CALL    SWAP    ; 1,2,576,0
    LIT    #37    ; 1,2,576,0,37
    CALL    D32    ; 1,2,21,15
    CALL    M16    ; 1,2,315
    CALL    DUP    ; 1,2,315,315
    CALL    M32    ; 1,2,33689,1
    LIT    #5    ; 1,2,33689,1,5
    CALL    D32    ; 1,2,0,19245
    CALL    M16    ; 1,2,0
    ADDD        ; 1,2
    CALLA    M32    ; 2,0
    ADDD        ; 2
    CALLA    DROP    ; -
;
    END

SIMULATION

( FIN
)

Périphériques internes

TIMER

Le rôle du TIMER est de générer une interruption régulière pour le noyau temps réel. Il est composé d'un seul registre de 16 bits placé dans la zone des registres d'extension du processeur (0x0100). Lorsque sa valeur est nulle (valeur correspondant à l'initialisation), la fonction du TIMER est inhibée. Une écriture de 1 dans le registre permet de générer une interruption toutes les 1 ms en incrémentant la valeur lue.

L'interruption est effacée par la lecture de ce même registre qui donne le nombre de tours effectués par le compteur avant que l'interruption soit servie. Cette valeur, codée sur 4 bits (D3..D0), est automatiquement remise à 0 après lecture. Les 12 28 bits de poids forts sont toujours lus à 0.

UART

L'UART permet le transfert de données entre le processeur et un ordinateur hôte. Cette interface est composée de 3 registres d'extension:

UART_BAUD (0x0101) permettant de choisir la fréquence de transmission multipliée par 16 à partir de la fréquence du processeur divisée par 13,5 (1,852 MHz). Lorsque sa valeur est de 12 (valeur correspondant à l'initialisation), la vitesse de transmission est de 9600 bauds avec une erreur de 0,47%. La valeur est codée sur 4 bits (D3..D0) permettant de choisir parmi 16 valeurs de 7200 à 115200 bauds :

Vitesse (bits/s) = Fréquence Processeur (Hz) / [13,5*16*(UART_BAUD+1)]

UART_CTRL (0x0102) qui en lecture donne accès aux différents bits d'état de l'UART et, en écriture, sert de masque d'interruption sachant que chacun des bits d'éta peut en générer une (le masque est positioné à l'initialisation):

D15
rxrdy
D14
txrdy
D13
parityerr
D12
framingerr
D11
overrun
D10
réserve
D9
réserve
D8
réserve
D7
réserve

D6 réserve

D5
réserve
D4
réserve
D3
réserve
D2
réserve
D1
réserve
D0
réserve

UART_DATA (0x0103) qui en lecture donne accès à l'octet reçu (rxrdy est remis à zéro) e en écriture permet d'envoyer un octet (txrdy est remis à zéro). L'octet est placé sur les bits D0 à D7. Les bits D8 à D15 D31 sont la copie du bit D7 en lecture.

Le format de transmission est fixé à 8 bits de données, parité impaire et 1 bit de stop.