.. index:: 12bitencoding,imm,glossary,folding,inlining,smudge,vocabularies,VOCS,,cornerstone,classic-kernel,ra-kernel,ra v/s classic kernel,create...does>,pearl of Forth,defining words,loop unrolling,token,marker .. _glossary: Glossary ======== .. _cornerstone: Cornerstone ----------- A Cornerstone is a special Word. Calling this word will then erase all definitions added *after* it. The Cornerstone name however will NOT be deleted. An example of this is 'eraseflash'. Mecrisp-Stellaris does not have a user 'cornerstone' word Marker ------ Marker is the same as 'Cornerstone' with the exception that 'marker' deletes the name of the marker as well. Mecrisp-Stellaris does not have a 'marker' word either, but you can create one. Marker Word for 1 KB Flash pages ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ :: : marker ( name -- ) begin dup $3FF and while 2+ repeat eraseflashfrom ; Example ~~~~~~~ 1) Enter the "marker" Word into Flash on your system as above 2) Enter the following, the reply from Mecrisp-Stellaris is indented :: words ... Address: 00003CE6 Link: 00004000 Flags: 0000FFFF Code: 00003D06 Name: --- Flash Dictionary --- marker corner-a : testa 2 2 + . cr ; words ... Address: 00003CE6 Link: 00004000 Flags: 0000FFFF Code: 00003D06 Name: --- Flash Dictionary --- Address: 00004000 Link: 0000405C Flags: 00000000 Code: 00004012 Name: marker Address: 0000405C Link: 00004400 Flags: 00000000 Code: 0000406C Name: corner-a Address: 00004400 Link: FFFFFFFF Flags: 00000000 Code: 0000440C Name: testa corner-a Erase block at 00004404 from Flash Mecrisp-Stellaris 2.4.5 for TM4C1294 by Matthias Koch words ... Address: 00003CE6 Link: 00004000 Flags: 0000FFFF Code: 00003D06 Name: --- Flash Dictionary --- .. warning:: Depending on the Flash implementation of the MCU, results may vary from this example. .. _imm: Imm --- An immediate value (or simply an immediate or imm) is a piece of data that is stored as part of the instruction itself instead of being in a memory location or a register. Immediate values are typically used in instructions that load a value or performs an arithmetic or a logical operation on a constant. ARM data processing instructions have 12 bits of space for values in their instruction word. This is arranged as a four-bit rotate value and an eight-bit immediate value. The 4-bit rotate value stored in bits 11-8 is multiplied by two giving a range of 0-30 in steps of two. Using this scheme we can express immediate constants such as: :: 0x000000FF 0x00000FF0 0xFF000000 0xF000000F But immediate constants such as: :: 0x000001FE 0xF000F000 0x55550000 …are not possible. An assembler will convert big values to the rotated form. Impossible values will cause an error. Some assemblers will use other tricks such as using MVN instead of MOV to form the bitwise complement of the required constant. For example the impossible instruction MOV r0,#0xFFFFFFFF could be assembled as MVN r0,#0. [davespace]_ Token ----- Token : sequence of characters having a collective meaning. .. _g-builds does: ------------- Or create does> Michael Ham (https://galileo.phys.virginia.edu/classes/551.jvn.fall01/primer.htm#create) has called the word pair CREATE...DOES>, the “pearl of Forth”. CREATE is a component of the compiler, whose function is to make a new dictionary entry with a given name (the next name in the input stream) and nothing else. DOES> assigns a specific run-time action to a newly CREATEd word. .. _folding: Folding ------- Constant folding is a well known technique in optimisation. It means that if an operator works on constants the result may be replaced by a constant that is calculated at compile time. In Forth we generalise this to folding. Folding refers to all words that can be replaced by simpler words in case they receive constant data on the stack. [vanderhorst]_ “n-foldable” is mostly used on words that take n arguments as input. When the compiler encounters a n-foldable word, it looks back to see if the word is preceded by n literals (or constants), puts them on the stack, calls the word, and compiles the result as a literal. .. _inlining: Inlining -------- Inlining means replacing a Forth word with its constituents. This technique is very important in Forth, more so than in other languages, due to the small size of Forth words. Inlining is always a winner in speed, and mostly even also a winner with regard to space. Even more important is the fact that inlining allows folding to be applied across constituent words. This applies to high level and low level code alike. Inlining high level code is trivial. A further inlining stage replaces a high level definition that only calls code words, by a code definition which concatenates the code words. [vanderhorst]_ Inlining means taking the code of a word, and putting it in place of a call to this word (saving the cost of a call, usually at the cost of memory) Inlining Example (Classic Kernel, NON -RA) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ First the Word "42+" is defined and called by "insert-here" which has to branch to "42+". No Inlining is used. :: : 42+ 42 + ; ok. see 42+ 20000340: B500 push { lr } 20000342: 362A adds r6 #2A 20000344: BD00 pop { pc } ok : insert-here 42+ ; ok. see insert-here 2000035A: B500 push { lr } 2000035C: F7FF bl 20000340 --> 42+ 2000035E: FFF0 20000360: BD00 pop { pc } ok. .. warning:: Inlining will fail if there are PC-relative BL opcodes in the definition to be inlined so carefully check the definition(s) in question using the disassembler before specifying INLINE flag or INLINE, Now Inlining is used, note that "insert-here" now includes the code from "42+" rather than branching to it. :: : 42+ 42 + inline ; see 42+ 20000422: B500 push { lr } 20000424: 362A adds r6 #2A 20000426: BD00 pop { pc } : insert-here 42+ ; see insert-here 2000043A: B500 push { lr } 2000043C: 362A adds r6 #2A 2000043E: BD00 pop { pc } .. note:: Can Inline be used later within "insert-here" instead of in 42+ ? No, this would only result in "insert-here" being Inlined if called by a later Word. :: : 42+ 42 + ; see 42+ 2000044A: B500 push { lr } 2000044C: 362A adds r6 #2A 2000044E: BD00 pop { pc } : insert-here 42+ inline ; see insert-here 20000462: B500 push { lr } 20000464: F7FF bl 2000044A --> 42+ 20000466: FFF1 20000468: BD00 pop { pc } .. seealso:: :ref:`Convert your Classic Kernel to RA` .. _smudge: Smudge ------ Finishes a definition by flushing all flash buffers and inserts a link into the dictionary chain, making the new definition visible. Vocabularies ------------ July 2017, *great news!* :ref:`Manfred Mahlow's` Final Release of VOCs extension for Mecrisp-Stellaris 2.3.6-hook-find (vocs-0.6.2-FR) has arrived for testing. See the new :ref:`GPIO MODE Demo` Amforth ^^^^^^^ In amforth there is a word that can place newly defined words in wordlists automatically. e.g. a word called foo:bar is placed as bar in wordlist foo. It is like a sibling of a dot (colon)-recognizer that can detect the foo:bar notation and searches bar in foo (only). This word does not affect the definition wordlist or the search order, not even temporarily. [mtrute]_ .. index:: lshift .. _ex.lshift: lshift ------ Q: What does the LSHIFT Word do ? Here are the Dictionary definitions of the *SHIFT* Words. +-------------------------------------------------------------------------------------------------------+ | *exactly ANS, some logical extensions* | +===============+===============================+=======================================================+ | arshift | ( x1 u - - x2 ) | Arithmetric right-shift of u bit-places | +---------------+-------------------------------+-------------------------------------------------------+ | rshift | ( x1 u - - x2 ) | Logical right-shift of u bit-places | +---------------+-------------------------------+-------------------------------------------------------+ | lshift | ( x1 u - - x2 ) | Logical left-shift of u bit-places | +---------------+-------------------------------+-------------------------------------------------------+ Example ^^^^^^^ :: : gpiob_bsrr_bs9 %1 9 LSHIFT gpiob_bsrr ! ; \ gpiob_bsrr_bs9 GIOB BSRR Register ^^^^^^^^^^^^^^^^^^ This is a 32 bit register and the picture below is taken from page 159 of the official STM :download:`STM32F0xx Reference Manual` Table 8.4.7 ~~~~~~~~~~~ .. image:: pics/stm32f0-GPIOx_BSRR.jpg These bits are write-only. A read to these bits returns the value 0x0000. Note: If both BSx and BRx are set, BSx has priority. ======================= ====================================== ================================================= BIT 0 1 ======================= ====================================== ================================================= **BS0** No Action **SETS** BIT 0 **BR0** No Action **RESETS** BIT 0 ======================= ====================================== ================================================= How does it work ? ~~~~~~~~~~~~~~~~~~ There is a "BSRR" register for every GPIO Port on the chip, and this example applies to GPIOB. Every one of the 16 bits in GPIOB can be SET (1) or RESET (0) by storing a 1 in either its BS or BR Bitfield respectively. Suppose we want to SET BIT 9 in GPIOB ? What we do is store a "1" to the BS9 position of the GIOB BSRR Register above. There are many ways to do this, let's look at some of them. 1) looking at the picture above we can store the binary value of %1000000000 into GIOB_BSRR. The "1" will only set BIT 9 and the "0"'s will have no effect on the other bits. :: %1000000000 GIOB_BSRR ! 2) Binary %1000000000 is equal to decimal 512 so we could use that instead, exactly the same thing would happen, BIT 9 would be SET. :: 512 GIOB_BSRR ! 3) Hexadecimal $200 is also equal to %1000000000, so we could use that to set BIT 9 :: $200 GIOB_BSRR ! Which one do you prefer ? The binary one does relate directly to the BIT in question, but it has a LOT of "0"'s which are painful to type and painful to check. Decimal or Hex have the same effect but are mentally harder to equate to BIT 9 in Table 8.4.7. above. Here is a alternative way to look at BIT 9 after it is SET and this is just a table of bits 0 to 31 showing bit 9 is set, and all the others are 0. lines 1 and 2 are the bit number and line 3 is the bit value. :: 3322222222221111111111 10987654321098765432109876543210 00000000000000000000001000000000 So back to the original question. The LSHIFT word is a short way to specify BIT 9 and still maintain a easy mental relationship to Table 8.4.7. above. This is how it works. The LSHIFT Word takes two parameters, the first parameter is the NUMBER TO BE SHIFTED, and the other is how many TIMES TO SHIFT THE NUMBER LEFT. In our example. "1" is shifted 9 times left using the syntax below. :: %1 9 lshift Which results in the number 1 :: 3322222222221111111111 10987654321098765432109876543210 00000000000000000000000000000001 being shifted into BIT POSITION 9 which is what we want. :: 3322222222221111111111 10987654321098765432109876543210 00000000000000000000001000000000 We then store that number into GIOB_BSRR like so, which in English reads "shift one, 9 spaces left then store the result into the GPIOB_BSRR register. :: %1 9 lshift GPIOB_BSRR ! .. seealso:: Our :ref:`example` above is a template that was generated automatically, no one wrote it. See :ref:`CMSIS-SVD` for more details. C Language also Left Shifts ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Mecrisp-Stellaris Forth isnt the only programming language to left shift bits, look at the following include code by Keil. This code is to define GPIO_MODER_MODE0 :: #define GPIO_MODER_MODE0_Pos (0U) #define GPIO_MODER_MODE0_Msk (0x3UL << GPIO_MODER_MODE0_Pos) /*!< 0x00000003 */ #define GPIO_MODER_MODE0 GPIO_MODER_MODE0_Msk I do it this way in Forth ~~~~~~~~~~~~~~~~~~~~~~~~~ :: : GPIOC_MODER_MODER0 ( %XX -- ) 0 lshift GPIOC_MODER bis! ; \ GPIOC_MODER_MODER0 %01 constant OUTPUT OUTPUT GPIOC_MODER_MODER0 \ Configure GPIOC_0 as a OUTPUT Loop Unrolling -------------- Loop unrolling, also known as loop unwinding, is a loop transformation technique that attempts to optimize a program's execution speed at the expense of its binary size .. _postpone-example: Postpone -------- (My thanks to rdrop-exit on irc.freenode #forth for helping me understand this.) postponing has the effect of delaying the normal compile-time action of a word, but what that action normally is depends on whether the word being postponed is immediate or not Example ^^^^^^^ :: : THINKING ( -- ) ." I'm deciding... " ; : NEWIF ( x -- ) postpone THINKING postpone IF ; immediate : FOO ( x -- ) newif ." yes" else ." no" then ; 1 FOO I'm deciding... yes ok. 0 FOO I'm deciding... no ok .. note:: THINKING and FOO are NON-IMMEDIATE Words, IF and NEWIF are IMMEDIATE Words. See :ref:`Dictionary Flags` :: Flags: 00000630 Name: if Flags: 00000000 Name: FOO Flags: 00000010 Name: NEWIF Flags: 00000000 Name: THINKING FLAG Codes ^^^^^^^^^^ Taken from mecrisp-stellaris-2.4.7/mecrisp-stellaris-source/common/datastackandmacros.s =========== ========================================================================================================= Flag Description =========== ========================================================================================================= 0x0000 Visible, non-immediate 0x0010 Immediate 0x0030 Immediate+Inline means: Immediate, Compile-Only =========== ========================================================================================================= .. _rlit: Registerliteral, ---------------- This is used to generate RELATIVE machine code to use when INLINING. Registerliteral, generates the shortest possible sequence to get x into given low Register using movs adds lsls sequences. 1. M0: A movs-lsls-adds… sequence 2. M3/M4: movs / movs-mvns / movw / movw-movt This is used instead of the command "ldr=" which generates ABSOLUTE addressing. A movs adds lsls sequences needs to be used instead to load a literal in a register. Example ^^^^^^^ :: : rlit [ 1000 0 registerliteral, ] ; see rlit 20000654: B500 push { lr } 20000656: 20FA movs r0 #FA 20000658: 0080 lsls r0 r0 #2 2000065A: BD00 pop { pc }