2 * avr-sim: An atmel AVR simulator
3 * Copyright (C) 2008 Tom Haber
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "Instruction.h"
21 #include "Registers.h"
23 #include "AccessViolation.h"
24 #include "RuntimeException.h"
39 #define SPMCSR_LOWERBITS 0x1f
40 #define BUFFERSIZE 1<<pagebits
41 #define DEFAULT_VALUE 0xff
42 #define setBusy() spmcsr->set( *spmcsr | BUSY );
44 // TODO these are cycles for 8Mhz!
45 #define ERASE_CYCLES 36000
46 #define WRITE_CYCLES 36000
47 #define RESET_CYCLES 4
51 static unsigned int log2Int(unsigned int v
) {
52 // find the log base 2 of 32-bit v
54 static const int MultiplyDeBruijnBitPosition
[32] = {
55 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
56 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
59 v
|= v
>> 1; // first round down to power of 2
66 return MultiplyDeBruijnBitPosition
[(v
* 0x077CB531UL
) >> 27];
69 Flash::Flash(Bus
& bus
, unsigned int size
, int pagesize
)
70 : Hardware(bus
), Memory(size
) {
72 pagebits
= log2Int(pagesize
);
74 Memory::fill(DEFAULT_VALUE
);
75 pagemask
= (0xffffffff >> (31 - (pagebits
)));
77 buffer
= new unsigned char[BUFFERSIZE
];
78 memset(buffer
, DEFAULT_VALUE
, BUFFERSIZE
);
88 void Flash::fill(unsigned int offset
, byte val
, unsigned int size
) {
89 if( offset
+ size
> siz
)
90 throw AccessViolation("Flash::fill: writing too much to memory");
92 memset( mem
+ offset
, val
, size
);
95 bool Flash::attachReg(const char *name
, IORegister
*reg
) {
96 if( strcmp(name
, "spmcsr") == 0 )
101 reg
->registerHW(this);
105 bool Flash::finishBuild() {
106 return ( spmcsr
!= 0 );
109 void Flash::regChanged( IORegister
*reg
) {
110 if( reg
== spmcsr
) {
111 bus
.setBreakDelta(RESET_CYCLES
, this);
115 void Flash::storeProgramMemory(dword Z
, byte r0
, byte r1
) {
116 pageoffset
= (Z
& pagemask
);
117 pagenum
= Z
>> pagebits
;
123 bus
.reassignBreakDelta(ERASE_CYCLES
, this);
128 bus
.clearBreak(this);
132 bus
.clearBreak(this);
136 if( pageoffset
>= BUFFERSIZE
)
137 throw AccessViolation("Tried to write beyond RWW buffer boundaries");
139 buffer
[pageoffset
] = r0
;
140 buffer
[pageoffset
+1] = r1
;
141 spmcsr
->set( *spmcsr
& ~SPMCSR_LOWERBITS
);
142 bus
.clearBreak(this);
147 bus
.reassignBreakDelta(WRITE_CYCLES
, this);
152 void Flash::resetRWW() {
153 if( (*spmcsr
& BUSY
) == 0 )
154 spmcsr
->set( *spmcsr
& ~(BUSY
|SPMCSR_LOWERBITS
) );
157 void Flash::pageErase() {
158 int size
= BUFFERSIZE
;
159 int addr
= pagenum
* size
;
160 fill( addr
, DEFAULT_VALUE
, size
);
163 void Flash::pageWrite() {
164 int size
= BUFFERSIZE
;
165 int addr
= pagenum
* size
;
166 write( addr
, buffer
, size
);
183 throw util::RuntimeException("Flash::step: invalid state");
186 memset(buffer
, DEFAULT_VALUE
, BUFFERSIZE
);
187 spmcsr
->set( *spmcsr
& ~(SPMCSR_LOWERBITS
) );