version 0.5.2
[fw/sdcc] / sim / ucsim / avr.src / jump_inst.cc
index 4b300b3a50adbbff0857e1afc29d2c61a04d237b..54f98f9726054b84082eebceb27620861305bd53 100644 (file)
@@ -42,7 +42,8 @@ cl_avr::ijmp(t_mem code)
   t_addr z;
 
   z= ram->get(ZH)*256 + ram->get(ZL);
-  PC= ((PC & ~0xffff) | z) % rom->size;
+  PC= rom->validate_address((PC & ~0xffff) | z);
+  //FIXME: analyze
   return(resGO);
 }
 
@@ -54,9 +55,26 @@ cl_avr::eijmp(t_mem code)
 }
 
 
+/*
+ * Indirect Call to Subroutine
+ * ICALL
+ * 1001 0101 XXXX 1001
+ *____________________________________________________________________________
+ */
+
 int
 cl_avr::icall(t_mem code)
 {
+  t_mem zl, zh;
+  t_addr z;
+  
+  push_addr(PC);
+  zl= ram->read(ZL);
+  zh= ram->read(ZH);
+  z= zh*256 + zl;
+  PC= (PC & ~0xffff) | (z & 0xffff);
+  //FIXME: analyze
+  tick(2);
   return(resGO);
 }
 
@@ -68,16 +86,43 @@ cl_avr::eicall(t_mem code)
 }
 
 
+/*
+ * Return from Subroutine
+ * RET
+ * 1001 0101 0XX0 1000
+ *____________________________________________________________________________
+ */
+
 int
 cl_avr::ret(t_mem code)
 {
+  t_addr a;
+
+  pop_addr(&a);
+  PC= rom->validate_address(a);
+  tick(3);
   return(resGO);
 }
 
 
+/*
+ * Return from Interrupt
+ * RETI
+ * 1001 0101 0XX1 1000
+ *____________________________________________________________________________
+ */
+
 int
 cl_avr::reti(t_mem code)
 {
+  t_addr a;
+
+  pop_addr(&a);
+  PC= rom->validate_address(a);
+  t_mem sreg= ram->read(SREG);
+  sreg|= BIT_I;
+  ram->write(SREG, sreg);
+  tick(3);
   return(resGO);
 }
 
@@ -92,22 +137,35 @@ cl_avr::reti(t_mem code)
 int
 cl_avr::rjmp_k(t_mem code)
 {
-  long k= code & 0xfff, pc;
+  long k= code & 0xfff;
 
   if (k & 0x800)
     k|= -4096;
-  pc= PC+k;
-  if (pc < 0)
-    pc= rom->size + pc;
-  PC= pc % rom->size;
+  PC= rom->validate_address((signed)PC + (signed)k);
   tick(1);
   return(resGO);
 }
 
 
+/*
+ * Relative Call to Subroutine
+ * RCALL k
+ * 1101 kkkk kkkk kkkk -1K<=k<=+1k
+ *____________________________________________________________________________
+ */
+
 int
 cl_avr::rcall_k(t_mem code)
 {
+  t_addr k;
+
+  push_addr(PC);
+  k= code & 0xfff;
+  if (k & 0x800)
+    k|= ~0xfff;
+  PC= rom->validate_address((signed)PC + (signed)k);
+  tick(2);
+
   return(resGO);
 }
 
@@ -136,7 +194,7 @@ cl_avr::cpse_Rd_Rr(t_mem code)
        i++;
       if (dt[i].mnemonic != NULL)
        {
-         PC= (PC + dt[i].length) % get_mem_size(MEM_ROM);
+         PC= rom->validate_address(PC + dt[i].length);
          tick(1);
        }
       else
@@ -161,8 +219,7 @@ cl_avr::jmp_k(t_mem code)
 
   k= ((code&0x1f0)>>3)|(code&1);
   k= (k<<16)|fetch();
-  PC= k;
-  //FIXME: analyze
+  PC= rom->validate_address(k);
   tick(2);
   return(resGO);
 }
@@ -183,7 +240,8 @@ cl_avr::call_k(t_mem code)
 
   k= (((code&0x1f0)>>3)|(code&1))*0x10000;
   k= k + fetch();
-
+  push_addr(PC);
+  PC= rom->validate_address(k);
   tick(3);
   return(resGO);
 }
@@ -209,7 +267,7 @@ cl_avr::brbs_s_k(t_mem code)
     {
       if (code&0x200)
        k|= -128;
-      PC= (PC+k) % get_mem_size(MEM_ROM);
+      PC= rom->validate_address((signed)PC+k);
       tick(1);
     }
   return(resGO);
@@ -236,7 +294,7 @@ cl_avr::brbc_s_k(t_mem code)
     {
       if (code&0x200)
        k|= -128;
-      PC= (PC+k) % get_mem_size(MEM_ROM);
+      PC= rom->validate_address((signed)PC+k);
       tick(1);
     }
   return(resGO);
@@ -266,7 +324,7 @@ cl_avr::sbrc_Rr_b(t_mem code)
        i++;
       if (dt[i].mnemonic != NULL)
        {
-         PC= (PC + dt[i].length) % get_mem_size(MEM_ROM);
+         PC= rom->validate_address(PC + dt[i].length);
          tick(1);
        }
       else
@@ -299,7 +357,7 @@ cl_avr::sbrs_Rr_b(t_mem code)
        i++;
       if (dt[i].mnemonic != NULL)
        {
-         PC= (PC + dt[i].length) % get_mem_size(MEM_ROM);
+         PC= rom->validate_address(PC + dt[i].length);
          tick(1);
        }
       else