MARC4 4-Bit Microcontroller Programmer's Guide I. Hardware Description II. Instruction Set III. Programming in qFORTH IV. qFORTH Language Dictionary V. Addresses MARC4 Programmer's Guide Table of Contents Contents I. 1 MARC4 Microcontroller . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . MARC4 Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1 General Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2 Components of MARC4 Core . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2.1 Program Memory (ROM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2.2 Data Memory (RAM) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2.3 Registers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2.4 ALU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2.5 Instruction Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2.6 I/O Bus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.2.7 Interrupt Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Software Interrupts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Hardware Interrupts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3 Reset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.4 Sleep Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.5 Peripheral Communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.5.1 Port Communication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.6 Emulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 12 12 13 13 13 14 16 17 17 18 19 20 21 21 21 21 22 II 2 Instruction Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . MARC4 Instruction Set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.1 Description of Used Identifiers and Abbreviations . . . . . . . . . . . . . . . . . . . . . . . . 2.1.2 Stack Notation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1.3 MARC4 Instruction Set Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23 25 25 27 27 32 III 3 Programming in qFORTH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Programming in qFORTH . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1 Why Program in qFORTH ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Language Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3 The qFORTH Vocabulary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3.1 Word Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4 Stacks, RPN and Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4.1 Reverse Polish Notation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4.2 The qFORTH Stacks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4.3 Stack Notation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4.4 Comments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5 Constants and Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5.1 Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Predefined Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.5.2 Look-up Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.6 Variables and Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.6.1 Defining Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 37 37 38 40 40 40 40 41 41 41 42 42 42 42 43 43 MARC4 Programmer's Guide Table of Contents Contents (continued) 3.7 3.8 3.9 3.10 3.11 3.12 3.13 Stack Allocation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.7.1 Stack Pointer Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Stack Operations, Reading and Writing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.8.1 Stack Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The Data Stack . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SWAP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DUP, OVER and DROP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ROT and , >R, R@ and DROPR . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Other Useful Stack Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.8.2 Reading and Writing (@, !) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.8.3 Low-Level Memory Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . RAM Address Registers X and Y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Bit Manipulations in RAM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . MARC4 Condition Codes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.9.1 The CCR and the Control Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Arithmetic Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.10.1 Number Systems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Single- and Double-Length Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.10.2 Addition and Subtraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.10.3 Increment and Decrement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.10.4 Mixed-Length Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.10.5 BCD Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . DAA and DAS . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.10.6 Summary of Arithmetic Words . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Logicals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.11.1 Logical Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . TOGGLE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . SHIFT and ROTATE Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Comparisons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.12.1 <,> ............................................................. 3.12.2 <= , >= . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.12.3 <> , = . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.12.4 Comparisons Using 8-bit Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Control Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.13.1 Selection Control Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . IF .. THEN . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . The CASE Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.13.2 Loops, Branches and Labels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Definite Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Indefinite Loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.13.3 Branches and Labels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 44 44 44 44 45 45 45 45 46 47 47 47 48 48 49 49 49 49 49 50 50 50 50 51 51 51 52 52 53 53 53 53 53 54 55 55 55 56 56 57 58 MARC4 Programmer's Guide Table of Contents Contents (continued) 3.13.4 4 V. Arrays and Look-up Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Array Indexing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Initializing and Erasing an Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Array Filling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Looping in an Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Moving Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Comparing Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.13.5 Look-up Tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.13.6 TICK and EXECUTE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.14 Making the Best Use of Compiler Directives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.14.1 Controlling ROM Placement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.14.2 Macro Definitions, EXIT and ;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.14.3 Controlling Stack Side Effects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.14.4 $INCLUDE Directive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.14.5 Conditional Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.14.6 Controlling XY Register Optimizations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.15 Recommended Naming Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.15.1 How to Pronounce the Symbols . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.16 Literature List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.16.1 Recommended Literature . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.16.2 Literature of General Interest . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . qFORTH Dictionary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1 Preface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3 Stack-Related Conventions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.4 Flags and Condition Code Register . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.5 MARC4 Memory Addressing Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.6 The qFORTH Language - Quick Reference Guide . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.6.1 Arithmetic/Logical . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.6.2 Comparisons . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.6.3 Control Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.6.4 Stack Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.6.5 Memory Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.6.6 Predefined Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.6.7 Assembler Mnemonics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.7 Short Form Dictionary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.8 Detailed Description of the qFORTH Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Index of "Detailed Description of the qFORTH Language" . . . . . . . . . . . . . . . . . . . . . . . . . . 58 58 58 58 59 59 59 59 59 62 62 62 62 63 63 63 64 64 66 66 66 71 71 72 75 76 77 78 78 78 79 79 80 81 81 83 93 465 Addresses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 469 I. Hardware Description II. Instruction Set III. Programming in qFORTH IV. qFORTH Language Dictionary V. Addresses MARC4 Programmer's Guide Hardware Description MARC4 Microcontroller Introduction The Atmel Wireless & Microcontrollers MARC4 microcontroller family is based on a low-power 4-bit CPU core. The modular MARC4 architecture is HARVARD like, high-level language oriented and well suitable to realize high integrated microcontrollers with a variety of application or customer-specific on-chip peripheral combinations. The MARC4 controller's low voltage and low power consumption is perfect for hand-held and battery-operated applications. The standard members of the family have selected peripheral combinations for a broad range of applications. Programming is supported by an easy-to-use PC based software development system with a high-level language qFORTH compiler and an emulator board. The stack-oriented microcontroller concept enables the qFORTH compiler to generate a compact and efficient MARC4 program code. Features D 4-bit HARVARD architecture D Low power consumption D High-level language oriented CPU D Power-down mode D 256 x 4 bit of RAM D Various on-chip peripheral combination available D Up to 9 KBytes of ROM D 8 vectored prioritized interrupt levels D Low voltage operating range 03.01 D High-level programming language qFORTH D Programming and testing is supported by an integrated software development system 11 MARC4 Programmer's Guide Hardware Description 1 1.1 MARC4 Architecture General Description The MARC4 microcontroller consists of an advanced stack-based 4-bit CPU core and application-specific, on-chip peripherals such as I/O ports, timers, counters, ADC, etc. The CPU is based on the HARVARD architecture with a physically separate program memory (ROM) and data memory (RAM). Three independent buses, the instruction-, the memory- and the I/O bus, are used for parallel communication between ROM, RAM and peripherals. This enhances program execution speed by allowing both instruction prefetching, and a simultaneous communication to the on-chip peripheral circuitry. The powerful integrated interrupt controller, with eight prioritized interrupt levels, supports fast processing of hardware events. The MARC4 is designed for the high-level programming language qFORTH. A lot of qFORTH instructions and two stacks, the Return Stack and the Expression Stack, are already implemented. The architecture allows high-level language programming without any loss of efficiency and code density. Sleep Clock Reset MARC4 CORE ROM X Y SP RP PC 256 x 4-bit II II Instruction bus Instruction decoder RAM Memory bus TOS CCR Interrupt controller ALU I/O bus I/O ports Timer Application -specific peripherals Interrupt inputs On-chip peripheral modules 94 8711 Figure 1. MARC4 core 12 03.01 MARC4 Programmer's Guide Hardware Description 1.2 Components of MARC4 Core The core contains the program memory (ROM), data memory (RAM), ALU, Program Counter, RAM Address Register, instruction decoder and interrupt controller. The following sections describe each of these parts. special subroutines accessible with single byte instructions (SCALL). The corresponding memory map is shown in figure 2. Look-up tables of constants are also stored in ROM and are accessed via the MARC4 built in TABLE instruction. 1.2.2 Program Memory (ROM) The MARC4's program memory contains the customer-application program. The 12-bit wide Program Counter can address up to 4 Kbytes of program memory. The access of program memory with more than 4 K is possible using the bank-switching method. One of 4 memory banks can be selected with bit 2 and 3 of the ROM bank register (RBR). Each ROM bank has a size of 2 Kbytes and is placed above the base bank in the upper 2 K (800h-FFFh) of the address space. This therefore enables program memory sizes of up to 10 Kbytes. 1 Kbyte of bank 3 is normally reserved for test software purposes. After any hardware reset, ROM Bank 1 is selected automatically. The program memory starts with a 512 byte segment (Zero Page) which contains predefined start addresses for interrupt service routines and MARC4 self test routines Bank 2 Bank 1 800h 7FFh 1FFh 000h Expression Stack The 4-bit wide Expression Stack is addressed with the Expression Stack Pointer (SP). All arithmetic, I/O and memory reference operations take their operands from, and return their result to the Expression Stack. The MARC4 performs the operations with the top of stack items (TOS and TOS-1). The TOS register contains the top element of the Expression Stack and works in the same way as an accumulator. This stack is also used for passing parameters between subroutines, and as a scratchpad area for temporary storage of data. 1F8h 1F0h 1E8h 1E0h Bank 4 Bank 3 FFFh The MARC4 contains a 256 x 4-bit wide static Random Access Memory (RAM). It is used for the Expression Stack, the Return Stack and as data memory for variables and arrays. The RAM is addressed by any of the four 8-bit wide RAM Address Registers SP, RP, X and Y. RBR: 11xxb RBR: 10xxb RBR: 01xxb RBR: 00xxb Basebank SCALL addresses 1.2.1 Data Memory (RAM) Zero page 020h 018h 010h 008h 000h Zero page 1E0h 1C0h 180h 140h 100h 0C0h 080h 040h INT7 INT6 INT5 INT4 INT3 INT2 INT1 INT0 008h 000h $RESET $AUTOSLEEP 94 8709 Figure 2. ROM map 03.01 13 MARC4 Programmer's Guide Hardware Description RAM (256 x 4-bit) Expression Stack 3 TOS FFh FCh 0 TOS-1 Global variables X SP TOS-2 4-bit RAM Address Register: Y Expression Stack SP TOS-1 Return Stack 11 0 RP Return Stack RP 04h 07h 00h 03h Global variables 12-bit 94 8710 Figure 3. RAM map Return Stack Program Counter (PC) The 12-bit wide Return Stack is addressed by the Return Stack Pointer (RP). It is used for storing return addresses of subroutines, interrupt routines and for keeping loop-index counters. The return stack can also be used as a temporary storage area. The MARC4 Return Stack starts with the AUTOSLEEP vector at the RAM location FCh and increases in the address direction 00h, 04h, 08h, ... to the top. The Program counter (PC) is a 12-bit register that contains the address of the next instruction to be fetched from the ROM. Instructions currently being executed are decoded in the instruction decoder to determine the internal micro-operations. The MARC4 instruction set supports the exchange of data between the top elements of the expression and the Return Stack. The two stacks within the RAM have a user-definable maximum depth. 1.2.3 Registers The MARC4 controller has six programmable registers and one condition code register. They are shown in the programming model in figure 4. 14 For linear code (no calls or branches), the program counter is incremented with every instruction cycle. If a branch, call, return instruction or an interrupt is executed, the program counter is loaded with a new address. The program counter is also used with the table instruction to fetch 8-bit wide ROM constants. RAM Address Register The RAM is addressed with the four 8-bit wide RAM address registers SP, RP, X and Y. These registers allow the access to any of the 256 RAM nibbles. 03.01 MARC4 Programmer's Guide Hardware Description 11 0 Program Counter PC 0 7 0 RP 0 Return Stack Pointer 0 7 Expression Stack Pointer SP 0 7 RAM Address Register (X) X 7 0 RAM Address Register (Y) Y 0 3 Top of Stack Register TOS 0 3 CCR C -- B I Condition Code Register Interrupt enable Branch unused Carry / Borrow 94 8707 Figure 4. Programming model Expression Stack Pointer (SP) The stack pointer (SP) contains the address of the next-to-top 4-bit item (TOS-1) of the Expression Stack. The pointer is automatically pre-incremented if a nibble is pushed onto the stack, or post-decremented if a nibble is removed from the stack. Every post-decrement operation moves the item (TOS-1) to the TOS register before the SP is decremented. After a reset, the stack pointer has to be initialized with the compiler variable S0 03.01 (" >SP S0 ") to allocate the start address of the Expression Stack area. Return Stack Pointer (RP) The Return Stack pointer points to the top element of the 12-bit wide Return Stack. The pointer automatically pre-increments if an element is moved onto the stack, or it post-decrements if an element is removed from the stack. The Return Stack Pointer increments and decrements in steps of 4. This means that every time a 12-bit element is stacked, a 4-bit RAM location is left unwritten. This location is 15 MARC4 Programmer's Guide Hardware Description used by the qFORTH compiler to allocate 4-bit variables. TOG_BF, CCR! and DI allow a direct manipulation of the Condition Code Register. To support the AUTOSLEEP feature, read and write operations to the RAM address FCh using the Return Stack Pointer are handled in a special way. Read operations will return the autosleep address 000h, whereby write operations have no effect.After a reset, the Return Stack Pointer has to be initialized with " >RP FCh ". Carry/Borrow (C) RAM Address Register (X and Y) Branch (B) The X and Y registers are used to address any 4-bit element in the RAM. A fetch operation moves the addressed nibble onto the TOS. A store operation moves the TOS to the addressed RAM location. The Branch flag controls the conditional program branching. When the Branch flag has been set by one of the previous instructions, a conditional branch is taken. This flag is affected by arithmetic, logic, shift, and rotate operations. By using either the pre-increment or post-decrement addressing mode, it is convenient to compare, fill or move arrays in the RAM. Interrupt Enable (I) Top of Stack (TOS) The Top of Stack Register is the accumulator of the MARC4. All arithmetic/logic, memory reference and I/O operations use this register. The TOS register gets the data from the ALU, the ROM, the RAM or via the I/O bus. Condition Code Register (CCR) The 4-bit wide Condition Code Register contains the branch, the carry and the interrupt enable flag. These bits indicate the current state of the CPU. The CCR flags are set or reset by ALU operations. The instructions SET_BCF, The Carry/Borrow flag indicates that the borrowing or carrying out of the Arithmetic Logic Unit (ALU) occurred during the last arithmetic operation. During shift and rotate operations, this bit is used as a fifth bit. Boolean operations have no effect on the Carry flag. The Interrupt Enable flag enables or disables the interrupt processing on a global basis. After a reset or by executing the DI instruction, the Interrupt Enable flag is cleared and all interrupts are disabled. The C does not process further interrupt requests until the Interrupt Enable flag is set again by either executing an EI, RTI or SLEEP instruction. 1.2.4 ALU The 4-bit ALU performs all the arithmetic, logical, shift and rotate operations with the top two elements of the Expression Stack (TOS and TOS-1) and returns their result to the TOS. The ALU operations affect the Carry/Borrow and Branch flag in the Condition Code Register (CCR). IIII IIIII IIII IIIII IIIII IIII IIII IIIIIII IIIII IIIII II IIIIIIII IIIIIII IIII IIIII IIIII II IIII IIIII IIIII III IIIIIIII II IIII IIIII III IIII IIIIIIII IIIII III IIIIIIII IIII IIIII RAM SP TOS-1 TOS-2 TOS-3 TOS-4 TOS ALU CCR 94 8977 Figure 5. ALU zero address operations 16 03.01 MARC4 Programmer's Guide Hardware Description 1.2.5 Instruction Set The MARC4 instruction set is optimized for the high-level programming language qFORTH. A lot of MARC4 instructions are qFORTH words. This enables the compiler to generate a fast and compact program code. The MARC4 is a zero address machine with a compact and efficient instruction set. The instructions contain only the operation to be performed but no source or destination address information. The operations are performed with the data placed on the stack. An instruction pipeline enables the controller to fetch the next instruction from ROM at the same time as the present instruction is being executed. One- and two-byte instructions are executed within 1 to 4 machine-cycles. Most of the instructions have a length of one byte and are executed in only one machine cycle. A complete overview of the MARC4 instruction set includes the table instruction set. MARC4 Instruction Timing The internal instruction timing and pipelining during the MARC4's instruction execution are shown in figure 6. The figure shows the timing for a sequence of three instructions. A machine cycle consists of two system-clock cycles. The first and second Cycle 1 Cycle 2 instruction needs one and the third two machine-cycles. 1.2.6 I/O Bus Communication between the core and the on-chip peripherals takes place via the I/O bus. This bus is used for read and write accesses, for interrupt requests, for peripheral reset and for the SLEEP mode. The operation mode of the 4-bit wide I/O bus is determined by the control signals N_Write, N_Read, N_Cycle and N_Hold. (see table I/O bus modes). During IN/OUT operations, the address and data and during an interrupt cycle the low and the high priority interrupts are multiplexed by using the N_Cycle signal. When N_Cycle is low the address respectively the low interrupts `0,1,2,3' are sent, when N_Cycle is high the data respectively the higher priority interrupts `4,5,6,7' are transfered (see figure 7). An IN operation transfers the port address from TOS (top of stack) onto the I/O bus and reads the data back on TOS. An OUT operation transfers both the port address from TOS and the data from TOS-1 onto the I/O bus. Note that the interrupt controller samples interrupt requests during the non-I/O cycles. Therefore, IN and OUT instructions may cause an interrupt delay. To minimize interrupt latency, avoid immediate consecutive IN and OUT instructions. Cycle 3 Cycle 4 Cycle 5 TCL/SYSCL ROM read Decode Execute Instr 1 Instr 2 Instr 1 Instr 3.1 Instr 2 Instr 1 Instr 3.2 Instr 4 Instr 3 Instr 2 Instr 3 94 8712 Figure 6. Instruction cycle (pipelining) 03.01 17 MARC4 Programmer's Guide Hardware Description Table 1. I/O bus modes AAAAAAAAAAA AAAAAA AAAAA AAAAA AAAAA AAAAA AAAAAAAAAAA AAAAAA AAAAA AAAAA AAAAA AAAAA AAAAAAAAAAA AAAAAA AAAAA AAAAA AAAAA AAAAA AAAAAAAAAAA AAAAAA AAAAA AAAAA AAAAA AAAAA AAAAAAAAAAA AAAAAA AAAAA AAAAA AAAAA AAAAA AAAAAAAAAAA AAAAAA AAAAA AAAAA AAAAA AAAAA AAAAAAAAAAA AAAAAA AAAAA AAAAA AAAAA AAAAA AAAAAAAAAAA AAAAAA AAAAA AAAAA AAAAA AAAAA AAAAAAAAAAA AAAAAA AAAAA AAAAA AAAAA AAAAA AAAAAAAAAAA AAAAAA AAAAA AAAAA AAAAA AAAAA Mode I/O read (address cycle) I/O read (data cycle) I/O write (address cycle) I/O write (data cycle) Interrupt 0 to 3 cycle Interrupt 4 to 7 cycle Sleep mode Reset mode N_Read 0 0 1 1 1 1 0 0 N_Write 1 1 0 0 1 1 0 0 N_Cycle 0 1 0 1 0 1 0 x N_Hold 1 x 1 1 1 1 1 0 I/O Bus x x x x x x 0 Fh TCL/SYSCL (N_Hold=1) N_Cycle OUT instruction cycle N_Write IN instruction cycle N_Read I/O bus Int0-3 Int4-7 III III III III Addr Data Int0-3 Int4-7 Figure 7. Timing for IN/OUT operations and interrupt requests The I/O bus is internal and therefore not accessible by the customer on the final microcontroller. 1.2.7 Interrupt Structure The MARC4 can handle interrupts with eight different priority levels. They can be generated from internal or external hardware interrupt sources or by a software interrupt from the CPU itself. Each interrupt level has a hard-wired priority and an associated vector for the service routine in the ROM (see table 2). The programmer can enable or disable all interrupts at once by setting or resetting the interrupt-enable flag (I) in the CCR. 18 III III IIIIII Addr Data 94 8713 Interrupt Processing To process the eight different interrupt levels, the MARC4 contains an interrupt controller with the 8-bit wide Interrupt Pending and Interrupt Active Register. The interrupt controller samples all interrupt requests on the I/O bus during every non-I/O instruction cycle and latches them in the Interrupt Pending Register. If no higher priority interrupt is present in the Interrupt Active Register, it signals the CPU to interrupt the current program execution. If the interrupt enable bit is set, the processor enters an interrupt acknowledge cycle. During this cycle, a SHORT CALL instruction to the service routine is executed and the 12-bit wide current PC is saved on the Return Stack automatically. 03.01 MARC4 Programmer's Guide Hardware Description INT7 7 INT7 active INT5 Priority level 6 5 4 3 2 AAAA AAAA AAAA AAA AAAA AAA RTI INT5 active INT3 AAA AAA INT3 active RTI AAAAA IIIIIII AAAA AAAAA IIIIIII AAAA INT2 RTI INT2 pending 1 SWI0 0 AAAAA AAAAA INT2 active RTI IIIIII AAAA IIIIII AAAA INT0 pending INT0 active RTI Main / Autosleep Main / Autosleep Time 94 8978 Figure 8. Interrupt handling An interrupt service routine is finished with the RTI instruction. This instruction sets the Interrupt Enable flag, resets the corresponding bits in the Interrupt Pending/Active Register and moves the return address from the Return Stack to the Program Counter. When the Interrupt Enable flag has been reset (interrupts are disabled), the execution of interrupts is inhibited, but not the logging of the interrupt requests in the Interrupt Pending Register. The execution of the interrupt will be delayed until the Interrupt Enable flag is set again. But note that interrupts are lost if an interrupt request occurs during the corresponding bit in the Pending Register is still set. After any hardware reset (power-on, external or watchdog reset), the Interrupt Enable flag, the Interrupt Pending and Interrupt Active Register are reset. 03.01 Interrupt Latency The interrupt latency is the time from the occurrence of the interrupt event to the interrupt service routine being activated. In the MARC4 this takes between three to five machine cycles depending on the state of the core. Software Interrupts The programmer can generate interrupts using the software interrupt instruction (SWI) which is supported in qFORTH by predefined macros named SWI0...SWI7. The software-triggered interrupt operates exactly in the same way as any hardware-triggered interrupt. The SWI instruction takes the top two elements from the Expression Stack and writes the corresponding bits via the I/O bus to the Interrupt Pending Register. Therefore, by using the SWI instruction, interrupts can be re-prioritized or lower priority processes scheduled for later execution. 19 MARC4 Programmer's Guide Hardware Description Hardware Interrupts automatically event-controlled program flow. The different vectored interrupts permit program dividing into different interrupt-controlled tasks. Hardware interrupt sources such as external interrupt inputs, timers etc. are used for fast Interrupt event INT3 TCL/SYSCL I I I I II III IIIIII IIIIII III IIIIII III III IIII III IIIIII III III IIIIII III III IIII III IIIIII IIIIII III III IIIIII III III IIII N_Cycle Interrupt request I/O bus 8 INT5 Instruction CCR! Interrupt acknowl. INT0 RTI AND LIT_5 Pending: 21h Active: 21h Interrupt register: 0 Pending: 01h Active: 01h ADD SCALL INT3 INT3 CCR@ LIT_5 LIT_E Pending: 09h Active: 01h Pending: 09h Active: 09h 94 8696 Figure 9. Interrupt request cycle Table 2. Interrupt priority table Interrupt Priority ROM Address INT0 INT1 INT2 INT3 INT4 INT5 INT6 INT7 lowest 040h 080h 0C0h 100h 140h 180h 1C0h 1E0h Interrupt Opcode (Acknowledge) C8h (SCALL 040h) D0h (SCALL 080h) D8h (SCALL 0C0h) E0h (SCALL 100h) E8h (SCALL 140h) F0h (SCALL 180h) F8h (SCALL 1C0h) FCh (SCALL 1E0h) Pending/ Active Bit 0 1 2 3 4 5 6 7 AAAAAA AAAAA AAAAAAAAA AAAAAAAAAAA AAAAA AAAAAA AAAAA AAAAAAAAA AAAAAAAAAAA AAAAA AAAAAA AAAAA AAAAAAAAA AAAAAAAAAAA AAAAA AAAAAA AAAAA AAAAAAAAA AAAAAAAAAAA AAAAA AAAAA AAAAAAAAAAA AAAAA AAAAAA AAAAAAAAA AAAAAA AAAAA AAAAAAAAA AAAAAAAAAAA AAAAA AAAAAA AAAAA AAAAAAAAA AAAAAAAAAAA AAAAA AAAAAA AAAAA AAAAAAAAA AAAAAAAAAAA AAAAA AAAAAA AAAAA AAAAAAAAA AAAAAAAAAAA AAAAA AAAAAA AAAAA AAAAAAAAA AAAAAAAAAAA AAAAA highest INT5 TCL/SYSCL Instruction IIIII IIIII I/O control bus NOP SLEEP SET_BCF SBRA $Autosleep SCALL INT5 SLEEP mode Int0-3 Int4-7 I/O bus IIII IIIIIII IIII IIIIIII Interrupt acknowledge Int0-3 IIII IIII Int4-7 Int0-3 Int4-7 Int0-3 94 8703 Figure 10. Timing sleep mode 20 03.01 MARC4 Programmer's Guide Hardware Description 1.3 Reset The reset puts the CPU into a well-defined condition. The reset can be triggered by switching on the supply voltage, by a break-down of the supply voltage, by the watchdog timer or by pulling the NRST pad to low. After any reset, the Interrupt Enable flag in the Condition Code Register (CCR), the Interrupt Pending Register and the Interrupt Active Register are reset. During the reset cycle, the I/O bus control signals are set to `reset mode', thereby initializing all on-chip peripherals. The reset cycle is finished with a short call instruction (opcode C1h) to the ROM-address 008h. This activates the initialization routine $RESET. In this routine the stack pointers, variables in the RAM and the peripheral must be initialized. 1.4 Sleep Mode The sleep mode is a shutdown condition which is used to reduce the average system power consumption in applications where the C is not fully utilized. In this mode, the system clock is stopped. The sleep mode is entered with the SLEEP instruction. This instruction sets the Interrupt Enable bit (I) in the Condition Code Register to enable all interrupts and stops the core. During the sleep mode, the peripheral modules remain active and are able to generate interrupts. The C exits the SLEEP mode with any interrupt or a reset. The sleep mode can only be kept when none of the Interrupt Pending or Active Register bits are set. The application of $AUTOSLEEP routine ensures the correct function of the sleep mode. The total power consumption is directly proportional to the active time of the C. For a rough estimation of the expected average system current consumption, the following formula should be used: 03.01 Itotal = ISleep + (IDD Tactive / Ttotal) IDD depends on VDD and fSYSCL. 1.5 Peripheral Communication All communication to and from on-chip peripheral moduls takes place via the peripheral I/O-bus. In this way the I/O does not interfere with core internal operations. Data transfer is always mastered by the core CPU. A peripheral device, if necessary, can however draw attention to itself by means of an interrupt. 1.5.1 Port Communication The MARC4 peripheral modules are I/O-mapped by using an IN or OUT instruction which in turn either inputs or outputs a 4-bit data or from one of 16 direct accessible port addresses. Before an OUT instruction is executed the port destination address and the data to be transmitted must be pushed onto the Expression Stack. Example: : TurnLED_Off 8 Port4 OUT ; TOS TOS Data TOS Addr Data Figure 11. OUT instruction - Stack effects In the case of an IN instruction only the port address needs to be pushed onto the Expression Stack. Example: : KeyPressed? KeyIn IN ; 21 MARC4 Programmer's Guide Hardware Description TOS TOS Addr the internal CPU core is inactive and the I/O buses are available via Port 0 and Port 1 to allow an external access to the on-chip peripherals. The MARC4 emulator uses this mode to control the peripherals of any MARC4 controller (target chip) and emulates the lost ports for the application. Data Figure 12. IN instruction - Stack effects For more complex peripherals please refer to the corresponding data sheets and the supplied hardware programming routines. 1.6 Emulation The basic function of emulation is to test and evaluate the customer's program and hardware in real time. This therefore enables the analysis of any timing, hardware or software problem. For emulation puposes, all MARC4 controllers include a special emulation mode. In this mode, A special evaluation chip (EVC) with a MARC4 core, additional breakpoint logic and program memory interface takes over the core function and executes the program from an external RAM on the emulator board. The MARC4 emulator can stop and restart a program at specified points during execution, making it possible for the applications engineer to view the memory contents and those of various registers during program execution. The designer also gains the ability to analyze the executed instruction sequences and all the I/O activities. Emulator target board MARC4 emulator MARC4 emulation-CPU I/O bus Trace memory Port 0 MARC4 target chip CORE I/O control Port 1 Program memory CORE (inactive) Peripherals Port 0 Control logic Port 1 Emulation control SYSCL/ TCL, TE, NRST Application-specific hardware Personal computer Figure 13. MARC4 emulation 22 03.01 I. Hardware Description II. Instruction Set III. Programming in qFORTH IV. qFORTH Language Dictionary V. Addresses MARC4 Programmer's Guide Instruction Set 2 2.1 MARC4 Instruction Set Introduction Most of the MARC4 instructions are single-byte instructions. The MARC4 is a zero address machine where the instruction to be performed contains only the operation and not the source or destination addresses of the data. Altogether, there are five types of instruction formats for the MARC4 processor. A Literal is a 4-bit constant value which is placed on the data stack. In the MARC4 native code they are represented as LIT_, where is the hexadecimal representation from 0 to 15 (0..F). This range is a result of the MARC4's 4-bit data width. The long RAM address format is used by the four 8-bit RAM address registers which can be pre-incremented, post-decremented or loaded directly from the MARC4's internal bus. This results in a direct accessible RAM address space of up to 256 x 4 bit. The 6-bit short address and the 12-bit long address formats are both used to address the byte-wide ROM via call and conditional branch instructions. This results in a ROM address space of up to 4 K x 8-bit words. The MARC4 instruction set includes both short and long call instructions as well as conditional branch instructions. The short instructions are single-byte instructions with the jump address included in the instruction. On execution, the lower 6 bits from the instruction word are directly loaded into the PC. Short call (SCALL) and short branch (SBRA) instructions are handled in different ways. SCALL jumps to one of 64 evenly distributed addresses within the zero page (from 000 to 1FF hex). The short branch instruction allows a jump to one of 64 addresses contained within the current page. Long jump instructions can jump anywhere within the ROM area. The CALL and SCALL instructions write the incremented Program Counter contents to the Return Stack. This address is loaded back to the PC when the associated EXIT or RTI instruction is encountered. Table 1. MARC4 opcode formats opcode 1) Zero address operation (ADD, SUB, etc...) 2) Literal (4-bit data) 7 6 5 4 3 2 1 0 opcode 3 2 1 0 opcode 3) Short ROM address (6-bit address, 2 cycles) 4) Long ROM address (12-bit address, 2 cycles) 5) Long RAM address (8-bit address, 2 cycles) 03.01 1 0 data 3 2 1 0 address 5 4 3 2 1 0 opcode address 3 2 1 0 11 10 9 8 7 6 5 4 3 2 1 0 opcode 7 6 5 4 3 2 1 0 address 7 6 5 4 3 2 1 0 25 MARC4 Programmer's Guide Instruction Set Table 2. Instruction set overview 00 ADD 10 SHL 20 TABLE 30 [X]@ 01 ADDC 11 ROL 21 --- 31 [+X]@ 02 SUB 12 SHR 22 >R 32 [X-]@ 03 SUBB 13 ROR 23 I 33 [>X]@ $xx 04 XOR 14 INC 24 --- 34 [Y]@ 05 AND 15 DEC 25 EXIT 35 [+Y]@ 06 CMP_EQ 16 DAA 26 SWAP 36 [Y-]@ 07 CMP_NE 17 NOT 27 OVER 37 [>Y]@ $xx 08 CMP_LT 18 TOG_BF 28 2>R 38 [X]! 09 CMP_LE 19 SET_BCF 29 3>R 39 [+X]! 0A CMP_GT 1A DI 2A 2R@ 3A [X-]! 0B CMP_GE 1B IN 2B 3R@ 3B [>X]! $xx 0C OR 1C DECR 2C ROT 3C [Y]! 0D CCR@ 1D RTI 2D DUP 3D [+Y]! 0E CCR! 1E SWI 2E DROP 3E [Y-]! 0F SLEEP 1F OUT 2F DROPR 3F [>Y]! $xx 40 CALL $0xx 50 BRA $0xx 60 LIT_0 70 SP@ 41 CALL $1xx 51 BRA $1xx 61 LIT_1 71 RP@ 42 CALL $2xx 52 BRA $2xx 62 LIT_2 72 X@ 43 CALL $3xx 53 BRA $3xx 63 LIT_3 73 Y@ 44 CALL $4xx 54 BRA $4xx 64 LIT_4 74 SP! 45 CALL $5xx 55 BRA $5xx 65 LIT_5 75 RP! 46 CALL $6xx 56 BRA $6xx 66 LIT_6 76 X! 47 CALL $7xx 57 BRA $7xx 67 LIT_7 77 Y! 48 CALL $8xx 58 BRA $8xx 68 LIT_8 78 >SP $xx R@ 49 CALL $9xx 59 BRA $9xx 69 LIT_9 79 >RP $xx 4A CALL $Axx 5A BRA $Axx 6A LIT_A 7A >X $xx 4B CALL $Bxx 5B BRA $Bxx 6B LIT_B 7B >Y $xx 4C CALL $Cxx 5C BRA $Cxx 6C LIT_C 7C NOP 4D CALL $Dxx 5D BRA $Dxx 6D LIT_D 7D --- 4E CALL $Exx 5E BRA $Exx 6E LIT_E 7E --- 4F CALL $Fxx 5F BRA $Fxx 6F LIT_F 7F --- 80..BF SBRA $xxx Short branch inside current page C0..FF SCALL $xxx Short subroutine CALL into 'zero page' 26 03.01 MARC4 Programmer's Guide Instruction Set 2.1.1 Description of Used Identifiers and Abbreviations n1 n2 n3 Three nibbles on the Expression Stack n3n2n1 Three nibbles on the Return Stack which combine to form a 12-bit word un2n1 Two nibbles on the Return Stack (i.e. DO loop index and limit), `u' is an unused (undefined) nibble on the Return Stack RP Return Stack Pointer (8 bits), the RAM Address Register which points to the last entry on the return address stack X RAM Address Register (8 bits) Y RAM Address Register Y (8 bits) these registers can be used in 3 different addressing modes (direct, pre-incremented or postdecremented addressing) TOS Top of (Expression) Stack (4 bits) CCR Condition Code Register (4 bits) which contains: /n 1's complement of the 4-bit word n 3210 Numbered bits within a 4-bit word $xx 8-bit hexadecimal RAM address $xxx 12-bit hexadecimal ROM address PC Program Counter (12 bits) I [bit 0] Interrupt-Enable flag SP Expression Stack Pointer (8 bits), the RAM Address Register which points to the RAM location containing the second nibble (TOS-1) on the Expression Stack B [bit 1] Branch flag 2.1.2 % [bit 2] Reserved (currently unused) C [bit 3] Carry flag /C NOT Carry (Borrow)flag Stack Notation E ( n1 n2 -- n ) Expression Stack contents ( rightmost 4-bit digit is in TOS ) R ( n1n2n3 -- ) Return Stack contents ( rightmost 12-bit word is top entry ) RET ( -- ROMAddr ) Return Address Stack effects EXP ( -- ) Expression / Data Stack effects True condition = Branch flag set in CCR False condition = Branch flag reset in CCR n 4-bit data value (nibble) d 8-bit data value (byte) addr 8-bit RAM address ROMAddr 12-bit ROM address 03.01 27 MARC4 Programmer's Guide Instruction Set Code [hex] 28 Mnemonic Operation 00 ADD Add the top 2 stack digits 01 ADDC Add with carry the top 2 stack digits 02 SUB 2's complement subtraction of the top 2 digits 03 SUBB 1's complement subtraction of the top 2 digits 04 XOR Exclusive-OR top 2 stack digits 05 AND Bitwise-AND top 2 stack digits 0C OR Bitwise-OR top 2 stack digits 06 CMP_EQ Equality test for top 2 stack digits 07 CMP_NE Inequality test for top 2 stack digits 08 CMP_LT Less-than test for top 2 stack digits 09 CMP_LE Less-or-equal for top 2 stack digits 0A CMP_GT Greater-than for top 2 stack digits 0B CMP_GE Greater-or-equal for top 2 stack digits 0E CCR! 0F SLEEP 10 SHL Shift TOS left into carry 11 ROL Rotate TOS left through carry 12 SHR Shift TOS right into Carry Restore condition codes CPU in 'sleep mode',, interrupts enabled Symbolic Description [Stack Effects] E ( n1 n2 -- n1+n2 ) If overflow then B:=C:=1 else B:=C:=0 E ( n1 n2 -- n1+n2+C) If overflow then B:=C:=1 else B:=C:=0 E ( n1 n2 -- n1+/n2+1) If overflow then B:=C:=1 else B:=C:=0 E ( n1 n2 -- n1+/n2+/C) If overflow then B:=C:=1 else B:= C:=0 E ( n1 n2 -- n1 XOR n2) If result=0 then B:=1 else B:=0 E ( n1 n2 -- n1 AND n2) If result=0 then B:=1 else B:=0 E ( n1 n2 -- n1 OR n2) If result=0 then B:=1 else B:=0 E ( n1 n2 -- n1) If n1=n2 then B:=1 else B:=0 E ( n1 n2 -- n1) If n1<>n2 then B:=1 else B:=0 E ( n1 n2 -- n1) If n1n2 then B:=1 else B:=0 E ( n1 n2 -- n1) If n1>=n2 then B:=1 else B:=0 E ( n -- ) R ( -- ) E ( -- ) R ( -- ) I:=1 C<--197>3210<--0 B:=C:=MSB ..<--C<--3210<--C<--.. B:=C:=MSB 0-->3210-->C B:=C:=LSB Instr. Cycles Flags C%BI 1 xxx- 1 xxx- 1 xxx- 1 xxx- 1 -xx- 1 -xx- 1 -xx- 1 xxx- 1 xxx- 1 xxx- 1 xxx- 1 xxx- 1 xxx- 1 xxxx 1 -x-1 1 xxx- 1 xxx- 1 xxx- 03.01 MARC4 Programmer's Guide Instruction Set Code [hex] Mnemonic Operation 13 ROR Rotate TOS right through carry 14 INC Increment TOS 15 DEC Decrement TOS 16 DAA Decimal adjust for addition (in BCD arithmetic) 17 NOT 1's complement of TOS 18 TOG_BF Toggle Branch flag 19 SET_BCF Set Branch and Carry flag 1A DI Disable all interrupts 1B IN Read data from 4-bit I/O port 1C DECR Decrement index on return stack 1D RTI Return from interrupt routine; enable all interrupts 1E SWI Software interrupt 1F OUT 20 21 TABLE 22 >R 23 I R@ 24 25 EXIT Write data to 4-bit I/O port Fetch an 8-bit ROM constant and performs an EXIT to RetPC Move (loop) index onto Return Stack Copy (loop) index from the Return Stack onto TOS Return from subroutine ( ' ; ' ) 26 SWAP 27 OVER 28 2>R 29 3>R 2A 2R@ 2B 3R@ 03.01 Exchange the top 2 digits Push a copy of TOS-1 onto TOS Move top 2 digits onto Return Stack Move top 3 digits onto Return Stack Copy 2 digits from Return to Expression Stack Copy 3 digits from Return to Expression Stack Symbolic Description [Stack Effects] ..-->C-->3210-->C-->.. B:=C:=LSB E ( n -- n+1) If result=0 then B:=1 else B:=0 E ( n -- n-1) If result=0 then B:=1 else B:=0 If TOS>9 OR C=1 then E ( n -- n+6 ) B:=C:=1 else E ( n -- n) R (--) B:=C:=0 E ( n -- /n) If result=0 then B:=1 else B:=0 If B = 1 then B:=0 else B:=1 B:=C:=1 E ( -- ) R ( -- ) I:=0 E ( port -- n) If port=0 then B:=1 else B:=0 R ( uun -- uun-1) If n-1=0 then B:=0 else B:=1 E (--) R ( $xxx -- ) PC := $xxx I:=1 E ( n1 n2 -- ) R ( -- ) [n1,n2 = 0,1,2,4,8] E ( n port -- ) R ( -- ) E ( -- nh nl ) R ( RetPC ROMaddr -- ) PC:= RetPC E ( n -- ) R ( -- uun) E ( -- n ) R ( uun -- uun) E ( -- ) R ( $xxx --) PC:=$xxx E ( n1 n2 -- n2 n1) R ( -- ) E ( n1 n2 -- n1 n2 n1) R ( -- ) E ( n1 n2 -- ) R ( -- un1n2) E ( n1 n2 n3 -- ) R ( -- n1n2n3) E ( -- n1 n2) R (un1n2 -- un1n2) E ( -- n1 n2 n3) R (n1n2n3 -- n1n2n3) Instr. Cycles Flags C%BI 1 xxx- 1 -xx- 1 -xx- 1 1x1- 0x0- 1 -xx- 1 -xx- 1 1x1- 1 -x-0 1 -xx- 2 -10- -01- 2 ---1 1 -x-- 1 -x-- 3 ---- 1 ---- 1 ---- 2 ---- 1 ---- 1 ---- 3 ---- 4 ---- 2 ---- 4 ---- 29 MARC4 Programmer's Guide Instruction Set Code [hex] Operation 2C ROT Move third digit onto TOS 2D DUP Duplicate the TOS digit 2E DROP Remove TOS digit from the Expression Stack 2F DROPR Remove one entry from the Return Stack 30 [X]@ Indirect fetch from RAM addressed by the X register 31 [+X]@ 32 [X-]@ Indirect fetch from RAM addressed by preincremented X register Indirect fetch from RAM addressed by the postdecremented X register [>X]@ $xx Direct fetch from RAM addressed by the X register 34 [Y]@ Indirect fetch from RAM addressed by the Y register 35 [+Y]@ 36 [Y-]@ 33 xx 37 xx [>Y]@ $xx 38 [X]! 39 [+X]! 3A [X-]! 3B xx 3C 30 Mnemonic Indirect fetch from RAM addressed by preincremented Y register Indirect fetch from RAM addressed by postdecremented Y register Direct fetch from RAM addressed by the Y register Indirect store into RAM addressed by the X register Indirect store into RAM addressed by pre-incremented X register Indirect store into RAM addressed by the postdecremented X reg. [>X]! $xx Direct store into RAM addressed by the X register [Y]! Indirect store into RAM addressed by the Y register Symbolic Description [Stack Effects] E (n1 n2 n3 -- n2 n3 n1) R ( -- ) E ( n -- n n) R ( -- ) E ( n -- ) R ( -- ) SP:=SP-1 E ( -- ) R( uuu -- ) RP:=RP-4 E ( -- n) R ( -- ) X:=X Y:=Y E ( -- n) R ( -- ) X:=X+1 Y:=Y E ( -- n) R ( -- ) X:=X-1 Y:=Y E ( -- n) R ( -- ) X:=$xx Y:=Y E ( -- n) R ( -- ) X:=X Y:=Y E ( -- n) R ( -- ) X:=X Y:=Y+1 E ( -- n) R ( -- ) X:=X Y:=Y-1 E ( -- n) R ( -- ) X:=X Y:=$xx E ( n -- ) R ( -- ) X:=X Y:=Y E ( n -- ) R ( -- ) X:=X+1 Y:=Y E ( n -- ) R ( -- ) X:=X-1 Y:=Y E ( n -- ) R ( -- ) X:=$xx Y:=Y E ( n -- ) R ( -- ) X:=X Y:=Y Instr. Cycles Flags C%BI 3 ---- 1 ---- 1 ---- 1 ---- 1 ---- 1 ---- 1 ---- 2 ---- 1 ---- 1 ---- 1 ---- 2 ---- 1 ---- 1 ---- 1 ---- 2 ---- 1 ---- 03.01 MARC4 Programmer's Guide Instruction Set Code [hex] Mnemonic Operation Symbolic Description [Stack Effects] Instr. Cycles Flags C%BI 3D [+Y]! Indirect store into RAM addressed by pre-incremented Y register E ( n -- ) R ( -- ) X:=X Y:=Y+1 1 ---- 3E [Y-]! Indirect store into RAM addressed by the post-decremented Y reg. E ( n -- ) R ( -- ) X:=X Y:=Y-1 1 ---- [>Y]! $xx Direct store into RAM addressed by the Y register E ( n -- ) R ( -- ) X:=X Y:=$xx 2 ---- 70 SP@ Fetch the current Expression Stack Pointer E ( -- SPh SPI+1) R ( -- ) SP:=SP+2 2 ---- 71 RP@ Fetch current Return Stack Pointer E ( -- RPh RPI) R ( -- ) 2 ---- 72 X@ Fetch current X register contents E ( -- Xh XI) R ( -- ) 2 ---- 73 Y@ Fetch current Y register contents E ( -- Yh YI) R ( -- ) 2 ---- 74 SP! Move address into the Expression Stack Pointer E ( dh dl -- ?) R ( -- ) SP:=dh_dl 2 ---- 75 RP! Move address into the Return Stack Pointer E ( dh dl -- ) R ( -- ?) RP:=dh_dl 2 ---- 76 X! Move address into the X register E ( dh dl -- ) R ( -- ) X:=dh_dl 2 ---- 77 Y! Move address into the Y register E ( dh dl -- ) R ( -- ) Y:=dh_dl 2 ---- 78 xx >SP $xx Set Expression Stack Pointer E ( -- ) R ( -- ) SP:=$xx 2 ---- 79 xx >RP $xx Set return Stack Pointer direct E ( -- ) R ( -- ) RP:=$xx 2 ---- 7A xx >X $xx Set RAM address register X direct E ( -- ) R ( -- ) X:=$xx 2 ---- 7B xx >Y $xx Set RAM address register Y direct E ( -- ) R ( -- ) Y:=$xx 2 ---- 7C NOP No operation PC:=PC+1 1 ---- 7D..7F NOP Illegal instruction PC:=PC+1 1 ---- 4x xx CALL $xxx Unconditional long CALL E ( -- ) R ( -- PC+2) PC:=$xxx 3 ---- 5x xx BRA $xxx Conditional long branch If B=1 then PC:=$xxx else PC:=PC+1 2 --1- --0- LIT_n Push literal/constant n onto TOS E ( -- n ) R ( -- ) 1 ---- 80..BF SBRA $xxx Conditional short branch in page If B=1 then PC:= $xxx else PC:=PC+1 2 ---- ---- C0..FF SCALL $xxx Unconditional short CALL E ( -- ) R ( -- PC+1) PC:= $xxx 2 ---- 3F xx 6n 03.01 31 MARC4 Programmer's Guide Instruction Set 2.1.3 MARC4 Instruction Set Overview Mnemonic Description Cycles/ Bytes AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAAAAAAAAAAA AAA AAAAAAAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAAAAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAA AAAAAAAAAAAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAAAAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAA AAAAAAAAAAAAAA AAAAAAAAA AAA Arithmetic operations: ADD Add ADDC Add with carry SUB Subtract SUBB Subtract with borrow DAA Decimal adjust INC Increment TOS DEC Decrement TOS DECR Decrement. 4-bit index on return stack Compare operations: CMP_EQ Compare equal CMP_NE Compare not equal CMP_LT Compare less than CMP_LE Compare less equal CMP_GT Compare greater than CMP_GE Compare greater equal Logical operations: XOR Exclusive OR AND AND OR OR NOT 1's complement SHL Shift left into carry SHR Shift right into carry ROL Rotate left through carry ROR Rotate right through carry Flag operations: TOG_BF Toggle branch flag SET_BFC Set branch flag DI Disable all interrupts CCR! Store TOS into CCR CCR@ Fetch CCR onto TOS Program branching: BRA $xxx Conditional long branch CALL $xxx Long call (current page) SBRA $xxx Conditional short branch SCALL$xxx Short call (zero page) EXIT Return from subroutine RTI Return from interrupt SWI Software interrupt SLEEP Activate sleep mode NOP No operation 32 1/1 1/1 1/1 1/1 1/1 1/1 1/1 2/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 1/1 2/2 3/2 2/1 2/1 2/1 2/1 1/1 1/1 1/1 Mnemonic Description Cycles/ Bytes AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAAAAAAAAA AAAAAAAA AAAA AAAAAAAAAAAAAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA AAAAA AAAAAAAA AAAA SP@ RP@ X@ Y@ SP! RP! X! Y! >SP $xx >RP $xx >X $xx >Y $xx SWAP OVER DUP ROT DROP >R 2>R 3>R R@ 2R@ 3R@ DROPR LIT_n Register operations: Fetch the current SP Fetch the current RP Fetch the contents of X Fetch the contents of Y Move the top 2 into SP Move the top 2 into RP Move the top 2 into X Move the top 2 into Y Store direct address to SP Store direct address to RP Store direct address into X Store direct address into Y Stack operations: Exchange the top 2 nibble Copy TOS-1 to the top Duplicate the top nibble Move TOS-2 to the top Remove the top nibble Move the top nibble onto the return stack Move the top 2 nibble onto the return stack Move the top 3 nibble onto the return stack Copy 1 nibble from the return stack Copy 2 nibbles from the return stack Copy 3 nibbles from the return stack Remove the top of return stack (12-Bit) Push immediate value 2/1 2/1 2/1 2/1 2/1 2/1 2/1 2/1 2/2 2/2 2/2 2/2 1/1 1/1 1/1 3/1 1/1 1/1 3/1 4/1 1/1 2/1 4/1 1/1 1/1 (1 nibble) onto TOS 03.01 MARC4 Programmer's Guide Instruction Set Instruction set overview (continued) Mnemonic Description Cycles/ Bytes AAAAAAAAAAAAAAA AAAAAAAAAAAAAAA AAAAA AAAAAAAAA AAA AAAAAAAAAAAAAAA AAAAA AAAAAAAAA AAA AAAAAAAAAAAAAAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAA AAAAA AAAAAAAAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAA AAAAA AAAAAAAAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAAAAA AAA AAAAA AAAAAAAAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAA AAAAA AAAAAAAAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAAAAA AAAAAAAAAAAAAAA AAAAAAAAAAAAAAA AAAAA AAAAAAAAA AAA AAAAA AAAAAAAAA AAA TABLE [X]@ [Y]@ [+X]@ [+Y]@ [X-]@ [Y-]@ [>X]@ $xx [>Y]@ $xx [X]! [Y]! [+X]! [+Y]! [X-]! [Y-]! [>X]! $xx [>Y]! $xx IN OUT 03.01 ROM data operations: Fetch 8-bit constant from ROM Memory operations: Fetch 1 nibble from RAM indirect addressed by Xor Y-register Fetch 1 nibble from RAM indirect addr. by pre-increm. X- or Y-register Fetch 1 nibble from RAM indirect addr. by post-dejcrem. X- or Y-register Fetch 1 nibble from RAM direct addressed by X- or Y-register Store 1 nibble into RAM indirect addressed by [X] Store 1 nibble into RAM indirect addressed by preincremented [X] Store 1 nibble into RAM indirect addr. by post-decrem. X- or Y-register Store 1 nibble into RAM direct addressed by X- or Y-register I/O operations: Read I/O-Port onto TOS Write TOS to I/O port 3 1/1 1/1 1/1 2/2 1/1 1/1 1/1 2/2 1/1 1/1 33 I. Hardware Description II. Instruction Set III. Programming in qFORTH IV. qFORTH Language Dictionary V. Addresses MARC4 Programmer's Guide Programming in qFORTH 3 3.1 Programming in qFORTH Why Program in qFORTH ? Programming in qFORTH reduces the software development time ! Atmel Wireless & Microcontrollers' strategy in developing an integrated programming environment for qFORTH was to free the programmer from restrictions imposed by many FORTH environments (e.g. screen, fixed file block sizes), and at the same time to maintain an interactive approach to program development. The MARC4 software development system enables the MARC4 programmer to edit, compile, simulate and/or evaluate a program code using an integrated package with predefined key codes and pull-down menus. The compiler-generated MARC4 code is optimized for demanding application requirements, such as the efficient usage of available program memory. One can be assured that the generated code only uses the amount of on-chip memory that is required, and that no additional overhead is attached to the program at the compilation phase. What other reasons are there for programming in qFORTH ? Subroutines that are kept short increase the modularity and program maintainability. Both are related to the development cost. Programs that are developed using the Brute Force approach (where the program is realized in software using a sequential code) tend to be considerably larger in memory consumption, and are extremely difficult to maintain. A qFORTH program, engineered using the building block modular approach is compact in size, easy to understand and thus, easier to maintain. The added benefit for the user is a library of software routines which can be interchanged with other MARC4 applications as long as the input and output conditions of your code block correspond. This toolbox of off-the-shelf qFORTH routines grows with each 03.01 new MARC4 application and reduces the amount of programming effort required. Programming in qFORTH results in a re-usable code. Re-usable for other applications which will be programmed at a later date. This is an important factor in ensuring that future software developement costs are kept to a minimum. Routines written by one qFORTH programmer can be easily incorporated by a different qFORTH user. Language Features: Expandability Many of the fundamental qFORTH operations are directly implemented in the MARC4 instruction set Stack Oriented All operations communicate with one another via the data stack and use the reverse polish form of notation (RPN) Structured Programming qFORTH supports programming structured Reentrant Different service routines can share the same code, as long as you do not modify global variables within this code Recursive qFORTH routines can call themselves Native Code Inclusion In qFORTH there is no separation of high level constructs from the native code mnemonics 37 MARC4 Programmer's Guide Programming in qFORTH 3.2 Language Overview qFORTH is based on the FORTH-83 language standard, the qFORTH compiler generates a native code for a 4-bit FORTH-architecture single-chip microcomputer - the Atmel Wireless & Microcontrollers MARC4. MARC4 applications are all programmed in qFORTH which is designed specifically for efficient real-time control. Since the qFORTH compiler generates highly optimized codes, there is no advantage or point in programming the MARC4 in assembly code. The high level of code efficiency generated by the qFORTH compiler is achieved by the use of modern optimization techniques such as branch-instruction size minimization, fast procedure calls, pointer tracking and peephole optimizations. IIIIII IIIIII IIIIII IIIIII IIIIII IIIIII IIIIII IIIIII IIIIIIIIIIIIIIIIII IIIIII IIIIII IIIIII IIIIII IIIIII IIIIII II APPLICATION SPECIFICATION PROGRAM SPECIFICATION HARDWARE REQUIREMENTS LEARN qFORTH LEARN DEVELOPMENT SYSTEM PSEUDO-CODE MODULES PROGRAMMER'S GUIDE CODE IN qFORTH MARC4 MARC4 qFORTH REFERENCE GUIDE II IIIIII II IIIIII IIIIII IIIIII II IIIIII IIIIII II IIIIII IIIIII IIIIII IIIIII IIIIII IIIIII IIIIII qFORTH qFORTH EDIT PROGRAM (MODULES) DEVELOPMENT SYSTEM USER'S GUIDE COMPILE MARC4 S.D.S. (TEST MODULES) SIMULATE EMULATE MAIL FLOPPY TO Atmel Wireless & mC MARC4 TARGET HARDWARE Figure 1. Program development with qFORTH 38 03.01 MARC4 Programmer's Guide Programming in qFORTH Standard FORTH operations which support string processing, formatting and disk I/O have been omitted from the qFORTH system library, since these instructions are not required in single-chip microcomputer applications. The following two tables highlight the basic constructs and compare qFORTH with the FORTH-83 language standard. Table 1. qFORTH's FORTH-83 language subset Arithmetic / Logical - D+ 1+ AND NEGATE + D- 1- NOT DNEGATE * 2* D2* OR / 2/ D2/ XOR Compiler ALLOT $INCLUDE CONSTANT 2CONSTANT CODE END-CODE VARIABLE 2VARIABLE Comparison < = <> <= >= 0= 0<> D> D0<> D< D0= D>= D= MIN MAX DMIN DMAX D<= D<> Stack Operations >R 2DROP DEPTH DUP PICK 2OVER DROP SWAP 2SWAP J ROT ROLL Control Structure ?DO DO IS ELSE THEN +LOOP LEAVE UNTIL AGAIN ENDCASE LOOP WHILE BEGIN ENDOF OF CASE EXIT REPEAT EXECUTE Memory Operations ! 2! @ 2@ ERASE MOVE MOVE > FILL TOGGLE Table 2. Differences between qFORTH and FORTH-83 qFORTH 4-bit Expression Stack 12-bit Return Stack The prefix "2" on a keyword (e.g. 2DUP refers to an 8-bit data type) Branch and Carry flag in the Condition Code Register Only predefined data types for handling untyped memory blocks, arrays or tables of constants 03.01 FORTH-83 16-bit Expression Stack 16-bit Return Stack The prefix "2" on a keyword (e.g. 2DUP refers to a 32-bit data type) Flag value on top of the Expression Stack CREATE, >BUILD .. DOES 39 MARC4 Programmer's Guide Programming in qFORTH 3.3 The qFORTH Vocabulary qFORTH is a compiled language with a dictionary of predefined words. Each qFORTH word contained in the system library has, as its basis, a set of core words which are very close to the machine-level instructions of the MARC4 (such as XOR, SWAP, DROP and ROT). Other instructions (such as D+ and D+!) are qFORTH word definitions. The qFORTH compiler parses the source code for words which have been defined in the system dictionary. Once located as being in the dictionary, the compiler then translates the qFORTH definition into MARC4 machine-level instructions. 3.3.1 Word Definitions A new word definition which i.e. contains three sub-words: WORD1, WORD2 and WORD3 in a colon definition called MASTER-WORD is written in qFORTH as: : MASTER-WORD WORD1 WORD2 WORD3 ; IIIII IIIII The colon `:' and the semicolon `;' are the start and stop declarations for the definition. A qFORTH programmer refers to a colon definition to specify a word name which follows the colon. The following diagram depicts the execution sequence of these three words: The sequential order shows the way the compiler (and the MARC4) will understand what the program is to do. 1st step Begin the word definition with a `:', followed by a space. 2nd step Specify the of the colon definition. 3rd step List the names of the sequentially-organized words which will perform the definition. Remember that each word as shown above can itself be a colon or macro definition of other qFORTH words (such as D+ or 2DUP). 4th step Specify the end of the colon definition with a semicolon. II II ; : MASTER_WORD WORD1 WORD2 WORD3 Figure 2. Threaded qFORTH word definition 3.4 Stacks, RPN and Comments In this section, we will look at the qFORTH notation known as RPN. Other topics to be examined include qFORTH's stacks, constants and variables. 3.4.1 Reverse Polish Notation qFORTH is a Reverse Polish Notation language (RPN), which operates on a stack of data values. RPN is a stack based representation of a mathematical problem where the top two numbers on the stack are operated on by the operation to be performed. 40 Example: 4+2 Is spoken in the English language as '4 plus 2', resulting in the value 6. In our stack-based MARC4, we write this using qFORTH notation as: 42+ The first number, 4, must be placed onto the data stack, then the second number will follow it onto the data stack. The MARC4 then comes to the addition operator. Both the 4 and 2 are taken off the data stack and processed by the MARC4's arithmetic and logic unit, the result (in this case 6) will be deposited onto the top of the data stack. 03.01 MARC4 Programmer's Guide Programming in qFORTH 3.4.2 The qFORTH Stacks The MARC4 processor is a stack-based microcomputer. It uses a hardware-constructed storage area onto which data is placed in a last-in-first-out nature. The MARC4 has two stacks, the Expression Stack and the Return Stack. The Expression Stack, also known as the data stack, is 4 bits wide and is used for temporary storage during calculations or to pass parameters to words. The Return Stack is 12 bits wide and is used by the processor to hold the return addresses of subroutines, so that upon completion of the called word, program control is transferred back Before Side ( n3 n2 n1 TOS 3.4.4 After Side -- n3 n2 n1) TOS qFORTH Comment Definitions Type _ 2 : \ text Type_1 Comments begin and end with curved brackets while Type_2 comments require only a backslash at the beginning of the comment. Type_1 declarations do not require a blank space before closing the bracket. 03.01 Stack Notation The qFORTH stack notation shows the stack contents before and after the execution of a qFORTH word. The before and after operations are separated via two bars: -- . The left hand side of the stack shows the stack before execution of the operation. The right most element before the two bars on the left side is the top of stack before the operation and the right most on the right side is also the top of stack after the operation. Examine the following qFORTH stack notation: Stack Notation 4 2 1 + SWAP Comments in qFORTH are definitions which instruct the qFORTH compiler to ignore the text following the comment character. The comment is included in the source code of your program to aid the programmer in understanding what the code does. There are two types of comment declarations: ( text ) 3.4.3 Example Comments Type _ 1 : to the calling qFORTH word. The Return Stack is used by all colon definitions (i.e. CALLs), interrupts and to hold loop-control variables. ( -- 4 2 1 ) ( 4 2 1 -- 4 3 ) ( 4 3 -- 3 4 ) Type_2 Comments start at the second space following the backslash and go till the end of the line. Both types of declarations require a blank space to follow the comment declaration. Valid Invalid ( this is a valid comment ) (this is not a valid comment) \ this is a valid comment \\ this is not a valid comment 41 MARC4 Programmer's Guide Programming in qFORTH 3.5 Constants and Variables $EXTMEMSIZE In qFORTH, data is normally manipulated as unsigned integer values, either as memory addresses or as data values. Allows the programmer to define the size of an external memory. Only required if an external memory is used whereby the default value is set at 255 nibbles. 3.5.1 $EXTMEMPORT Constants A constant is an unalterable qFORTH definition. Once defined, the value of the constant cannot be altered. In qFORTH, 4-bit and 8-bit numerical data can be assigned to a more readable symbolic representation. Allows the definition of a port address via which the external memory is accessed. The default port address for external memory is Fh. $EXTMEMTYPE value CONSTANT ( 4-bit constant ) Allows the definition of the type of external memory used. The types RAM or EEPROM are valid, whereby RAM is default if an external memory is used. value 2CONSTANT ( 8-bit constant ) Example: qFORTH Constant Definitions Example: 7 42h CONSTANT 2CONSTANT : Load-Answer Set-Mode ROM_Okay ROM_Okay ; ( Places 42h on EXP stack) 6 CONSTANT RAM CONSTANT 95 2CONSTANT 16 2ARRAY : Check_Freq Freq [4] IF 0 0 THEN ; 3.5.2 $EXTMEMPORT $EXTMEMTYPE $EXTMEMSIZE Freq EXTERNAL 2@ 80h D> Frequency [5] 2! Look-up Tables In the qFORTH compiler a number of constants have a predefined function. Look-up tables of 8-bit bytes are defined by the word ROMCONST followed by the and a list of single- or double-length constants each delimited by a space and a comma. $ROMSIZE 2CONSTANT to define the MARC4's actual ROM size. The values are 1.5K (default), 2.0K, 2.5K, 3.0K and 4.0Kbytes of ROM. The content of a table is not limited to literals such as 5 or 67h, but may also include user- or pre-defined constants such as Set-Mode or ROM_Okay. $RAMSIZE 2CONSTANT to define the MARC4's actual RAM size in nibbles. Possible values are 111 (default), 167 and 255 nibbles. In the examples below, the days of the month are placed into a look-up table called `Days_Of_Month', the month (converted to 0 ... 11) is used to access the table in order to return the BCD number of days in the given month. Predefined Constants 42 03.01 MARC4 Programmer's Guide Programming in qFORTH qFORTH Table Definition ROMCONST Const , Const , Const , Const , Const , Const , Examples: ROMCONST DaysOfMonth 31h , 28h , 31h , 30h , 31h , 30h , 31h , 31h , 30h , 31h , 30h , 31h , ROMCONST DaysOfWeek SU , MO , TU , WE, TH , FR , SA , ROMCONST Message 11 , " Hello World " , Note 1:A comma must follow the last table item. Note 2:Since there is no end-of-table delimiter in qFORTH, only a colon definition, a VARIABLE or another ROMCONST may follow a table definition (i.e. the last comma). 3.6 Variables and Arrays A variable is a qFORTH word whose name is associated with a memory address. A value can be stored at the memory address by assigning a value to the named variable. The value at this address can be accessed by using the variable name, thereby placing the variable value onto the top of the stack. The VARIABLE definition has a 4-bit memory cell allocated to it. qFORTH also permits a double-length 8-bit value to be assigned as a 2VARIABLE. qFORTH Variable Definitions VARIABLE 4-bit variable 2VARIABLE 8-bit variable 03.01 Example: VARIABLE Relay# 2VARIABLEVoltage 3.6.1 Defining Arrays qFORTH arrays are declared differently from arrays in FORTH-83. In both implementations of FORTH an array is a collection of elements assigned to a common name. An array can either be defined as being a VARIABLE with 8 elements: VARIABLE DATA 7 ALLOT or using the qFORTH array implementation: 8 ARRAY DATA The array index is running from 0 to . ARRAY and 2ARRAY may contain up to 16 elements (e.g. nibbles or bytes). LARRAY and 2LARRAY contain more than 16 elements. qFORTH Array Definitions ARRAY Allocates RAM space for a short 4-bit array LARRAY Allocates RAM space for a long 4-bit array 2ARRAY Allocates space for a short 8-bit array 2LARRAY Allocates space for a long 8-bit array 3.7 Stack Allocation Both the Expression and Return Stacks are located in RAM. The size of the stacks is variable and must be defined by the programmer by using the predefined variables R0 and S0. Figure 3 shows the location of the stacks in RAM. The Return Stack variable address R0 starts at RAM location 00h. The Expression Stack is located above the Return Stack, starting at the next location called S0. The depth of the Expression and Return Stacks is allocated using the ALLOT construct. While 43 MARC4 Programmer's Guide Programming in qFORTH the depth (in nibbles) of the Expression Stack is exactly the number allocated, the Return Stack depth is expressed by the following formula: : $RESET >RP FCh \ Initialize the two stack pointers >SP S0 RAM_Test ... RET_Value := (RET_Depth-2)4+1 ; Example: VARIABLE R0 20 ALLOT \ RET Depth of 7 VARIABLE S0 17 ALLOT \ EXP Depth of 17 3.7.1 Stack Pointer Initialization 2 3 S0 unused 0Ch 08h 04h 00h R0 FCh 0 0 0 Return Stack RP Expression Stack 15h (TOS-1) used SP used unused Global variables and arrays 1 3.8.1 Stack Operations, Reading and Writing Stack Operations A number of stack operators are available to the qFORTH programmer. An overview of all the predefined stack words can be found in the qFORTH Quick Reference Guide. Stack operators used most often and which manipulate the order of the elements on the data stack like DUP, DROP, SWAP, OVER and ROT are explained later on. The Data Stack RAM 0 3.8 The 4-bit wide Data Stack is called the Expression Stack. Arithmetic and data manipulation are performed on the Expression Stack. The Expression Stack serves as a holding device for the data and also as the interface link between words, so that all data passed between the qFORTH words can be located on the Expression Stack or in global variables. The qFORTH word : TEN 1 2 3 4 5 6 7 8 9 0 ; Auto-Sleep Figure 3. Stacks inside RAM 9 The two stack pointers must be initialized in the $RESET routine. Note: The Return Stack pointer RP must be set to FCh so that the AUTOSLEEP feature will work. 44 TOS-1 8 7 6 5 4 3 2 Example: VARIABLE R0 32 ALLOT VARIABLE S0 12 ALLOT TOS 0 1 \ RET stack depth = 10 \ EXP stack depth = 12 nibbles TOS-9 Figure 4. Push-down data stack 03.01 MARC4 Programmer's Guide Programming in qFORTH When executed, the value 0 at the top and the value 1 at the bottom of the Expression Stack will be the result. SWAP In many programming applications it is necessary to re-arrange the input data so that it can be handled properly. For example we will use a simple series of data and then SWAP them so that they appear in the reserve order. 4 2 SWAP ( 4 2--2 4) 2 4 4 2 TOS TOS-1 ROT and , >R, R@ and DROPR TOS-9 Expression Stack Expression Stack Figure 5. The SWAP operation DUP, OVER and DROP The qFORTH word to duplicate the TOS item is DUP. It will make a copy of the current TOS element on the Expression Stack. DUP is useful in retaining the TOS value before operations which implicitly DROP the TOS following their execution. For example, all of the comparison operations like >, >=, <= or < destroy the TOS. qFORTH also supports data transfers between the Expression and the Return Stack. The >R operation moves the top 4-bit value from the Expression Stack and pushes the value onto the Return Stack. R> removes the top 4-bit value from the Return Stack and puts the value onto the Expression Stack, while R@ (or I) copies the 4-bit value from the Return Stack and deposits the copied value onto the Expression Stack. DROPR removes the top entry from the Return Stack. R>, R@, I TOS TOS-1 The OVER operation makes a copy of the second element on the stack (TOS-1) and deposits it onto the top of the stack. The MARC4 stack operator DROP removes one 4-bit value from the TOS. For example, the qFORTH operation NIP will drop the TOS-1 element from the stack. This can be written in qFORTH as: : NIP SWAP DROP ; ( n1 n2 -- n2 ) 03.01 TOS-9 0 9 8 7 6 5 4 3 2 1 Expression Stack 0 >R, #DO Return Stack Figure 6. Return Stack data transfers 45 MARC4 Programmer's Guide Programming in qFORTH Other Useful Stack Operations The following list contains more useful stack operations. Note that for every 4-bit stack operation, there is almost always an 8-bit equivalent. A full list of all stack operations may be found in the qFORTH Quick Reference Guide. ' EXP ( -- ROMAddr ) Places ROM address of colon-definition on EXP stack 0 I EXP ( -- I ) R@ RET ( u|u|I -- u|u|I ) Copy 4-bit loop index I from the return to the Expression Stack NIP EXP ( n1 n2 -- n2 ) Drop second to top 4-bit value TUCK EXP ( n1 n2 -- n2 n1 n2 ) Duplicate top value, move under second item 2>R EXP ( n1 n2 -- ) RET ( -- u|n2|n1 ) Move top two values from Expression to Return Stack 2DROP EXP ( n1 n2 -- ) Drop top 2 values from the stack 2DUP EXP ( d -- d d ) Duplicate top 8-bit value 2NIP EXP ( d1 d2 -- d2 ) Drop 2nd 8-bit value from stack 2OVER EXP ( d1 d2 -- d1 d2 d1 ) Copy 2nd 8-bit value over top value 2 EXP ( -- n1 n2 ) RET ( u|n2|n1 -- ) Move top 8 bits from Return to Expression Stack 2R@ EXP ( -- n1 n2 ) RET ( u|n2|n1 -- u|n2|n1 ) Copy top 8 bits from Return to Expression Stack 3>R EXP ( n1 n2 n3 -- ) RET ( -- n3|n2|n1 ) Move top 3 nibbles from the Expression onto the Return Stack 3DROP EXP ( n1 n2 n3 -- ) Remove top 12-bit value from stack 3DUP EXP ( t -- t t ) Duplicate top 12-bit value 3R> EXP ( -- n1 n2 n3 ) RET ( n3|n2|n1 -- ) Move top 3 nibbles from Return to the Expression Stack 3R@ EXP ( -- n1 n2 n3 ) Copy 3 nibbles (1 ROM address entry) from the RET ( n3|n2|n1 -- n3|n2|n1 ) Return Stack to the Expression Stack 46 03.01 MARC4 Programmer's Guide Programming in qFORTH 3.8.2 3.8.3 Reading and Writing (@, !) In the previous section it was mentioned that data can be placed onto, and taken off the Expression Stack. The reading and writing operations transfer data values between the data stack and the RAM. Writing a data value to a RAM location which has been specified by a variable name requires the TOS to contain the variables 8-bit RAM address and that the data to be stored in the RAM be contained at the TOS-2 location. The read operator is written in the qFORTH syntax with the @ symbol and is pronounced fetch. The write operator is written in qFORTH with the ! symbol and is pronounced store. Write two qFORTH colon definitions (words) that will store the numeric value 7 from the TOS to the variable named FRED and then fetch the contents its back onto the Expression Stack (TOS). Example: VARIABLE FRED : Store 7 FRED : Fetch FRED ! ; @ ; ( ( -- ) -- n ) For 8-bit values, stored at two consecutive locations, qFORTH has the Double-Fetch and Double-Store words: 2@ and 2!. To store 1Ah in the 8-bit 2VARIABLE BERT using the Double-Store, examine the following code: 2VARIABLE BERT : Double-Store 1Ah BERT RAM Address Registers X and Y The MARC4 processor can address any location in RAM indirectly via the 8-bit wide X and Y RAM Address Registers. These registers are used as pointer registers to organize arrays within the RAM. They can be pre-incremented or post-decremented by using CPU control. The X and Y registers are automatically used by the compiler during fetch (@) and store (!) operations. Hence, care should be taken when referencing these registers explicitly. If a default occurs, the compiler uses the Y register. Memory Operators which Use the X / Y Register @ D+! 2! ERASE ! D-! 2@ FILL +! TD+! 3! MOVE 1+! TD-! 3@ MOVE> -! T+! PICK TOGGLE 1-! T-! ROLL DTOGGLE Example: BERT 2! ; Storing the value 1Ah is a two-part operation: The high-order nibble 1 is stored in the first digit, while at the next 4-bit RAM location the hexadecimal value A will be stored. : Double-Fetch Low-Level Memory Operations 2@ ; (-- d) i.e., accesses the 8 bits at the memory address where BERT is placed and loads them onto Expression Stack. The lower-order nibble will always end up on TOS. The 4-bit value in TOS is added to an 8-bit RAM value and stored back into the 8-bit RAM variable. : M+! X! 0 ; ( n RAM_addr -- ) [+X]@ [X]@ + +C [X-]! [X]! 2VARIABLE Voltage 5 Voltage M+! Note: Hexadecimal values are represented by an h or H following the value. 03.01 47 MARC4 Programmer's Guide Programming in qFORTH X Register X@ X! Description Fetch current X (or Y) register contents Y@ Move 8-bit address from stack into X (or Y) reg. Y! >X xx Set register address of X (or Y) direct >Y yy [>X]@ xx Direct RAM fetch, X (or Y) addressed [>Y]@ yy [>X]! xx Direct RAL store, X (or Y) addressed [>Y]! yy [X]@ Indirect X (or Y) fetch of RAM contents [Y]@ [X]! Indirect X (or Y) store of RAM contents [Y]! [+X]@ Preincrement X (or Y) indirect RAM fetch [+Y]@ [X-]@ Postdecrement X (or Y) indirect RAM fetch [Y-]@ [+X]! Preincrement X (or Y) indirect RAM store [+Y]! [X-]! Postdecrement X (or Y) indirect RAM store [Y-]! Bit Manipulations in RAM By using the X or Y registers, it is possible to manipulate the content of the RAM on a bitwise basis. The following examples all have the same stack notation. : BitSet X! [X]@ OR [X]! ; ( mask RAM_addr -- [branch flag] ) ( get data from memory ) ( mask & store in memory ) 3.9 MARC4 Condition Codes The MARC4 processor has within its Arithmetic Logic Unit (ALU) a 4-bit wide Condition Code Register (CCR) which contains 4 flag bits. These are the Branch (B) flag, the Interrupt-Enable (I) flag and the Carry (C) flag. C : BitReset X! Fh XOR [X]@ AND [X]! ; ( mask RAM_addr -- [branch flag] ) ( Invert mask for AND ) ( get data from memory ) ( mask & store in memory ) : Test0= ( mask RAM_addr -- [branch flag] ) X! [X]@ AND DROP ; CODE Test0<> ( mask RAM_addr -- [branch flag] ) Test0= TOG_BF END-CODE 48 Y Register - B I CCR Interrupt enable Branch (reserved) Carry Figure 7. MARC4 Condition Code Register flags Most arithmetic/logical operations, for example, will have an effect on the CCR. If you try to add 12 and 5, the Carry and Branch flags will be set, since an arithmetic overflow has occured. 03.01 MARC4 Programmer's Guide Programming in qFORTH 3.9.1 The CCR and the Control Operations The Carry flag is set by ALU instructions such as the +, +C, -or -C whenever an arithmetic under/overflow occurs. The Carry flag is also used during shift/rotate instruction such as ROR and ROL. The Branch flag is set under CPU control, depending upon the current ALU instruction, and is a result of the logical combination of the carry flag and the TOS = 0 condition. The Branch flag is responsible for generating conditional branches. The conditional branch is performed when the Branch flag has been set by one of the previous qFORTH operations (e.g. comparison operations). The TOG_BF instruction will toggle the state of the Branch flag in the CCR. If the Branch flag is set before the TOG_BF instruction, it will be reset following the execution. The SET_BCF instruction will set the Branch and Carry on execution, while the CLR_BCF operation will reset both flags. 3.10 Arithmetic Operations The arithmetic operators presented here are similar to those described in most FORTH literature. The underlying difference, however, is that the qFORTH arithmetic operations are based on the 4-bit CPU architecture of the MARC4. 3.10.1 Number Systems When coding in qFORTH, standard numeric representations are decimal values. For other representations, it is necessary to append a single character for that representation. Examples have already been presented which perform operations on the TOS as a 4-bit (single-length) value or on both the TOS and TOS-1 values. By combining the TOS and TOS-1 locations, it is possible to handle the data as an 8-bit value. Note: In qFORTH, all operators which start with a 2 (e.g: 2SWAP or 2@) use double-length (8-bit) data. Other operators such as D+ and D= are also double-length operators. The qFORTH language also permits triple-length operators, which are defined with a 3 prefix (e.g: 3DROP). Examples for all qFORTH dictionary words are included in the qFORTH Language Reference Dictionary. 3.10.2 Addition and Subtraction The algebraic expression 4 + 2 is spoken in the English language as: 4 plus 2, and results in a value of 6. In qFORTH, this expression as 4 2 +. The 4 is deposited onto the Data Stack, followed by the 2. The operator gives a command to take the top two values from the Data Stack and add them together. The result is then placed back onto the Data Stack. Both the 4 and the 2 are dropped from the stack by the operation. The stack notation for the addition operator is: + EXP ( n1 n2 -- n1+n2 ) qFORTH performs the subtraction in a similar way to the addition operator. The operator is the common algebraic symbol with the stack notation: - EXP ( n1 n2 -- n1-n2 ) Examples: : TNEGATE Example: Bh --> bH --> 11 --> 1011b--> 1011B--> Single- and Double-Length Operators hexadecimal hexadecimal decimal binary binary ( 12-bit 2's complement on the TOS ) 0 SWAP - ( th tm tl -- th tm -tl ) 0 ROT -c ( th tm -tl -- th -tl -tm ) ROT 0 SWAP-c ( th -tl -tm -- tl -tm -th) SWAP ROT ( -tl -tm -th -- -t ) ( base 16 ) ( base 16 ) ( base 10 ) ( base 2 ) ( base 2 ) ; 03.01 49 MARC4 Programmer's Guide Programming in qFORTH : 3NEG! Voltage 2@ 5 M+ IF 2DROP 0 0 \ IF overflow, THEN reset Voltage ELSE 10 M- THEN Voltage 2! ; 3.10.5 ( 12-bit 2's complement in an array ) Y! 0 [+Y]@ 0 [+Y]@ ( addr -- 0 tm 0 tl ) -[Y-]! -c [Y-]! ( 0 tm 0 tl -- ) 0 [Y]@ -c [Y]! ( 0 tm -tl -- ) 3.10.3 DAA and DAS Increment and Decrement Increment and decrement instructions are common to most programming languages. qFORTH supports both with the standard syntax: 1+ 1- incrementnew-TOS: = old-TOS + 1 decrement new-TOS: = old-TOS -1 Decimal numbers are usually represented in 4-bit binary equivalents of each digit using the binary-coded-decimal coding scheme. The qFORTH instruction set includes the DAA and DAS operations for BCD arithmetic. DAA Example: : Inc-Dec Note: 3.10.4 10 1+ 1-1- ; ( -- Ah ( Ah -- Bh ( Bh -- 9h BCD Arithmetic ) ) ) Fh ( 1111 ) -> 5 ( 0101 ) and carry flag set Eh ( 1110 ) -> 4 ( 0100 ) Dh ( 1101 ) -> 3 ( 0011 ) Ch ( 1100 ) -> 2 ( 0010 ) Bh ( 1011 ) -> 1 ( 0001 ) Ah ( 1010 ) -> 0 ( 0000 ) The Carry flag in the CCR is not affected by these MARC4 instructions, whereby the Branch flag is set if the result of the operation becomes zero. Mixed-Length Arithmetic qFORTH supports mixed-length operators such as M+, M-, M* and M/MOD. In the examples below, a 4-bit value is added/subtracted to/from an 8-bit value (generating an 8-bit result) using the M+ and M-operators. Decimal adjust for BCD arithmetic, adds 6 to values between 10 and 15. It will also add 6 to the TOS, if the carry flag is set. DAS Decimal arithmetic for BCD subtraction, builds a 9's complement for DAA and ADDC, the branch and carry flags will be changed. Examples: : DIG- Y! SWAP DAS SWAP #DO [Y]@ + DAA [Y-]! 10 -?LEAVE #LOOP DROP ; : BCD_1+! Y! [Y]@ 1 + DAA [Y]! ; : Array_1+ Y! SET_BCF BEGIN [Y]@ 0 +C DAA [Y-]! 1- UNTIL DROP ; 50 \ Digit count LSD_Addr -- \ Generate 9's complement \ Digit count -- Digit \ Transfer carry on stack \ Exit LOOP, if NO carry \ Repeat until index = 0 \ Skip TOS overflow digit \ RAM_Addr -- \ Increments BCD digit \ in RAM array element \ Inc BCD array by 1 ( n array[n] -- ) ( Start with carry = 1 ) 03.01 MARC4 Programmer's Guide Programming in qFORTH 3.10.6 Summary of Arithmetic Words The following list contain more useful arithmetic words. The full list and implementation may be found in the MATHUTIL.INC file D+ D- D+! D-! M+ M- M+! M-! M/ M* M/MOD D/MOD TD+! TD-! TD+ TD- D->BCD ( d1 d2 -- d_sum ( d1 d2 -- d2-d1 ( nh nl addr -- ( nh nl addr -- ( d1 n -- d2 ( d1 n -- d2 ( n addr -- ( n addr -- ( d n -- d_quotient ( d n -- d_product ( d n -- n_quot n_rem ( d n -- d_quot n_rem ( d addr -- ( d addr -- ( d addr -- t ( d addr -- t ( d -- n_100 n_10 n_1 ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) Add top two 8-bit elements Subtract top two 8-bit elements Add 8-bit TOS to memory Subtract 8-bit TOS from memory Add 4-bit TOS to an 8-bit value Sub 4-bit TOS from 8-bit value Add n to an 8-bit RAM byte Subtract n from 8-bit RAM byte Divide n from d Multiply d by n Div n from d giving 4-bit results Div 8-bit value &4-bit remainder Add 8-bit TOS to 12-bit RAM var. Sub 8-bit from 12-bit RAM var. Add 8-bit to 12-bit RAM var. Sub 8-bit from 12-bit RAM var. Convert 8-bit binary to BCD 3.11 Logicals The logical operators in qFORTH permit bit manipulation. The programmer can input a bit stream from the input port, transfer it onto the expression stack and then shift branches and the bit pattern left or right, or the bit pattern can be rotated onto the TOS. The Branch and Carry flag in the CCR are used by many of the qFORTH logical operators. used to represent the effects of the logical operators on two data values (n1 and n2). These qFORTH operators take the top values off of the expression stack and perform the desired logical operation. The resultant flag setting and the stack conditions are described in the qFORTH Language Reference Dictionary. The stack notation for all logical qFORTH words is: EXP ( n1 n2 -- n3 ) 3.11.1 Logical Operators The truth table shown below is the standard table NOT OR AND XOR n1 n1' n1 n2 n1 v n2 n1 n2 n1 ^ n2 n1 n2 n1 XOR n2 1 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 1 0 0 1 1 1 0 1 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 03.01 51 MARC4 Programmer's Guide Programming in qFORTH As an example, examine the logical AND operation with the data values 3 and 5. Representing these values in 4-bit binary, and performing the AND operator: 0101b 0011b AND ( -- 0101b 0011b ( 0101b 0011b -- 0001b ) ) results in a value of 1 appearing on the TOS. The Branch flag will be reset, since the result of the logical operation is non-zero. value located at the specified memory location will be exclusive-ORed. Example: VARIABLE LED_Status : Toggle-LED 0001b LED_Status TOGGLE ( toggles bit 0 only ) ; SHIFT and ROTATE Operations Example: : Logicals 3 7 OR 3 7 AND 5 XOR NOT 2DROP ; ( -- 7 ) ( 7 -- 7 3 ) ( 7 3 -- 7 6 ) ( 7 6 -- 7 9 ) ( 7 9 -- ) TOGGLE The TOGGLE operation is classified in the qFORTH Language Reference Dictionary as belonging to the set of memory operations. Although this is true, the TOGGLE and its relative, the DTOGGLE, are both used to change bit patterns at a specified memory address. For the TOGGLE operation the 4-bit Mnemonic SHR 2/ The MARC4 instruction set contains two shift and two rotate instructions which are shown in figure 2.8. The shift operators multiply (SHL) and divide (SHR) the TOS value by two. These instructions are identical to the qFORTH macros for 2* and 2/. The rotate instructions ROR and ROL shift the TOS value right/left through the Carry flag, and cause will the Carry and Branch flags to be altered. When using these instructions, it is advisable to set or reset the flags within your initialization routine, using either the SET_BCF or the CLR_BCF instructions. Description Shift TOS right into carry Function 3 2 1 0 0 C 3 2 1 0 ROR Rotate TOS right through carry SHL 2* Shift TOS left into carry C ROL Rotate TOS left through carry C C 0 Figure 8. Shift and rotate instructions 52 03.01 MARC4 Programmer's Guide Programming in qFORTH Example: Write the necessary qFORTH word definitions to flip a data byte (located on TOS) as shown below: Before flip: 3 2 1 0 After flip: 7 6 5 4 : FlipBits 0 4 #DO SWAP SHR SWAP ROL #LOOP NIP ; : FlipByte FlipBits SWAP 4 5 6 7 0 1 2 3 : GREATER-EQUAL 9 >= FlipBits ; 3.12 Comparisons The qFORTH comparison operations (such as > or <) will set the Branch flag in the CCR if the result of the comparison is true. The stack effects of a comparison operation is: EXP ( n1 n2 -- ) 3.12.1 <,> The qFORTH word < performs a 'less-than' comparison of the top two values on the stack. If the second value on the Expression Stack is less than the value on the TOS, then the Branch flag in the CCR will be set. Following the operation, the stack will contain neither of the two values which where checked, as they will be dropped from the Expression Stack. : Less-Example 9 5 < ; ( -- 9 5 ) ( 9 5 -- ) The > comparison operator determines if the second value on the stack is greater than the TOS value. If this condition is met, then the Branch flag will be set in the CCR. 3.12.2 <= , >= Using <= in your qFORTH program enables you to determine if the second item on the stack is less or equal to the TOS value. 03.01 In the GREATER-EQUAL example, the top two stack values 5 and 9 are removed from the stack and used as input values for the greater-or-equal operation. If the second value (TOS-1) is greater or equal the TOS value and subsequently the branch flag in the CCR will be set. After the comparison operation has been performed by the MARC4 processor, neither of the two input values will be contained on the Expression Stack. 3.12.3 5 ( -- 9 5 ) ; ( 9 5 -- [C-B-] ) <> , = These two qFORTH comparison operators can be used to determine the Boolean (true/false) value (e.g. setting/ resetting the Branch flag in the CCR). If the second value on the stack is not equal ( <> ) to the TOS value, then the Branch flag in the CCR will be set. The two values that were on the TOS before the operation, are dropped off the stack after the operation has been executed, except if one or both items on the Data Stack were duplicated before the operation. If, however, the equality test (=) is executed then the Branch flag will only be set, if both the TOS and the TOS-1 values are identical. Again, as with all the comparison operations presented so far, the contents of the TOS and TOS-1 previous to the operations are dropped from the stack. 3.12.4 Comparisons Using 8-bit Values Example: 68 2CONSTANT PAR-FOR-COURSE 2VARIABLE GROSS-SCORE : Check-golf-score GROSS-SCORE2@PAR-FOR-COURSE D0 8 D<= IF GOOD-SCORE THEN \ My Handicap is 8 ; Note: There is a space between the 0 and 8. This is required because literals less then 16 are assumed to be 4-bit values. 53 MARC4 Programmer's Guide Programming in qFORTH This problem may be improved if an additional 2CONSTANT is used, since 2CONSTANT assumes an 8-bit value, e.g. : 8 2CONSTANT My-Handicap : Check-Golf-score GROSS-SCORE2@PAR-FOR-COURSE DMy-Handicap D<= IF GOOD-SCORE THEN ; 3.13 Control Structures The control structures presented here can be divided into two categories: Selection and looping. The tables 3 and 4 compare qFORTH's control structures will those found in PASCAL. As the comparison of the two languages shows, qFORTH offers a rich variety of structures which enable your program to branch to different code segments within the program. Table 3. qFORTH selection control structures qFORTH IF THEN IF ELSE THEN CASE .. OF ENDOF .. ENDCASE PASCAL IF THEN ; IF THEN ELSE ; CASE .. OF ; .. END ; Table 4. qFORTH loop control structures qFORTH BEGIN UNTIL BEGIN WHILE REPEAT BEGIN AGAINb DO LOOP DO + LOOP DO ?LEAVE LOOP #DO #LOOP 54 PASCAL REPEAT UNTIL ; WHILE DO ; FOR i := TO DO ; FOR i := DOWNTO 0 DO ; 03.01 MARC4 Programmer's Guide Programming in qFORTH 3.13.1 Selection Control Structures The code to be executed is dependent on a specific condition. This condition can be indicated by setting the Branch flag in the CCR. The control operation sequences such as the IF .. THEN and the indefinite loop operations such as BEGIN .. UNTIL and BEGIN .. WHILE .. REPEAT will only be executed if the Branch flag has been set. IF .. THEN The IF .. THEN construct is a conditional phrase permitting the sequence of program statements to be executed dependent on the IF condition being valid. The qFORTH implementation of the IF .. THEN phrase requires that the computation appears before the IF word. IF .. THEN in PASCAL : IF THEN < True statements> ELSE ; IF .. THEN in qFORTH : First the current TOS value is duplicated. Then, 9 is deposited onto the TOS so that the value to be compared to is now in the TOS-1 and TOS-2 location of our data stack. The TOS value is now compared with the TOS-1 value. IF TOS-1 is greater than 9, then the condition has been met. The qFORTH words following the IF will therefore be executed. In the first example the TOS value will be dropped and replaced by the value 1. The CASE Structure The CASE structure is equivalent to the IF .. ELSE .. THEN structure. The IF .. ELSE .. THEN permits nested combinations to be constructed in qFORTH. A nested IF .. ELSE .. THEN structure can look like this example: : 2BIT-TEST DUP 0 = DUP 1 = DUP 2 = BIT0OFF ELSE BIT0ON ELSE BIT1OFF ELSE BIT1ON THEN THEN THEN THEN IF ELSE THEN IF IF IF DROP ; Example: : ) GREATER-9 DUP (n -- n or 1, IF n > 9 9 > IF DROP 1 (THEN replace n -- 1 ) THEN (ELSE keep original n ) ; : $RESET >SP S0 (Power-on initialization entry) >RP FCh (Init both stack pointers first ) 10 Greater-9(Compare 10 > 9 ==> BF true ) 5 Greater-9(1 5 -- 1 5 ) 2DROP (1 5 -- ) ; The qFORTH word GREATER-9 checks if the values given on TOS as a parameter to the word are greater than 9. 03.01 In the word `2BIT-TEST', the TOS is checked to see if it contains one of three possible values. If either one of these three values is on the TOS, then the desired word definition will be executed. If none of these three conditions has been met, then a fourth word BIT1ON will be executed. Re-writing the `2BIT-TEST' word using the CASE .. ENDCASE structure results in a qFORTH code which is more readable and thus easier to understand: : 2BIT-CASE CASE 0 OF 1 OF 2 OF BIT0OFF BIT0ON BIT1OFF BIT1ON ENDOF ENDOF ENDOF ENDCASE ; 55 MARC4 Programmer's Guide Programming in qFORTH The CASE selectors are not limited to constants ( e.g. high-score @). 15 CONSTANT TILT : PIN-BALL CASE 0 OF HIGH-SCORE @ OF TILT OF ( ELSE ) ENDCASE ; ( BALL-CODE -- ) FREE-BALL ENDOF REPLAY ENDOF GAME-OVER ENDOF UPDATE-SCORE Note: Unlike Pascal, the case compares the index to the loop's limit to determine whether the loop should terminate or continue. In addition to the FORTH-83 looping construct, the MARC4 has special hardware support for the qFORTH #DO .. #LOOP. As a result of this, the #DO..#LOOP is the most code and speed efficient definite loop and is recommended for most loop constructs. Example: 5 #DO HELLO-WORLD #LOOP The DO .. LOOP control structure is an example of a definite loop. The number of times the loop is executed by the MARC4 must be specified by the qFORTH programmer. In this example, the loop control variable is set to 5, then decremented at the end of each iteration until 0. Hence, 5 #DO .. #LOOP will loop 5 times. #LOOPS may also be nested (to any depth). The outer loop control variable is called J when used inside the inner loop. Example: Example: 3.13.2 Loops, Branches and Labels Definite Loops : DO-Example 12 5 ( -- Ch 5 ) DO ( Ch 5 -- ) I 1 OUT ( Copy loop-index I onto TOS ) LOOP ( Write "5 6 7 8 9 Ah Bh" to port1 ) ; Here, the loop index I starts at the value 5 and is incremented until the value 12 is reached. This is an example where we have defined a definite looping range (from 5 to 11) for the statements between the DO and the LOOP to be repeated. On each iteration of a DO loop, the LOOP operator will increment the loop index. It then 56 : NESTED-LOOPS 7 #DO \ OUTER LOOP 5 #DO \ INNER LOOP IJ+ Port0 OUT #LOOP #LOOP ; Care should be taken when using loops to compute multi-nibble arithmetic (e.g. 16-bit shift right). This is because the standard FORTH-83 definite loops change the Carry flag after each iteration of the loop. In such cases, the #DO .. #LOOP is recommended since the Carry flag is not affected. 03.01 MARC4 Programmer's Guide Programming in qFORTH ?DO .. ?LEAVE LOOP, ( limit start -- ) (--) (--) IF start = limit THEN skip the loop exit loop if the Branch flag is true increment loop-index by 1 DO .. -?LEAVE LOOP ( limit start -- ) (--) (--) Init iterative DO..LOOP if Branch flag is false, then exit loop increment loop-index by 1 ?DO .. LOOP ( limit start -- ) (--) IF start = limit THEN skip the loop DO .. +LOOP ( limit start -- ) (n--) Iterative loop with steps by increment loop-index by n #DO .. #LOOP (n--) (--) Execute #LOOP block n-times decrement loop-index until n = 0 Indefinite Loops BEGIN indicates the start of an indefinite loop-control structure. The sequence of words which are to be performed by the MARC4 processor will be repeated until a conditional repeat construct (such as UNTIL or WHILE .. REPEAT) is found. Write a counter value from 3 to 9 to Port 1, then finish the loop. The second conditional loops control structure BEGIN .. WHILE .. REPEAT repeats a sequence of qFORTH words as long as a condition (computed between BEGIN and WHILE) is still being met. qFORTH also provides an infinite loop sequence, the BEGIN .. AGAIN which can only be escaped by EXIT, -?LEAVE or ?LEAVE. Example: : UNTIL-Example 3 BEGIN DUP Port1 1+ DUP UNTIL DROP 9 OUT ( Write the current value to Port 1 ) ( Increment the TOS value 3 .. 9 ) > ( DUPlicate the current value .. ) ( the comparison will DROP it ) ( skip counter value from stack ) Example: : BinBCD Fh WHILE \ High order is zero 10 M- ROT 1- = IF 10 - ROT 1- 9) is met. 03.01 \ Converts binary to 2 digit BCD ( d [<99] -- Dhi Dlo ) \ 1's comp of '0' ; 57 MARC4 Programmer's Guide Programming in qFORTH qFORTH - Indefinite Loops BEGIN WHILE ... REPEAT Condition tested at start of loop BEGIN ... UNTIL Condition tested at end of loop BEGIN ... AGAIN Unconditional loop 3.13.3 Branches and Labels While not recommended in normal programming, branches and labels have been included in qFORTH for completeness. Labels have the following format: