AVR Instructions ################ .. include:: /header.inc .. vim:filetype=rst spell: The AVR processor family supports around 130 unique instructions. We could simply start implementing each of them, one at a time, as we build our simulator. But that would take more effort than we need in this class. Since we have a nice example ``C`` program to use as a starting point, let's ask the ``avr-gcc`` assembler to help us select instructions to implement in our simulator. To generate AVR assembly language from a high-level ``C`` program, we need a few more components for our ``Modular Make`` setup. For now, keep this `Makefile`` setup seprate from the one we aare using for the C++ project (I will get the two merged together soon!) Here are the new ``Makefile`` components we need: .. literalinclude:: avr-sum/Makefile :linenos: :caption: Makefile .. literalinclude:: avr-sum/mk/avr-files.mk :linenos: :caption: mk/avr-files.mk .. literalinclude:: avr-sum/mk/avr-tools.mk :linenos: :caption: mk/avr-tools.mk .. literalinclude:: avr-sum/mk/avr-utils.mk :linenos: :caption: mk/avr-utils.mk .. literalinclude:: avr-sum/mk/avr-build.mk :linenos: :caption: mk/avr-build.mk You should add the ``debug.mk``, ``help.mk`` and ``os_detect.mk`` files, with their Python helper files as well. Test your setup by running this command: .. command-output:: make help :cwd: avr-sum For now, we will skip discussing exactly what is happening in this build system. Example AVR Assembly Language ***************************** To demonstrate how this system works, here is a streamlined example of AVR assembly language distilled from compiling the ``C`` code we looked at earlier: .. note:: It is not important that you understand this code for now, we will get to that. For now, all we are focusing on is how we will build programms written in this strange new language! .. literalinclude:: avr-sum/avr/sum/avr-sum.S :linenos: :caption: avr/sum/avr-sum.S .. note:: Notice that we name our assembly language with a ``.S`` extension. This is important because it tells the compiler that a human wrote this. Compiler generated assembly language files end with a lower case ``.s``. Let's run the build system and get a look at these files: .. command-output:: make clean :cwd: avr-sum .. command-output:: make :cwd: avr-sum After these commands run, you will find two important files that have been constructed by the build system: * avr-sum.hex - a file ready to load on a real AVR board * avr-sum.lst - a listing file showing the assembly language produced from your code Intel Hex File ************** Rather than produce some form of "executable" file for this processor, the compiler and linker produce a data file containing exactly the binary code to be loaded into the memory of the processor. We will eventually use a loader program to put our code onto a real board. For mow, we will use this data file to load up our simulator's memory. Here is the "hex" data file produced: .. literalinclude:: avr-sum/avr-sum.hex :linenos: :caption: avr-sum.hex The format of this data file is pretty simple. Each line in the file contains exactly 16 bytes to be loaded into the processors program memory area. Here are the basic parts of each line, which Intel calls a "record". Here is a document detailing this data file format. It has been in use since the 1970s! * :download:`/files/intelhex.pdf` Here is a start on a C++ class that can read this data file. You can use this code to buuild your simulators memory load routine: .. literalinclude:: loader/Loader.h :linenos: :caption: include/Loader.h And here is the implementation: .. literalinclude:: loader/Loader.cpp :linenos: :caption: lib/Loader.cpp .. warning:: This code is not complete, you still need to convert the hex data into data you can actually load into your simulator's memeory. The Listing File **************** In this build system, the compiler does not generate the assembly listing we might like to see. Instead another tool, ``obj-dump`` generates a listing file, and that is what we will peek at next: .. literalinclude:: avr-sum/avr-sum.lst :linenos: :caption: avr-sum.lst Notice an important detail here. Each line of assembly code is preceeded with the address where that instruction will be located in the instruction memory area, and the exact binary bits recorded there (in hex, of course). Looking through this listing shows us that most instructions are 16-bits long, shown as four hex characters, and a few instructions are 32-bits long, shown as eight hex characters. For our present work, we simply need ot look at the instructions used in implementing this program. Here is an alphabetical listing of those instructions: +----+-----+---+ |MNEM|Op1 |Op2| +====+=====+===+ |ADD |Rd |Rr | +----+-----+---+ |ADC |Rd |Rr | +----+-----+---+ |ADIW|Rd |K | +----+-----+---+ |AND |Rd |Rr | +----+-----+---+ |BREQ|k | | +----+-----+---+ |BRLT|label| | +----+-----+---+ |CALL|K | | +----+-----+---+ |LDI |Rd |K | +----+-----+---+ |LDS |Rd |K | +----+-----+---+ |LSL |Rd | | +----+-----+---+ |LSR |Rd | | +----+-----+---+ |MOV |Rd |Rr | +----+-----+---+ |MOVW|Rd |Rr | +----+-----+---+ |NOT |Rd | | +----+-----+---+ |OR |Rd |Rr | +----+-----+---+ |RET | | | +----+-----+---+ |RJMP|K | | +----+-----+---+ |ROL |Rd | | +----+-----+---+ |SBCI|Rd |K | +----+-----+---+ |SBIW|Rd |K | +----+-----+---+ |STS |K |Rr | +----+-----+---+ |SUBI|Rd | k | +----+-----+---+ Obviously, we need to set our ``Fetch Unit`` up to load each instruction and pass those data bytes to the ``Decode Unit``. As mentioned earlier, we will ask the ``Fetch Unit`` to grab atwo chunks from the instruction meneory and let the decoder logic figure out if the second chunk is needed. That is not that many instructions to cope with! But, before we can get very far in this adventure, we need to see how each has been encoded by the manufacturer of this chip. AVR Documentation ***************** We have the pieces needed to build our ``Fetch Unit`` for the simulator. Fortunately, "fetching" is independent of the actual instructions we will be processing. However, before w can go much further, we really need to look at the actual chip documentation. Here are the files you will need: ATtiny85 Data Sheet =================== This is the master document detailing everything inside this tiny chip. For now, all we are interested in is the Instruction Setfor this chip; * :download:`/files/ATtiny85_Datasheet.pdf` AVR Instructuction Summary ========================== This document is a summary of all instructions supported by the AVR family of processors. This is more detailed data on those instructions, but remember, our tiny chip does not support all of the instructuons listed in this reference. * :download:`/files/AVR_Instruction_Summary.pdf` AVR Instruction Encoding ======================== This last document provides information that can be produced with a bit of coding and the tools provided above. Basically, we want to discover how each instruction is encoded by the manufacturer. This information is essential in building our decoder, which is coming up next! * :download:`/files/AVR_Instruction_Encoding.pdf` Python Listing File Processor ***************************** Just for fun (!), I put together short Python program that reads a listing file produced by our build system, and shows the binary encoding for each instruction it find. Try this code out and see what it produces: .. literalinclude:: avr-assembly/code-extractor.py :linenos: :caption: code-extractor.py