285a746d20a9910042e8735115cf434dbae1666c
[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 t_uc51::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 t_uc51::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_mem *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= (PC + (signed char)jaddr) & (EROM_SIZE - 1);
85   tick(1);
86   return(resGO);
87 }
88
89
90 /*
91  * 0x02 3 24 LJMP addr
92  *____________________________________________________________________________
93  *
94  */
95
96 int
97 t_uc51::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 t_uc51::inst_acall_addr(uchar code)
113 {
114   uchar h, l;
115   class cl_cell *stck;
116   t_mem sp;
117
118   h= (code >> 5) & 0x07;
119   l= fetch();
120   sp= sfr->wadd(SP, 1);
121   //proc_write_sp(sp);
122   stck= iram->get_cell(sp);
123   stck->write(PC & 0xff); // push low byte
124   tick(1);
125
126   sp= sfr->wadd(SP, 1);
127   //proc_write_sp(sp);
128   stck= iram->get_cell(sp);
129   stck->write((PC >> 8) & 0xff); // push high byte
130   PC= (PC & 0xf800) | (h*256 + l);
131   return(resGO);
132 }
133
134
135 /*
136  * 0x12 3 24 LCALL addr
137  *____________________________________________________________________________
138  *
139  */
140
141 int
142 t_uc51::inst_lcall(uchar code, uint addr)
143 {
144   uchar h= 0, l= 0;
145   t_mem sp;
146   class cl_cell *stck;
147
148   if (!addr)
149     {
150       h= fetch();
151       l= fetch();
152     }
153   sp= sfr->wadd(SP, 1);
154   //proc_write_sp(sp);
155   stck= iram->get_cell(sp);
156   stck->write(PC & 0xff); // push low byte
157   if (!addr)
158     tick(1);
159
160   sp= sfr->wadd(SP, 1);
161   //proc_write_sp(sp);
162   stck= iram->get_cell(sp);
163   stck->write((PC >> 8) & 0xff); // push high byte
164   if (addr)
165     PC= addr;
166   else
167     PC= h*256 + l;
168   return(resGO);
169 }
170
171
172 /*
173  * 0x20 3 24 JB bit,addr
174  *____________________________________________________________________________
175  *
176  */
177
178 int
179 t_uc51::inst_jb_bit_addr(uchar code)
180 {
181   uchar bitaddr, jaddr;
182   t_addr a;
183   t_mem m;
184
185   class cl_mem *mem;
186   if ((mem= bit2mem(bitaddr= fetch(), &a, &m)) == 0)
187     return(resBITADDR);
188   tick(1);
189   jaddr= fetch();
190   if (mem->read(a) & m)
191     PC= (PC + (signed char)jaddr) & (EROM_SIZE-1);
192   return(resGO);
193 }
194
195
196 /*
197  * 0x22 1 24 RET
198  *____________________________________________________________________________
199  *
200  */
201
202 int
203 t_uc51::inst_ret(uchar code)
204 {
205   uchar h= 0, l= 0;
206   t_mem sp;
207   class cl_cell *stck;
208
209   sp= sfr->read(SP);
210   stck= iram->get_cell(sp);
211   h= stck->read();
212   sp= sfr->wadd(SP, -1);
213   tick(1);
214
215   stck= iram->get_cell(sp);
216   l= stck->read();
217   sp= sfr->wadd(SP, -1);
218   PC= h*256 + l;
219   return(resGO);
220 }
221
222
223 /*
224  * 0x30 3 24 JNB bit,addr
225  *____________________________________________________________________________
226  *
227  */
228
229 int
230 t_uc51::inst_jnb_bit_addr(uchar code)
231 {
232   uchar bitaddr, jaddr;
233   t_mem m;
234   t_addr a;
235   class cl_mem *mem;
236
237   if ((mem= bit2mem(bitaddr= fetch(), &a, &m)) == 0)
238     return(resBITADDR);
239   tick(1);
240   jaddr= fetch();
241   if (!(mem->read(a) & m))
242     PC= (PC + (signed char)jaddr) & (get_mem_size(MEM_ROM)-1);
243   return(resGO);
244 }
245
246
247 /*
248  * 0x32 1 24 RETI
249  *____________________________________________________________________________
250  *
251  */
252
253 int
254 t_uc51::inst_reti(uchar code)
255 {
256   uchar h= 0, l= 0;
257   t_mem sp;
258   class cl_cell *stck;
259
260   sp= sfr->read(SP);
261   stck= iram->get_cell(sp);
262   h= stck->read();
263   sp= sfr->wadd(SP, -1);
264   tick(1);
265
266   stck= iram->get_cell(sp);
267   l= stck->read();
268   sp= sfr->wadd(SP, -1);
269   PC= h*256 + l;
270
271   interrupt->was_reti= DD_TRUE;
272   class it_level *il= (class it_level *)(it_levels->top());
273   if (il &&
274       il->level >= 0)
275     {
276       il= (class it_level *)(it_levels->pop());
277       delete il;
278     }
279   return(resGO);
280 }
281
282
283 /*
284  * 0x40 2 24 JC addr
285  *____________________________________________________________________________
286  *
287  */
288
289 int
290 t_uc51::inst_jc_addr(uchar code)
291 {
292   uchar jaddr;
293
294   jaddr= fetch();
295   tick(1);
296   if (SFR_GET_C)
297     PC= (PC + (signed char)jaddr) & (EROM_SIZE-1);
298   return(resGO);
299 }
300
301
302 /*
303  * 0x50 2 24 JNC addr
304  *____________________________________________________________________________
305  *
306  */
307
308 int
309 t_uc51::inst_jnc_addr(uchar code)
310 {
311   uchar jaddr;
312
313   jaddr= fetch();
314   tick(1);
315   if (!SFR_GET_C)
316     PC= (PC + (signed char)jaddr) & (EROM_SIZE-1);
317   return(resGO);
318 }
319
320
321 /*
322  * 0x60 2 24 JZ addr
323  *____________________________________________________________________________
324  *
325  */
326
327 int
328 t_uc51::inst_jz_addr(uchar code)
329 {
330   uchar jaddr;
331
332   jaddr= fetch();
333   tick(1);
334   if (!acc->read())
335     PC= (PC + (signed char)jaddr) & (EROM_SIZE-1);
336   return(resGO);
337 }
338
339
340 /*
341  * 0x70 2 24 JNZ addr
342  *____________________________________________________________________________
343  *
344  */
345
346 int
347 t_uc51::inst_jnz_addr(uchar code)
348 {
349   uchar jaddr;
350
351   jaddr= fetch();
352   tick(1);
353   if (acc->read())
354     PC= (PC + (signed char)jaddr) & (EROM_SIZE-1);
355   return(resGO);
356 }
357
358
359 /*
360  * 0x73 1 24 JMP @A+DPTR
361  *____________________________________________________________________________
362  *
363  */
364
365 int
366 t_uc51::inst_jmp_Sa_dptr(uchar code)
367 {
368   PC= (sfr->read(DPH)*256 + sfr->read(DPL) + acc->read()) &
369     (EROM_SIZE - 1);
370   tick(1);
371   return(resGO);
372 }
373
374
375 /*
376  * 0x80 2 24 SJMP addr
377  *____________________________________________________________________________
378  *
379  */
380
381 int
382 t_uc51::inst_sjmp(uchar code)
383 {
384   signed char target= fetch();
385
386   PC= (PC + target) & (EROM_SIZE -1);
387   tick(1);
388   return(resGO);
389 }
390
391
392 /*
393  * 0xb4 3 24 CJNE A,#data,addr
394  *____________________________________________________________________________
395  *
396  */
397
398 int
399 t_uc51::inst_cjne_a_Sdata_addr(uchar code)
400 {
401   uchar data, jaddr, ac;
402
403   data = fetch();
404   jaddr= fetch();
405   tick(1);
406   SFR_SET_C((ac= acc->read()) < data);
407   if (ac != data)
408     PC= (PC + (signed char)jaddr) & (EROM_SIZE - 1);
409   return(resGO);
410 }
411
412
413 /*
414  * 0xb5 3 24 CJNE A,addr,addr
415  *____________________________________________________________________________
416  *
417  */
418
419 int
420 t_uc51::inst_cjne_a_addr_addr(uchar code)
421 {
422   uchar data, jaddr;
423   t_addr a;
424   class cl_cell *cell;
425
426   cell= get_direct(a= fetch());
427   jaddr= fetch();
428   tick(1);
429   data= cell->read();
430   SFR_SET_C(acc->get() < data);
431   if (acc->read() != data)
432     PC= (PC + (signed char)jaddr) & (EROM_SIZE - 1);
433   return(resGO);
434 }
435
436
437 /*
438  * 0xb6-0xb7 3 24 CJNE @Ri,#data,addr
439  *____________________________________________________________________________
440  *
441  */
442
443 int
444 t_uc51::inst_cjne_Sri_Sdata_addr(uchar code)
445 {
446   uchar data, jaddr;
447   class cl_cell *cell;
448
449   cell= iram->get_cell(get_reg(code & 0x01)->read());
450   data = fetch();
451   jaddr= fetch();
452   tick(1);
453   t_mem d;
454   SFR_SET_C((d= cell->read()) < data);
455   if (d != data)
456     PC= (PC + (signed char)jaddr) & (EROM_SIZE - 1);
457   return(resGO);
458 }
459
460
461 /*
462  * 0xb8-0xbf 3 24 CJNE Rn,#data,addr
463  *____________________________________________________________________________
464  *
465  */
466
467 int
468 t_uc51::inst_cjne_rn_Sdata_addr(uchar code)
469 {
470   uchar data, jaddr;
471   class cl_cell *reg;
472
473   reg  = get_reg(code & 0x07);
474   data = fetch();
475   jaddr= fetch();
476   tick(1);
477   t_mem r;
478   SFR_SET_C((r= reg->read()) < data);
479   if (r != data)
480     PC= (PC + (signed char)jaddr) & (EROM_SIZE - 1);
481   return(resGO);
482 }
483
484
485 /*
486  * 0xd5 3 24 DJNZ addr,addr
487  *____________________________________________________________________________
488  *
489  */
490
491 int
492 t_uc51::inst_djnz_addr_addr(uchar code)
493 {
494   uchar jaddr;
495   class cl_cell *cell;
496
497   cell = get_direct(fetch());
498   jaddr= fetch();
499   tick(1);
500   t_mem d= cell->read(HW_PORT);//cell->wadd(-1);
501   d= cell->write(d-1);
502   if (d)
503     PC= (PC + (signed char)jaddr) & (EROM_SIZE-1);
504   return(resGO);
505 }
506
507
508 /*
509  * 0xd8-0xdf 2 24 DJNZ Rn,addr
510  *____________________________________________________________________________
511  *
512  */
513
514 int
515 t_uc51::inst_djnz_rn_addr(uchar code)
516 {
517   uchar jaddr;
518   class cl_cell *reg;
519
520   reg  = get_reg(code & 0x07);
521   jaddr= fetch();
522   tick(1);
523   t_mem r= reg->wadd(-1);
524   if (r)
525     PC= (PC + (signed char)jaddr) & (EROM_SIZE-1);
526   return(resGO);
527 }
528
529
530 /* End of s51.src/jmp.cc */