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