Imported Upstream version 2.9.0
[debian/cc1111] / sim / ucsim / avr.src / move_inst.cc
1 /*
2  * Simulator of microcontrollers (move_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  * Load Program Memory
34  * LPM
35  * 1001 0101 110X 1000
36  *____________________________________________________________________________
37  */
38
39 int
40 cl_avr::lpm(t_mem code)
41 {
42   t_addr addr;
43   t_mem data;
44
45   addr= ram->get(ZH)*256 + ram->get(ZL);
46   data= rom->read(addr);
47   if (addr & 1)
48     ram->/*write*/set(0, (data>>8)&0xff);
49   else
50     ram->/*write*/set(0, data&0xff);
51   tick(2);
52   return(resGO);
53 }
54
55
56 int
57 cl_avr::elpm(t_mem code)
58 {
59   return(resGO);
60 }
61
62
63 int
64 cl_avr::spm(t_mem code)
65 {
66   return(resGO);
67 }
68
69
70 int
71 cl_avr::espm(t_mem code)
72 {
73   return(resGO);
74 }
75
76
77 /*
78  * Load Immediate
79  * LDI Rd,K 16<=d<=31 0<=K<=255
80  * 1110 KKKK dddd KKKK
81  *____________________________________________________________________________
82  */
83
84 int
85 cl_avr::ldi_Rd_K(t_mem code)
86 {
87   t_addr d;
88   t_mem K;
89
90   d= (code&0xf0)>>4;
91   K= ((code&0xf00)>>4)|(code&0xf);
92   ram->write(d+16, K);
93   return(resGO);
94 }
95
96
97 int
98 cl_avr::movw_Rd_Rr(t_mem code)
99 {
100   return(resGO);
101 }
102
103
104 /*
105  * Load Indirect From SRAM to Register using Index Z
106  * LDD Rd,Z+q 0<=d<=31, 0<=q<=63
107  * 10q0 qq0d dddd 0qqq
108  *____________________________________________________________________________
109  */
110
111 int
112 cl_avr::ldd_Rd_Z_q(t_mem code)
113 {
114   int d, q;
115   t_addr z;
116
117   d= (code&0x1f0)>>4;
118   q= ((code&0x2000)>>8)|((code&0xc00)>>7)|(code&0x7);
119   z= ram->get(ZH)*256 + ram->get(ZL);
120   t_mem data= ram->read(z+q);
121   ram->write(d, data);
122   tick(1);
123   return(resGO);
124 }
125
126
127 /*
128  * Load Indirect From SRAM to Register using Index Y
129  * LDD Rd,Y+q 0<=d<=31, 0<=q<=63
130  * 10q0 qq0d dddd 1qqq
131  *____________________________________________________________________________
132  */
133
134 int
135 cl_avr::ldd_Rd_Y_q(t_mem code)
136 {
137   int d, q;
138   t_addr y;
139
140   d= (code&0x1f0)>>4;
141   q= ((code&0x2000)>>8)|((code&0xc00)>>7)|(code&0x7);
142   y= ram->get(YH)*256 + ram->get(YL);
143   t_mem data= ram->read(y+q);
144   ram->write(d, data);
145   tick(1);
146   return(resGO);
147 }
148
149
150 /*
151  * Store Indirect From Register to SRAM using Index Z
152  * ST Z+q,Rr 0<=r<=31, 0<=q<=63
153  * 10q0 qq1r rrrr 0qqq
154  *____________________________________________________________________________
155  */
156
157 int
158 cl_avr::std_Z_q_Rr(t_mem code)
159 {
160   int r, q;
161   t_addr z;
162
163   r= (code&0x1f0)>>4;
164   q= ((code&0x2000)>>8)|((code&0xc00)>>7)|(code&0x7);
165   z= ram->get(ZH)*256 + ram->get(ZL);
166   t_mem data= ram->read(r);
167   ram->write(z+q, data);
168   tick(1);
169   return(resGO);
170 }
171
172
173 /*
174  * Store Indirect From Register to SRAM using Index Y
175  * ST Y+q,Rr 0<=r<=31, 0<=q<=63
176  * 10q0 qq1r rrrr 1qqq
177  *____________________________________________________________________________
178  */
179
180 int
181 cl_avr::std_Y_q_Rr(t_mem code)
182 {
183   int r, q;
184   t_addr y;
185
186   r= (code&0x1f0)>>4;
187   q= ((code&0x2000)>>8)|((code&0xc00)>>7)|(code&0x7);
188   y= ram->get(YH)*256 + ram->get(YL);
189   t_mem data= ram->read(r);
190   ram->write(y+q, data);
191   tick(1);
192   return(resGO);
193 }
194
195
196 /*
197  * Load Direct from SRAM
198  * LDS Rd,k 0<=d<=31, 0<=k<=65535
199  * 1001 000d dddd 0000
200  * kkkk kkkk kkkk kkkk
201  *____________________________________________________________________________
202  */
203
204 int
205 cl_avr::lds_Rd_k(t_mem code)
206 {
207   t_addr d, k;
208
209   d= (code&0x1f0)>>4;
210   k= fetch();
211   t_mem data= ram->read(k);
212   ram->write(d, data);
213   tick(2);
214   return(resGO);
215 }
216
217
218 /*
219  * Load Indirect From SRAM to register using Index Z
220  * LD Rd,Z+ 0<=d<=31
221  * 1001 000d dddd 0001
222  *____________________________________________________________________________
223  */
224
225 int
226 cl_avr::ld_Rd_ZS(t_mem code)
227 {
228   t_addr z, d;
229
230   d= (code&0x1f0)>>4;
231   z= ram->get(ZH)*256 + ram->get(ZL);
232   t_mem data= ram->read(z);
233   ram->write(d, data);
234   ram->set(ZL, data= (ram->get(ZL)+1)&0xff);
235   if (!data)
236     ram->set(ZH, (ram->get(ZH)+1)&0xff);
237   tick(1);
238   return(resGO);
239 }
240
241
242 /*
243  * Load Indirect From SRAM to register using Index Z
244  * LD Rd,-Z 0<=d<=31
245  * 1001 000d dddd 0010
246  *____________________________________________________________________________
247  */
248
249 int
250 cl_avr::ld_Rd_SZ(t_mem code)
251 {
252   t_addr z, d;
253   t_mem data;
254
255   d= (code&0x1f0)>>4;
256   ram->set(ZL, z= (ram->get(ZL)-1)&0xff);
257   if (z == 0xff)
258     ram->set(ZH, (ram->get(ZH)-1)&0xff);
259   z= ram->get(ZH)*256 + z;
260   data= ram->read(z);
261   ram->write(d, data);
262   tick(1);
263   return(resGO);
264 }
265
266
267 int
268 cl_avr::lpm_Rd_Z(t_mem code)
269 {
270   return(resGO);
271 }
272
273
274 int
275 cl_avr::lpm_Rd_ZS(t_mem code)
276 {
277   return(resGO);
278 }
279
280
281 int
282 cl_avr::elpm_Rd_Z(t_mem code)
283 {
284   return(resGO);
285 }
286
287
288 int
289 cl_avr::elpm_Rd_ZS(t_mem code)
290 {
291   return(resGO);
292 }
293
294
295 /*
296  * Load Indirect From SRAM to register using Index Y
297  * LD Rd,Y+ 0<=d<=31
298  * 1001 000d dddd 1001
299  *____________________________________________________________________________
300  */
301
302 int
303 cl_avr::ld_Rd_YS(t_mem code)
304 {
305   t_addr y, d;
306
307   d= (code&0x1f0)>>4;
308   y= ram->get(YH)*256 + ram->get(YL);
309   t_mem data= ram->read(y);
310   ram->write(d, data);
311   ram->set(YL, data= (ram->get(YL)+1)&0xff);
312   if (!data)
313     ram->set(YH, (ram->get(YH)+1)&0xff);
314   tick(1);
315   return(resGO);
316 }
317
318
319 /*
320  * Load Indirect From SRAM to register using Index Y
321  * LD Rd,-Y 0<=d<=31
322  * 1001 000d dddd 1010
323  *____________________________________________________________________________
324  */
325
326 int
327 cl_avr::ld_Rd_SY(t_mem code)
328 {
329   t_addr y, d;
330   t_mem data;
331
332   d= (code&0x1f0)>>4;
333   ram->set(YL, y= (ram->get(YL)-1)&0xff);
334   if (y == 0xff)
335     ram->set(YH, (ram->get(YH)-1)&0xff);
336   y= ram->get(YH)*256 + y;
337   data= ram->read(y);
338   ram->write(d, data);
339   tick(1);
340   return(resGO);
341 }
342
343
344 /*
345  * Load Indirect From SRAM to register using Index X
346  * LD Rd,X 0<=d<=31
347  * 1001 000d dddd 1100
348  *____________________________________________________________________________
349  */
350
351 int
352 cl_avr::ld_Rd_X(t_mem code)
353 {
354   t_addr x, d;
355
356   d= (code&0x1f0)>>4;
357   x= ram->get(XH)*256 + ram->get(XL);
358   t_mem data= ram->read(x);
359   ram->write(d, data);
360   tick(1);
361   return(resGO);
362 }
363
364
365 /*
366  * Load Indirect From SRAM to register using Index X
367  * LD Rd,X+ 0<=d<=31
368  * 1001 000d dddd 1101
369  *____________________________________________________________________________
370  */
371
372 int
373 cl_avr::ld_Rd_XS(t_mem code)
374 {
375   t_addr x, d;
376
377   d= (code&0x1f0)>>4;
378   x= ram->get(XH)*256 + ram->get(XL);
379   t_mem data= ram->read(x);
380   ram->write(d, data);
381   ram->set(XL, data= (ram->get(XL)+1)&0xff);
382   if (!data)
383     ram->set(XH, (ram->get(XH)+1)&0xff);
384   tick(1);
385   return(resGO);
386 }
387
388
389 /*
390  * Load Indirect From SRAM to register using Index X
391  * LD Rd,-X 0<=d<=31
392  * 1001 000d dddd 1110
393  *____________________________________________________________________________
394  */
395
396 int
397 cl_avr::ld_Rd_SX(t_mem code)
398 {
399   t_addr x, d;
400   t_mem data;
401
402   d= (code&0x1f0)>>4;
403   ram->set(XL, x= (ram->get(XL)-1)&0xff);
404   if (x == 0xff)
405     ram->set(XH, (ram->get(XH)-1)&0xff);
406   x= ram->get(XH)*256 + x;
407   data= ram->read(x);
408   ram->write(d, data);
409   tick(1);
410   return(resGO);
411 }
412
413
414 /*
415  * Pop Register from Stack
416  * POP Rd 0<=d<=31
417  * 1001 000d dddd 1111
418  *____________________________________________________________________________
419  */
420
421 int
422 cl_avr::pop_Rd(t_mem code)
423 {
424   t_addr d;
425   t_mem D;
426
427   d= (code&0x1f0)>>4;
428   pop_data(&D);
429   ram->write(d, D);
430   tick(1);
431   
432   return(resGO);
433 }
434
435
436 /*
437  * Store Direct to SRAM
438  * STS k,Rr 0<=r<=31, 0<=k<=65535
439  * 1001 001r rrrr 0000
440  * kkkk kkkk kkkk kkkk
441  *____________________________________________________________________________
442  */
443
444 int
445 cl_avr::sts_k_Rr(t_mem code)
446 {
447   t_addr r, k;
448
449   r= (code&0x1f0)>>4;
450   k= fetch();
451   t_mem data= ram->read(r);
452   ram->write(k, data);
453   tick(2);
454   return(resGO);
455 }
456
457
458 /*
459  * Store Indirect From Register to SRAM using Index Z
460  * ST Z+,Rr 0<=r<=63
461  * 1001 001r rrrr 0001
462  *____________________________________________________________________________
463  */
464
465 int
466 cl_avr::st_ZS_Rr(t_mem code)
467
468   t_addr z, r;
469
470   r= (code&0x1f0)>>4;
471   z= ram->get(ZH)*256 + ram->get(ZL);
472   t_mem data= ram->read(r);
473   ram->write(z, data);
474   ram->set(ZL, data= (ram->get(ZL)+1)&0xff);
475   if (!data)
476     ram->set(ZH, (ram->get(ZH)+1)&0xff);
477   tick(1);
478   return(resGO);
479 }
480
481
482 /*
483  * Store Indirect From Register to SRAM using Index Z
484  * ST -Z,Rr 0<=r<=63
485  * 1001 001r rrrr 0010
486  *____________________________________________________________________________
487  */
488
489 int
490 cl_avr::st_SZ_Rr(t_mem code)
491 {
492   t_addr z, r;
493   t_mem data;
494
495   r= (code&0x1f0)>>4;
496   ram->set(ZL, z= (ram->get(ZL)-1)&0xff);
497   if (z == 0xff)
498     ram->set(ZH, (ram->get(ZH)-1)&0xff);
499   z= ram->get(ZH)*256 + z;
500   data= ram->read(r);
501   ram->write(z, data);
502   tick(1);
503   return(resGO);
504 }
505
506
507 /*
508  * Store Indirect From Register to SRAM using Index Y
509  * ST Y+,Rr 0<=r<=63
510  * 1001 001r rrrr 1001
511  *____________________________________________________________________________
512  */
513
514 int
515 cl_avr::st_YS_Rr(t_mem code)
516 {
517   t_addr y, r;
518
519   r= (code&0x1f0)>>4;
520   y= ram->get(YH)*256 + ram->get(YL);
521   t_mem data= ram->read(r);
522   ram->write(y, data);
523   ram->set(YL, data= (ram->get(YL)+1)&0xff);
524   if (!data)
525     ram->set(YH, (ram->get(YH)+1)&0xff);
526   tick(1);
527   return(resGO);
528 }
529
530
531 /*
532  * Store Indirect From Register to SRAM using Index Y
533  * ST -Y,Rr 0<=r<=63
534  * 1001 001r rrrr 1010
535  *____________________________________________________________________________
536  */
537
538 int
539 cl_avr::st_SY_Rr(t_mem code)
540 {
541   t_addr y, r;
542   t_mem data;
543
544   r= (code&0x1f0)>>4;
545   ram->set(YL, y= (ram->get(YL)-1)&0xff);
546   if (y == 0xff)
547     ram->set(YH, (ram->get(YH)-1)&0xff);
548   y= ram->get(YH)*256 + y;
549   data= ram->read(r);
550   ram->write(y, data);
551   tick(1);
552   return(resGO);
553 }
554
555
556 /*
557  * Store Indirect From Register to SRAM using Index X
558  * ST X,Rr 0<=r<=31
559  * 1001 001r rrrr 1100
560  *____________________________________________________________________________
561  */
562
563 int
564 cl_avr::st_X_Rr(t_mem code)
565 {
566   int r;
567   t_addr x;
568
569   r= (code&0x1f0)>>4;
570   x= ram->get(XH)*256 + ram->get(XL);
571   t_mem data= ram->read(r);
572   ram->write(x, data);
573   tick(1);
574   return(resGO);
575 }
576
577
578 /*
579  * Store Indirect From Register to SRAM using Index X
580  * ST X+,Rr 0<=r<=63
581  * 1001 001r rrrr 1101
582  *____________________________________________________________________________
583  */
584
585 int
586 cl_avr::st_XS_Rr(t_mem code)
587 {
588   t_addr x, r;
589
590   r= (code&0x1f0)>>4;
591   x= ram->get(XH)*256 + ram->get(XL);
592   t_mem data= ram->read(r);
593   ram->write(x, data);
594   ram->set(XL, data= (ram->get(XL)+1)&0xff);
595   if (!data)
596     ram->set(XH, (ram->get(XH)+1)&0xff);
597   tick(1);
598   return(resGO);
599 }
600
601
602 /*
603  * Store Indirect From Register to SRAM using Index X
604  * ST -X,Rr 0<=r<=63
605  * 1001 001r rrrr 1110
606  *____________________________________________________________________________
607  */
608
609 int
610 cl_avr::st_SX_Rr(t_mem code)
611 {
612   t_addr x, r;
613   t_mem data;
614
615   r= (code&0x1f0)>>4;
616   ram->set(XL, x= (ram->get(XL)-1)&0xff);
617   if (x == 0xff)
618     ram->set(XH, (ram->get(XH)-1)&0xff);
619   x= ram->get(XH)*256 + x;
620   data= ram->read(r);
621   ram->write(x, data);
622   tick(1);
623   return(resGO);
624 }
625
626
627 /*
628  * Push register on Stack
629  * PUSH Rr 0<=r<=31
630  * 1001 001d dddd 1111
631  *____________________________________________________________________________
632  */
633
634 int
635 cl_avr::push_Rr(t_mem code)
636 {
637   t_addr d;
638   t_mem D;
639
640   d= (code&0x1f0)>>4;
641   D= ram->read(d);
642   push_data(D);
643   tick(1);
644
645   return(resGO);
646 }
647
648
649 /*
650  * Swap Nibbles
651  * SWAP Rd 0<=d<=31
652  * 1001 010d dddd 0010
653  *____________________________________________________________________________
654  */
655
656 int
657 cl_avr::swap_Rd(t_mem code)
658 {
659   t_addr d;
660   t_mem data, temp;
661
662   d= (code&0x1f0)>>4;
663   data= ram->read(d);
664   temp= (data>>4)&0xf;
665   data= (data<<4)|temp;
666   ram->write(d, data);
667   return(resGO);
668 }
669
670
671 /*
672  * Load an I/O Port to Register
673  * IN Rd,P 0<=d<=31 0<=P<=63
674  * 1011 0PPd dddd PPPP
675  *____________________________________________________________________________
676  */
677
678 int
679 cl_avr::in_Rd_A(t_mem code)
680 {
681   t_mem P, data;
682   t_addr d;
683   
684   P= ((code&0x600)>>5)|(code&0xf);
685   d= (code&0x1f0)>>4;
686   data= ram->read(P+0x20);
687   ram->write(d, data);
688   return(resGO);
689 }
690
691
692 /*
693  * Store Register to I/O Port
694  * OUT P,Rr 0<=r<=31 0<=P<=63
695  * 1011 1PPr rrrr PPPP
696  *____________________________________________________________________________
697  */
698
699 int
700 cl_avr::out_A_Rr(t_mem code)
701 {
702   t_mem P, data;
703   t_addr r;
704   
705   P= ((code&0x600)>>5)|(code&0xf);
706   r= (code&0x1f0)>>4;
707   data= ram->read(r);
708   ram->write(P+0x20, data);
709   return(resGO);
710 }
711
712
713 /*
714  * Copy Register
715  * MOV Rd,Rr 0<=d<=31 0<=r<=31
716  * 0010 11rd dddd rrrr
717  *____________________________________________________________________________
718  */
719
720 int
721 cl_avr::mov_Rd_Rr(t_mem code)
722 {
723   t_addr d, r;
724   
725   d= (code&0x1f0)>>4;
726   r= ((code&0x200)>>5)|(code&0xf);
727   t_mem data= ram->read(r);
728   ram->write(d, data);
729   return(resGO);
730 }
731
732
733 /* End of avr.src/move_inst.cc */