version 0.5.2
[fw/sdcc] / sim / ucsim / s51.src / jmp.cc
1 /*
2  * Simulator of microcontrollers (jmp.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 /* Bugs fixed by Sandeep Dutta:
29  *      relative<->absolute jump in "jmp @a+dptr"
30  */
31
32 #include "ddconfig.h"
33
34 #include <stdio.h>
35 #include <stdlib.h>
36
37 // local
38 #include "uc51cl.h"
39 #include "regs51.h"
40 #include "types51.h"
41 #include "interruptcl.h"
42
43
44 /*
45  * 0x[02468ace]1 2 24 AJMP addr
46  *____________________________________________________________________________
47  *
48  */
49
50 int
51 cl_51core::inst_ajmp_addr(uchar code)
52 {
53   uchar h, l;
54
55   h= (code >> 5) & 0x07;
56   l= fetch();
57   tick(1);
58   PC= (PC & 0xf800) | (h*256 + l);
59   return(resGO);
60 }
61
62
63 /*
64  * 0x10 3 12 JBC bit,addr
65  *____________________________________________________________________________
66  *
67  */
68
69 int
70 cl_51core::inst_jbc_bit_addr(uchar code)
71 {
72   uchar bitaddr, jaddr;
73
74   bitaddr= fetch();
75   jaddr  = fetch();
76   t_addr a;
77   t_mem m;
78   class cl_address_space *mem;
79   if ((mem= bit2mem(bitaddr, &a, &m)) == 0)
80     return(resBITADDR);
81   t_mem d= mem->read(a, HW_PORT);
82   mem->write(a, d & ~m);
83   if (d & m)
84     PC= rom->validate_address(PC + (signed char)jaddr);
85   tick(1);
86   return(resGO);
87 }
88
89
90 /*
91  * 0x02 3 24 LJMP addr
92  *____________________________________________________________________________
93  *
94  */
95
96 int
97 cl_51core::inst_ljmp(uchar code)
98 {
99   PC= fetch()*256 + fetch();
100   tick(1);
101   return(resGO);
102 }
103
104
105 /*
106  * 0x[13579bdf]1 2 24 ACALL addr
107  *____________________________________________________________________________
108  *
109  */
110
111 int
112 cl_51core::inst_acall_addr(uchar code)
113 {
114   uchar h, l;
115   class cl_memory_cell *stck;
116   t_mem sp, sp_before/*, sp_after*/;
117
118   h= (code >> 5) & 0x07;
119   l= fetch();
120   sp_before= sfr->get(SP);
121   sp= sfr->wadd(SP, 1);
122   //proc_write_sp(sp);
123   stck= iram->get_cell(sp);
124   stck->write(PC & 0xff); // push low byte
125   tick(1);
126
127   sp= /*sp_after*= */sfr->wadd(SP, 1);
128   //proc_write_sp(sp);
129   stck= iram->get_cell(sp);
130   stck->write((PC >> 8) & 0xff); // push high byte
131   t_mem pushed= PC;
132   PC= (PC & 0xf800) | (h*256 + l);
133   class cl_stack_op *so= new cl_stack_call(instPC, PC, pushed, sp_before, sp);
134   so->init();
135   stack_write(so);
136   return(resGO);
137 }
138
139
140 /*
141  * 0x12 3 24 LCALL addr
142  *____________________________________________________________________________
143  *
144  */
145
146 int
147 cl_51core::inst_lcall(uchar code, uint addr, bool intr)
148 {
149   uchar h= 0, l= 0;
150   t_mem sp, sp_before/*, sp_after*/;
151   class cl_memory_cell *stck;
152
153   if (!addr)
154     {
155       h= fetch();
156       l= fetch();
157     }
158   sp_before= sfr->get(SP);
159   sp= sfr->wadd(SP, 1);
160   //proc_write_sp(sp);
161   stck= iram->get_cell(sp);
162   stck->write(PC & 0xff); // push low byte
163   if (!addr)
164     tick(1);
165
166   sp= sfr->wadd(SP, 1);
167   //proc_write_sp(sp);
168   stck= iram->get_cell(sp);
169   stck->write((PC >> 8) & 0xff); // push high byte
170   t_mem pushed= PC;
171   if (addr)
172     PC= addr;
173   else
174     PC= h*256 + l;
175   class cl_stack_op *so;
176   if (intr)
177     so= new cl_stack_intr(instPC, PC, pushed, sp_before, sp/*_after*/);
178   else
179     so= new cl_stack_call(instPC, PC, pushed, sp_before, sp/*_after*/);
180   so->init();
181   stack_write(so);
182   return(resGO);
183 }
184
185
186 /*
187  * 0x20 3 24 JB bit,addr
188  *____________________________________________________________________________
189  *
190  */
191
192 int
193 cl_51core::inst_jb_bit_addr(uchar code)
194 {
195   uchar bitaddr, jaddr;
196   t_addr a;
197   t_mem m;
198
199   class cl_address_space *mem;
200   if ((mem= bit2mem(bitaddr= fetch(), &a, &m)) == 0)
201     return(resBITADDR);
202   tick(1);
203   jaddr= fetch();
204   if (mem->read(a) & m)
205     PC= rom->validate_address(PC + (signed char)jaddr);
206   return(resGO);
207 }
208
209
210 /*
211  * 0x22 1 24 RET
212  *____________________________________________________________________________
213  *
214  */
215
216 int
217 cl_51core::inst_ret(uchar code)
218 {
219   uchar h= 0, l= 0;
220   t_mem sp, sp_before/*, sp_after*/;
221   class cl_memory_cell *stck;
222
223   sp= sp_before= sfr->read(SP);
224   stck= iram->get_cell(sp);
225   h= stck->read();
226   sp= sfr->wadd(SP, -1);
227   tick(1);
228
229   stck= iram->get_cell(sp);
230   l= stck->read();
231   sp= sfr->wadd(SP, -1);
232   PC= h*256 + l;
233   class cl_stack_op *so= new cl_stack_ret(instPC, PC, sp_before, sp/*_after*/);
234   so->init();
235   stack_read(so);
236   return(resGO);
237 }
238
239
240 /*
241  * 0x30 3 24 JNB bit,addr
242  *____________________________________________________________________________
243  *
244  */
245
246 int
247 cl_51core::inst_jnb_bit_addr(uchar code)
248 {
249   uchar bitaddr, jaddr;
250   t_mem m;
251   t_addr a;
252   class cl_address_space *mem;
253
254   if ((mem= bit2mem(bitaddr= fetch(), &a, &m)) == 0)
255     return(resBITADDR);
256   tick(1);
257   jaddr= fetch();
258   if (!(mem->read(a) & m))
259     PC= rom->validate_address(PC + (signed char)jaddr);
260   return(resGO);
261 }
262
263
264 /*
265  * 0x32 1 24 RETI
266  *____________________________________________________________________________
267  *
268  */
269
270 int
271 cl_51core::inst_reti(uchar code)
272 {
273   uchar h= 0, l= 0;
274   t_mem sp, sp_before, sp_after;
275   class cl_memory_cell *stck;
276
277   sp= sp_before= sfr->read(SP);
278   stck= iram->get_cell(sp);
279   h= stck->read();
280   sp= sfr->wadd(SP, -1);
281   tick(1);
282
283   stck= iram->get_cell(sp);
284   l= stck->read();
285   sp= sp_after= sfr->wadd(SP, -1);
286   PC= h*256 + l;
287
288   interrupt->was_reti= DD_TRUE;
289   class it_level *il= (class it_level *)(it_levels->top());
290   if (il &&
291       il->level >= 0)
292     {
293       il= (class it_level *)(it_levels->pop());
294       delete il;
295     }
296   class cl_stack_op *so=
297     new cl_stack_iret(instPC, PC, sp_before, sp_after);
298   so->init();
299   stack_read(so);
300   return(resGO);
301 }
302
303
304 /*
305  * 0x40 2 24 JC addr
306  *____________________________________________________________________________
307  *
308  */
309
310 int
311 cl_51core::inst_jc_addr(uchar code)
312 {
313   uchar jaddr;
314
315   jaddr= fetch();
316   tick(1);
317   if (SFR_GET_C)
318     PC= rom->validate_address(PC + (signed char)jaddr);
319   return(resGO);
320 }
321
322
323 /*
324  * 0x50 2 24 JNC addr
325  *____________________________________________________________________________
326  *
327  */
328
329 int
330 cl_51core::inst_jnc_addr(uchar code)
331 {
332   uchar jaddr;
333
334   jaddr= fetch();
335   tick(1);
336   if (!SFR_GET_C)
337     PC= rom->validate_address(PC + (signed char)jaddr);
338   return(resGO);
339 }
340
341
342 /*
343  * 0x60 2 24 JZ addr
344  *____________________________________________________________________________
345  *
346  */
347
348 int
349 cl_51core::inst_jz_addr(uchar code)
350 {
351   uchar jaddr;
352
353   jaddr= fetch();
354   tick(1);
355   if (!acc->read())
356     PC= rom->validate_address(PC + (signed char)jaddr);
357   return(resGO);
358 }
359
360
361 /*
362  * 0x70 2 24 JNZ addr
363  *____________________________________________________________________________
364  *
365  */
366
367 int
368 cl_51core::inst_jnz_addr(uchar code)
369 {
370   uchar jaddr;
371
372   jaddr= fetch();
373   tick(1);
374   if (acc->read())
375     PC= rom->validate_address(PC + (signed char)jaddr);
376   return(resGO);
377 }
378
379
380 /*
381  * 0x73 1 24 JMP @A+DPTR
382  *____________________________________________________________________________
383  *
384  */
385
386 int
387 cl_51core::inst_jmp_Sa_dptr(uchar code)
388 {
389   PC= rom->validate_address(sfr->read(DPH)*256 + sfr->read(DPL) + acc->read());
390   tick(1);
391   return(resGO);
392 }
393
394
395 /*
396  * 0x80 2 24 SJMP addr
397  *____________________________________________________________________________
398  *
399  */
400
401 int
402 cl_51core::inst_sjmp(uchar code)
403 {
404   signed char target= fetch();
405
406   PC= rom->validate_address(PC + target);
407   tick(1);
408   return(resGO);
409 }
410
411
412 /*
413  * 0xb4 3 24 CJNE A,#data,addr
414  *____________________________________________________________________________
415  *
416  */
417
418 int
419 cl_51core::inst_cjne_a_Sdata_addr(uchar code)
420 {
421   uchar data, jaddr, ac;
422
423   data = fetch();
424   jaddr= fetch();
425   tick(1);
426   SFR_SET_C((ac= acc->read()) < data);
427   if (ac != data)
428     PC= rom->validate_address(PC + (signed char)jaddr);
429   return(resGO);
430 }
431
432
433 /*
434  * 0xb5 3 24 CJNE A,addr,addr
435  *____________________________________________________________________________
436  *
437  */
438
439 int
440 cl_51core::inst_cjne_a_addr_addr(uchar code)
441 {
442   uchar data, jaddr;
443   t_addr a;
444   class cl_memory_cell *cell;
445
446   cell= get_direct(a= fetch());
447   jaddr= fetch();
448   tick(1);
449   data= cell->read();
450   SFR_SET_C(acc->get() < data);
451   if (acc->read() != data)
452     PC= rom->validate_address(PC + (signed char)jaddr);
453   return(resGO);
454 }
455
456
457 /*
458  * 0xb6-0xb7 3 24 CJNE @Ri,#data,addr
459  *____________________________________________________________________________
460  *
461  */
462
463 int
464 cl_51core::inst_cjne_Sri_Sdata_addr(uchar code)
465 {
466   uchar data, jaddr;
467   class cl_memory_cell *cell;
468
469   cell= iram->get_cell(get_reg(code & 0x01)->read());
470   data = fetch();
471   jaddr= fetch();
472   tick(1);
473   t_mem d;
474   SFR_SET_C((d= cell->read()) < data);
475   if (d != data)
476     PC= rom->validate_address(PC + (signed char)jaddr);
477   return(resGO);
478 }
479
480
481 /*
482  * 0xb8-0xbf 3 24 CJNE Rn,#data,addr
483  *____________________________________________________________________________
484  *
485  */
486
487 int
488 cl_51core::inst_cjne_rn_Sdata_addr(uchar code)
489 {
490   uchar data, jaddr;
491   class cl_memory_cell *reg;
492
493   reg  = get_reg(code & 0x07);
494   data = fetch();
495   jaddr= fetch();
496   tick(1);
497   t_mem r;
498   SFR_SET_C((r= reg->read()) < data);
499   if (r != data)
500     PC= rom->validate_address(PC + (signed char)jaddr);
501   return(resGO);
502 }
503
504
505 /*
506  * 0xd5 3 24 DJNZ addr,addr
507  *____________________________________________________________________________
508  *
509  */
510
511 int
512 cl_51core::inst_djnz_addr_addr(uchar code)
513 {
514   uchar jaddr;
515   class cl_memory_cell *cell;
516
517   cell = get_direct(fetch());
518   jaddr= fetch();
519   tick(1);
520   t_mem d= cell->read(HW_PORT);//cell->wadd(-1);
521   d= cell->write(d-1);
522   if (d)
523     PC= rom->validate_address(PC + (signed char)jaddr);
524   return(resGO);
525 }
526
527
528 /*
529  * 0xd8-0xdf 2 24 DJNZ Rn,addr
530  *____________________________________________________________________________
531  *
532  */
533
534 int
535 cl_51core::inst_djnz_rn_addr(uchar code)
536 {
537   uchar jaddr;
538   class cl_memory_cell *reg;
539
540   reg  = get_reg(code & 0x07);
541   jaddr= fetch();
542   tick(1);
543   t_mem r= reg->wadd(-1);
544   if (r)
545     PC= rom->validate_address(PC + (signed char)jaddr);
546   return(resGO);
547 }
548
549
550 /* End of s51.src/jmp.cc */