Back to General discussions forum
Hi Friends!
For some time already I'm slowly working on AVR assembler emulator which we can use in future for creating new problems. Currently only small subset of instructions is implemented, but I want to share the current state of the project - probably seeking for some advice, help in testing etc.
Excuse me for this post is bit too long.
Here is the Emulator page and the Github Project.
But what is important - this thing works differently from i4004 emulator. It emulates not the instruction list itself, but the compiled hex code (intel hex file format). This means that:
avrasm32
with all its features;Emulator has "Compile" button also (it sends the code for compilation to remote server where
AvrA compiler is used). Though different AVR devices are in many
ways compatible, we emulate one of the most popular - ATMega8
, which has about 8k
memory for
code.
EXAMPLE
Copy this sample program to the emulator and click "Compile":
.include "m8def.inc"
.org $0
; output few bytes to UART
ldi r16, 'H'
out UDR, r16
ldi r16, 'i'
out UDR, r16
ldi r16, '!'
out UDR, r16
some hex compiled code should appear below - now click "Execute" to execute this code. Some output registers will be shown to have non-zero value - and the "output console" will show "Hi!" message.
In this case "output console" is the honest thing, not some imaginary device. The emulated chip ATMega8
have UART pins and real serial terminal could be used with it.
ldi
or "load immediate" just loads value to register;out
sends data from register to "io-register" - or rather some hardware endpoint
controlling some peripherial device;UDR
is defined in m8def.inc
file (wehave a copy on a compilation server) and is
just the address of "io-register" assigned to UART.CURRENT TROUBLES
The main problem is that AVR instruction set is comparatively huge. Right now I implemented instructions like:
add
, adc
, sub
, subi
, sbc
, sbci
, inc
, dec
;ldi
, mov
, in
, out
(though the last two work only with few io-regs now);breq
, brsh
, brcc
etc.).But I'm already facing the fact that I could not be sure results of instructions are always correct especially in regard of flags (there are flags of carry, zero, negative, overflow, half-carry and few more). If anyone can think of whimsical self-test based on these instructions - it would be cool...
Another concern is that the code of executor looks somewhat horrible because of parsing hex instruction codes (which sometimes have a whimsical bit ordering). Perhaps someone could provide some insight on reorganizing this part?
The third issue is that, I suspect, this emulator would not be very fast as i often needs to perform many lines in scripting language to calculate a single instruction. I haven't conducted performance tests yet.
THE FUTURE
We are going to have the first avr-asm related problems as soon as some more popular instructions are implemented. I hope it is ok not to wait until all possible ones are here?
Meanwhile I invite you to check this stuff, if you are interested, and tell if you see some horrible bugs, flaws or have some cool suggestions.
I provided no documentation still, but as this is far more modern chip, you can easily find some good guides, and among them two official papers:
P.S. Our emulator still have some cheating - on startup of real device we could not be sure
registers are initialized to 0 and UART for example needs to be configured with few more instructions.
However we can pretend this was done in bootloader code after which jump was performed to address
of $000
(that is an often practice).
Hi Rodion,
Sorry I don't have much time to look at this right now as I have a dog that needs a walk, but...
It looks good. I'll be glad to help anywhere I can and certainly with testing. I'll start reading about AVR.
Your example code needs an extra OUT instruction to handle the "!".
The emulator appears to just ignore instructions it doesn't understand. I think it should give an error message.
Graeme Hi! I've added the missing line, thank you!
You are right - now it just skips the instructions which failed to match with any of the if-else-ifs... It is not convenient - I'll try to find a countermeasure for this...
LDI & MOV seem to work ok. I have some tests to check ADD, i.e.
ID Test Result
-- ---- ------
A 1+255 ZHC
B 0+0 Z
C 0+1 no flags
D 7+8 no flags
E 7+120 no flags
F 7+9 H
G 8+120 VNH
H 8+121 VNH
I 21+107 VNH
J 32+100 VN
K 31+100 VNH
L 16+116 VN
M 126+126 VNH
N 129+129 SVC
O 136+1 SN
P 255+2 HC
I've written code for the first
.include "m8def.inc"
.org $0
;R20 holds test ID
;R21 & R22 are added
LDI R20,'A' ;add 1+255 expect flags ZHC
LDI R21,1
LDI R22,255
ADD R21,R22
BRCC fail
BRNE fail
BRHC fail
BRMI fail
BRVS fail
BRBS 4,fail
;Now do tests B-P
LDI R16, 'O'
OUT UDR, R16
LDI R16, 'K'
OUT UDR, R16
RJMP end ;not implemented!
BRCS end
BRCC end
;never gets here
fail: LDI R16, 'F'
OUT UDR, R16
LDI R16, 'a'
OUT UDR, R16
LDI R16, 'i'
OUT UDR, R16
LDI R16, 'l'
OUT UDR, R16
LDI R16, ' '
OUT UDR, R16
OUT UDR, R20
end:
I'm running into problems already
a) I don't know if all the BR instructions I've used have been implemented
b) I can't do an unconditional jump
c) I'm going to have more than 63 bytes of code so I need a way of doing longer jumps
d) A better way of printing a string would be nice
Graeme, Hi!
Thanks for the insight. I think it is just of the kind I needed - a guidance about most wanted commands. I'll try to make the requested improvements right now.
As about BRXX
commands I believe that any of them which is the clone of some BRBC/BRBS
is
working - i.e. any which tests some of the flags (bits in SREG
). I'm not sure if there are other
conditional branches however...
UPD: I've added rjmp
(for jumps) and lpm
(to use strings from ROM) as
"Hi People" example shows.
It seems that label addresses are in words rather than in bytes. Hope it works!
Also I've tried to add "not implemented" warning though I'm not sure all relevant places are covered.
UPD-2: Added push
, pop
, rcall
and ret
(examples strrev.asm
and subroutine.asm
) for
perhaps they could be useful.
Hi Rodion, that looks much better.
When I tried a CLZ instruction it reported
Execution error:
Not implemented instruction 9498
(Not implemented instruction 9498)
I haven't used the new string print mechanism, but when I use this code it fails because ADDing 0+0 is setting the V flag
.include "m8def.inc"
.org $0
;R20 holds test ID
;R21 & R22 are added
;R23 expected result
LDI R20,'A' ;add 1+255 expect flags ZHC 0
LDI R21,1
LDI R22,255
LDI R23,0
ADD R21,R22
BRCC fail1
BRNE fail1
BRHC fail1
BRMI fail1
BRVS fail1
BRBS 4,fail1
SUB R21,R23
BRNE fail1
LDI R20,'B' ;add 0+0 expect flags Z 0
LDI R21,0
LDI R22,0
LDI R23,0
ADD R21,R22
LDI R24,'C'
BRCS fail1
LDI R24,'Z'
BRNE fail1
LDI R24,'H'
BRHS fail1
LDI R24,'N'
BRMI fail1
LDI R24,'V'
BRVS fail1
LDI R24,'S'
BRBS 4,fail1
SUB R21,R23
BRNE fail1
RJMP testf
fail1: RJMP fail3
testf: LDI R16,'O'
OUT UDR,R16
LDI R16,'K'
OUT UDR,R16
RJMP end
fail3: LDI R16,'F'
OUT UDR,R16
LDI R16,'a'
OUT UDR,R16
LDI R16,'i'
OUT UDR,R16
LDI R16,'l'
OUT UDR,R16
LDI R16,' '
OUT UDR,R16
OUT UDR,R20
LDI R16,' '
OUT UDR,R16
OUT UDR,R24
end:
> When I tried a CLZ instruction it reported
That's true, CLC/CLZ
and others are not yet implemented though I see now it is inconvenient. I'll try to do this asap.
> ADDing 0+0 is setting the V flag
Wow. Really, and not only for 0+0... This do not look correct, I'll investigate! Thank you very much!
UPD
CLx / SEx
for flags (they are synonyms of BCLR
and BSET
, I think)P.S. just realized that would be nice to see flags in emulator web-page.
Thanks. No problems with ADDing now. All flags are fine.
If someone gets an error like Not implemented instruction 9475 how can they find out which instruction it is they have to stop using?
UPD: I can go to https://www.onlinedisassembler.com/odaweb/ and enter it in reverse order, i.e. 7594, and it tells me.
Thanks for the link! As the emulator works with compiled hex instruction codes, I myself would be very glad to find a good way to determine the instruction by code. Before your link I've used the table from wikipedia.
http://lyons42.com/AVR/Opcodes/AVRAllOpcodes.html is good for looking up the op code.
Hi Rodion,
I think what you've done so far with this is really good, although I'd prefer the Not implemented xxyy error message to be reported the other way around as yyxx.
I haven't had any problems with the speed of the emulator.
I don't think you need to implement all the instructions before creating an avr-asm problem.
I've tried VMLAB and Atmel Studio and both are fine for compiling/simulating/debugging, but I haven't been able to get to see the output I've written to UDR. With VMLAB, I tried the TTY component, but it didn't like my 64bit version of Windows. With Atmel Studio, I installed version 7, then found that the Terminal Window extension only worked with versions 5 & 6. For the code I've written, I've used your emulator, which worked perfectly well.
When you get around to implementing more instructions, I'd suggest compare/xor/and/or/shift/rotate.
Hi Graeme! Sorry for delay in moving this forward.
> but I haven't been able to get to see the output I've written to UDR
That's correct, as mentioned above UART needs to be initialized in real devices with few additional instructions. If you peek in "Atmega8 pdf" it can be found in article "USART Initialization" along with sample code.
In emulator we pretend that some initialization was already performed to save people from thinking about such hardware-related
code (it is not a cheat, because real chips too may be programmed for such behavior by starting with custom "bootloader"
in upper memory address and then jumping to $000
to start the user's code).
Though I'm not sure if this decision is right...
> I'd suggest compare/xor/and/or/shift/rotate.
Thanks for suggestion! I'll proceed in this direction soon!
Hi! Few more instructions wre added:
cp, cpi, cpse, com, neg, swap, asr, lsr, ror, and, andi, or, ori, eor
I've found with surprise that lsl
and rol
are not separate instructions but instead are
simply encoded as add
or addi
of register to itself (so they are already supported).
Well done to Signum_X for reaching the rank of cardinal.
Why post this here? He says he's "Mainly an 8-bit AVR Assembly Programmer"