version 0.5.2
[fw/sdcc] / sim / ucsim / avr.src / jump_inst.cc
1 /*
2  * Simulator of microcontrollers (jmp_inst.cc)
3  *
4  * Copyright (C) 1999,99 Drotos Daniel, Talker Bt.
5  * 
6  * To contact author send email to drdani@mazsola.iit.uni-miskolc.hu
7  *
8  */
9
10 /* This file is part of microcontroller simulator: ucsim.
11
12 UCSIM is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; either version 2 of the License, or
15 (at your option) any later version.
16
17 UCSIM is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 GNU General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with UCSIM; see the file COPYING.  If not, write to the Free
24 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25 02111-1307, USA. */
26 /*@1@*/
27
28 #include "avrcl.h"
29 #include "regsavr.h"
30
31
32 /*
33  * Indirect Jump
34  * IJMP
35  * 1001 0100 XXXX 1001
36  *____________________________________________________________________________
37  */
38
39 int
40 cl_avr::ijmp(t_mem code)
41 {
42   t_addr z;
43
44   z= ram->get(ZH)*256 + ram->get(ZL);
45   PC= rom->validate_address((PC & ~0xffff) | z);
46   //FIXME: analyze
47   return(resGO);
48 }
49
50
51 int
52 cl_avr::eijmp(t_mem code)
53 {
54   return(resGO);
55 }
56
57
58 /*
59  * Indirect Call to Subroutine
60  * ICALL
61  * 1001 0101 XXXX 1001
62  *____________________________________________________________________________
63  */
64
65 int
66 cl_avr::icall(t_mem code)
67 {
68   t_mem zl, zh;
69   t_addr z;
70   
71   push_addr(PC);
72   zl= ram->read(ZL);
73   zh= ram->read(ZH);
74   z= zh*256 + zl;
75   PC= (PC & ~0xffff) | (z & 0xffff);
76   //FIXME: analyze
77   tick(2);
78   return(resGO);
79 }
80
81
82 int
83 cl_avr::eicall(t_mem code)
84 {
85   return(resGO);
86 }
87
88
89 /*
90  * Return from Subroutine
91  * RET
92  * 1001 0101 0XX0 1000
93  *____________________________________________________________________________
94  */
95
96 int
97 cl_avr::ret(t_mem code)
98 {
99   t_addr a;
100
101   pop_addr(&a);
102   PC= rom->validate_address(a);
103   tick(3);
104   return(resGO);
105 }
106
107
108 /*
109  * Return from Interrupt
110  * RETI
111  * 1001 0101 0XX1 1000
112  *____________________________________________________________________________
113  */
114
115 int
116 cl_avr::reti(t_mem code)
117 {
118   t_addr a;
119
120   pop_addr(&a);
121   PC= rom->validate_address(a);
122   t_mem sreg= ram->read(SREG);
123   sreg|= BIT_I;
124   ram->write(SREG, sreg);
125   tick(3);
126   return(resGO);
127 }
128
129
130 /*
131  * Relative Jump
132  * RJMP k -2K<=k<=2K
133  * 1100 kkkk kkkk kkkk
134  *____________________________________________________________________________
135  */
136
137 int
138 cl_avr::rjmp_k(t_mem code)
139 {
140   long k= code & 0xfff;
141
142   if (k & 0x800)
143     k|= -4096;
144   PC= rom->validate_address((signed)PC + (signed)k);
145   tick(1);
146   return(resGO);
147 }
148
149
150 /*
151  * Relative Call to Subroutine
152  * RCALL k
153  * 1101 kkkk kkkk kkkk -1K<=k<=+1k
154  *____________________________________________________________________________
155  */
156
157 int
158 cl_avr::rcall_k(t_mem code)
159 {
160   t_addr k;
161
162   push_addr(PC);
163   k= code & 0xfff;
164   if (k & 0x800)
165     k|= ~0xfff;
166   PC= rom->validate_address((signed)PC + (signed)k);
167   tick(2);
168
169   return(resGO);
170 }
171
172
173 /*
174  * Compare Skip if Equal
175  * CPSE Rd,Rr 0<=d<=31, 0<=r<=31
176  * 0001 00rd dddd rrrr
177  *____________________________________________________________________________
178  */
179
180 int
181 cl_avr::cpse_Rd_Rr(t_mem code)
182 {
183   t_addr d, r;
184
185   d= (code&0x1f0)>>4;
186   r= ((code&0x200)>>5)|(code&0xf);
187   if (ram->read(r) == ram->read(d))
188     {
189       t_mem next_code= rom->get(PC);
190       int i= 0;
191       struct dis_entry *dt= dis_tbl();
192       while ((next_code & dt[i].mask) != dt[i].code &&
193              dt[i].mnemonic)
194         i++;
195       if (dt[i].mnemonic != NULL)
196         {
197           PC= rom->validate_address(PC + dt[i].length);
198           tick(1);
199         }
200       else
201         return(resINV_INST);
202     }
203   return(resGO);
204 }
205
206
207 /*
208  * Jump
209  * JMP k 0<=k<=4M
210  * 1001 010k kkkk 110k
211  * kkkk kkkk kkkk kkkk
212  *____________________________________________________________________________
213  */
214
215 int
216 cl_avr::jmp_k(t_mem code)
217 {
218   t_addr k;
219
220   k= ((code&0x1f0)>>3)|(code&1);
221   k= (k<<16)|fetch();
222   PC= rom->validate_address(k);
223   tick(2);
224   return(resGO);
225 }
226
227
228 /*
229  * Long Call to a Subroutine
230  * CALL k 0<=k<=64k/4M
231  * 1001 010k kkkk 111k
232  * kkkk kkkk kkkk kkkk
233  *____________________________________________________________________________
234  */
235
236 int
237 cl_avr::call_k(t_mem code)
238 {
239   t_addr k;
240
241   k= (((code&0x1f0)>>3)|(code&1))*0x10000;
242   k= k + fetch();
243   push_addr(PC);
244   PC= rom->validate_address(k);
245   tick(3);
246   return(resGO);
247 }
248
249
250 /*
251  * Branch if Bit in SREG is Set
252  * BRBS s,k 0<=s<=7, -64<=k<=+63
253  * 1111 00kk kkkk ksss
254  *____________________________________________________________________________
255  */
256
257 int
258 cl_avr::brbs_s_k(t_mem code)
259 {
260   int s, k;
261
262   k= (code&0x3f8)>>3;
263   s= code&7;
264   t_mem sreg= ram->get(SREG);
265   t_mem mask= 1<<s;
266   if (sreg & mask)
267     {
268       if (code&0x200)
269         k|= -128;
270       PC= rom->validate_address((signed)PC+k);
271       tick(1);
272     }
273   return(resGO);
274 }
275
276
277 /*
278  * Branch if Bit in SREG is Cleared
279  * BRBC s,k 0<=s<=7, -64<=k<=+63
280  * 1111 01kk kkkk ksss
281  *____________________________________________________________________________
282  */
283
284 int
285 cl_avr::brbc_s_k(t_mem code)
286 {
287   int s, k;
288
289   k= (code&0x3f8)>>3;
290   s= code&7;
291   t_mem sreg= ram->get(SREG);
292   t_mem mask= 1<<s;
293   if (!(sreg & mask))
294     {
295       if (code&0x200)
296         k|= -128;
297       PC= rom->validate_address((signed)PC+k);
298       tick(1);
299     }
300   return(resGO);
301 }
302
303
304 /*
305  * Skip if Bit in Register is Cleared
306  * SBRC Rr,b  0<=r<=31, 0<=b<=7
307  * 1111 110r rrrr Xbbb
308  *____________________________________________________________________________
309  */
310
311 int
312 cl_avr::sbrc_Rr_b(t_mem code)
313 {
314   t_addr r= (code&0x1f0)>>4;
315   int b= code&7;
316   t_mem mask= 1<<b;
317   if (!(ram->read(r) & mask))
318     {
319       t_mem next_code= rom->get(PC);
320       int i= 0;
321       struct dis_entry *dt= dis_tbl();
322       while ((next_code & dt[i].mask) != dt[i].code &&
323              dt[i].mnemonic)
324         i++;
325       if (dt[i].mnemonic != NULL)
326         {
327           PC= rom->validate_address(PC + dt[i].length);
328           tick(1);
329         }
330       else
331         return(resINV_INST);
332     }
333   return(resGO);
334 }
335
336
337 /*
338  * Skip if Bit in Register is Set
339  * SBRS Rr,b  0<=r<=31, 0<=b<=7
340  * 1111 111r rrrr Xbbb
341  *____________________________________________________________________________
342  */
343
344 int
345 cl_avr::sbrs_Rr_b(t_mem code)
346 {
347   t_addr r= (code&0x1f0)>>4;
348   int b= code&7;
349   t_mem mask= 1<<b;
350   if (ram->read(r) & mask)
351     {
352       t_mem next_code= rom->get(PC);
353       int i= 0;
354       struct dis_entry *dt= dis_tbl();
355       while ((next_code & dt[i].mask) != dt[i].code &&
356              dt[i].mnemonic)
357         i++;
358       if (dt[i].mnemonic != NULL)
359         {
360           PC= rom->validate_address(PC + dt[i].length);
361           tick(1);
362         }
363       else
364         return(resINV_INST);
365     }
366   return(resGO);
367 }
368
369
370 /*
371  * Skip if Bit in I/O Register is Clear
372  * SBIC P,b 0<=P<=31 0<=b<=7
373  * 1001 1001 pppp pbbb
374  *____________________________________________________________________________
375  */
376
377 int
378 cl_avr::sbic_P_b(t_mem code)
379 {
380   uint addr, mask;
381   
382   addr= ((code&0xf8)>>3)+0x20;
383   mask= 1 << (code&7);
384   if (0 == (mask & ram->read(addr)))
385     {
386       code= fetch();
387       int size= inst_length(code);
388       while (size > 1)
389         {
390           fetch();
391           size--;
392         }
393       tick(1);
394     }
395   return(resGO);
396 }
397
398
399 /*
400  * Skip if Bit in I/O Register is Set
401  * SBIS P,b 0<=P<=31 0<=b<=7
402  * 1001 1011 pppp pbbb
403  *____________________________________________________________________________
404  */
405
406 int
407 cl_avr::sbis_P_b(t_mem code)
408 {
409   uint addr, mask;
410   
411   addr= ((code&0xf8)>>3)+0x20;
412   mask= 1 << (code&7);
413   if (mask & ram->read(addr))
414     {
415       code= fetch();
416       int size= inst_length(code);
417       while (size > 1)
418         {
419           fetch();
420           size--;
421         }
422       tick(1);
423     }
424   return(resGO);
425 }
426
427
428 /* End of avr.src/jump_inst.cc */