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/>.
19 #include "ScriptableAnalyzer.h"
20 #include "ScriptEngine.h"
21 #include "script/ScriptException.h"
29 #define ANALYZER_PATH "./analyzers/:./"
33 static std::string
locateScript(const std::string
& name
) {
34 static const std::string
path(ANALYZER_PATH
);
35 static const std::string
delimiters(":");
36 static const std::string empty
;
40 j
= path
.find_first_of(delimiters
, i
);
43 if( j
!= std::string::npos
)
44 test
= path
.substr(i
, j
) + name
+ ".lua";
46 test
= path
.substr(i
) + name
+ ".lua";
48 std::ifstream
f( test
.c_str() );
53 } while( j
!= std::string::npos
);
58 using script::ScriptMethod
;
59 using script::ScriptUtil
;
61 ScriptMethod
<ScriptableAnalyzer
> ScriptableAnalyzer::sm_methods
[] = {
62 ScriptMethod
<ScriptableAnalyzer
>( "breakSystem", &ScriptableAnalyzer::script_breakSystem
),
63 ScriptMethod
<ScriptableAnalyzer
>( "register", &ScriptableAnalyzer::script_register
),
64 ScriptMethod
<ScriptableAnalyzer
>( "ioregister", &ScriptableAnalyzer::script_ioregister
),
67 ScriptableAnalyzer::ScriptableAnalyzer(Core
*core
, ScriptEngine
*vm
,
68 const char *scriptname
)
69 : Analyzer(core
), script::Scriptable(vm
), scriptname(scriptname
) {
71 std::string path
= locateScript(scriptname
);
73 throw ScriptException(
74 util::format("Unable to locate script %s") % scriptname
);
76 methodBase
= ScriptUtil
<ScriptableAnalyzer
,Scriptable
>::addMethods( this,
77 sm_methods
, sizeof(sm_methods
)/sizeof(sm_methods
[0]) );
80 compileFile( path
.c_str() );
81 registerClass(scriptname
);
82 setNumber("pcBytes", core
->pcBytes());
83 } catch( script::ScriptException
& ex
) {
84 throw ScriptException( ex
.message() );
88 ScriptableAnalyzer::~ScriptableAnalyzer() {
90 const char *method
= "finish";
91 if( hasMethod(method
) ) {
93 Scriptable::call(0, 0);
96 unregisterClass(scriptname
);
97 } catch( script::ScriptException
& ex
) {
99 * Throwing exceptions in destructors is a bad idea
100 * see http://www.kolpackov.net/projects/c++/eh/dtor-1.xhtml
101 * for an interesting overview of the problems
103 //throw ScriptException( ex.message() );
104 std::cerr
<< "~ScriptableAnalyzer: " << ex
.message() << std::endl
;
108 void ScriptableAnalyzer::callHelper(const char *method
) {
110 if( hasMethod(method
) ) {
112 Scriptable::call(0, 0);
114 } catch( script::ScriptException
& ex
) {
115 throw ScriptException( ex
.message() );
119 void ScriptableAnalyzer::callHelperb(const char *method
, bool b
) {
121 if( hasMethod(method
) ) {
124 Scriptable::call(1, 0);
126 } catch( script::ScriptException
& ex
) {
127 throw ScriptException( ex
.message() );
131 void ScriptableAnalyzer::callHelper(const char *method
, float x
) {
133 if( hasMethod(method
) ) {
136 Scriptable::call(1, 0);
138 } catch( script::ScriptException
& ex
) {
139 throw ScriptException( ex
.message() );
143 void ScriptableAnalyzer::callHelperb(const char *method
, float x
, bool b
) {
145 if( hasMethod(method
) ) {
149 Scriptable::call(2, 0);
151 } catch( script::ScriptException
& ex
) {
152 throw ScriptException( ex
.message() );
156 void ScriptableAnalyzer::callHelper(const char *method
, float x
, float y
) {
158 if( hasMethod(method
) ) {
162 Scriptable::call(2, 0);
164 } catch( script::ScriptException
& ex
) {
165 throw ScriptException( ex
.message() );
169 int ScriptableAnalyzer::methodCall(int i
) {
170 return ScriptUtil
<ScriptableAnalyzer
,Scriptable
>::methodCall(this, i
, methodBase
,
171 sm_methods
, sizeof(sm_methods
)/sizeof(sm_methods
[0]) );
174 void ScriptableAnalyzer::reset(unsigned int type
) {
175 const char *methodName
= "reset";
176 callHelper(methodName
, type
);
179 void ScriptableAnalyzer::trace(dword address
) {
180 const char *methodName
= "trace";
181 callHelper(methodName
, address
);
184 void ScriptableAnalyzer::step(lword ticks
) {
185 const char *methodName
= "step";
188 setNumber("ticks", ticks
);
190 if( hasMethod(methodName
) ) {
191 pushMethod(methodName
);
192 vm
->pushNumber(ticks
);
193 Scriptable::call(1, 0);
195 } catch( script::ScriptException
& ex
) {
196 throw ScriptException( ex
.message() );
200 void ScriptableAnalyzer::readRegister(unsigned int r
, byte val
) {
201 const char *methodName
= "readRegister";
202 callHelper(methodName
, r
, val
);
205 void ScriptableAnalyzer::writeRegister(unsigned int r
, byte val
) {
206 const char *methodName
= "writeRegister";
207 callHelper(methodName
, r
, val
);
210 void ScriptableAnalyzer::readByte(unsigned int addr
, byte val
) {
211 const char *methodName
= "readByte";
212 callHelper(methodName
, addr
, val
);
215 void ScriptableAnalyzer::writeByte(unsigned int addr
, byte val
) {
216 const char *methodName
= "writeByte";
217 callHelper(methodName
, addr
, val
);
220 void ScriptableAnalyzer::readFlash(unsigned int addr
, byte val
) {
221 const char *methodName
= "readFlash";
222 callHelper(methodName
, addr
, val
);
225 void ScriptableAnalyzer::writeFlash(unsigned int addr
, word val
) {
226 const char *methodName
= "writeFlash";
227 callHelper(methodName
, addr
, val
);
230 void ScriptableAnalyzer::fetchOperand(word val
) {
231 const char *methodName
= "fetchOperand";
232 callHelper(methodName
, val
);
235 void ScriptableAnalyzer::push(byte val
) {
236 const char *methodName
= "push";
237 callHelper(methodName
, val
);
240 void ScriptableAnalyzer::pop(byte val
) {
241 const char *methodName
= "pop";
242 callHelper(methodName
, val
);
245 void ScriptableAnalyzer::jump(dword address
, bool push
) {
246 const char *methodName
= "jump";
247 callHelperb(methodName
, address
, push
);
250 void ScriptableAnalyzer::skip() {
251 const char *methodName
= "skip";
252 callHelper(methodName
);
255 void ScriptableAnalyzer::call(dword address
, bool push
) {
256 const char *methodName
= "call";
257 callHelperb(methodName
, address
, push
);
260 void ScriptableAnalyzer::ret(bool interrupt
) {
261 const char *methodName
= "ret";
262 callHelperb(methodName
, interrupt
);
265 void ScriptableAnalyzer::sleep(unsigned int mode
) {
266 const char *methodName
= "sleep";
267 callHelper(methodName
, mode
);
270 void ScriptableAnalyzer::systemBreak() {
271 const char *methodName
= "systemBreak";
272 callHelper(methodName
);
275 void ScriptableAnalyzer::interrupt(unsigned int vector
, unsigned int addr
) {
276 const char *methodName
= "interrupt";
277 callHelper(methodName
, vector
, addr
);
280 int ScriptableAnalyzer::script_breakSystem(const char *funcName
) {
285 int ScriptableAnalyzer::script_register(const char *funcName
) {
286 if ( vm
->top() != 1 || vm
->getType(1) != script::VM::Number
)
287 throw script::ScriptException("expects a register index");
290 int r
= (int)vm
->toNumber(1);
291 byte val
= core
->getR( r
);
292 vm
->pushNumber( val
);
294 } catch( util::Exception
& ex
) {
295 throw script::ScriptException( ex
.message() );
299 int ScriptableAnalyzer::script_ioregister(const char *funcName
) {
300 if ( vm
->top() != 1 || vm
->getType(1) != script::VM::Number
)
301 throw script::ScriptException("expects a io register index");
304 int r
= (int)vm
->toNumber(1);
305 byte val
= core
->getIoreg( r
);
306 vm
->pushNumber( val
);
308 } catch( util::Exception
& ex
) {
309 throw script::ScriptException( ex
.message() );