1 /* This file is part of microcontroller simulator: ucsim.
2 
3 UCSIM is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
7 
8 UCSIM is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 GNU General Public License for more details.
12 
13 You should have received a copy of the GNU General Public License
14 along with UCSIM; see the file COPYING.  If not, write to the Free
15 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
16 02111-1307, USA. */
17 /*@1@*/
18 
19 #include "ddconfig.h"
20 
21 // local
22 #include "r2kcl.h"
23 #include "z80mac.h"
24 
25 
word_parity(u16_t x)26 unsigned   word_parity( u16_t  x ) {
27   // bitcount(x) performed by shift-and-add
28   u16_t  tmp = (x & 0x5555) + ((x & 0xAAAA) >> 1);
29   tmp = (tmp & 0x3333) + ((tmp & 0xCCCC) >> 2);
30   tmp = (tmp & 0x0F0F) + ((tmp & 0xF0F0) >> 4);
31   tmp = (tmp & 0x000F) + ((tmp & 0x0F00) >> 8);
32 
33   // parity determined by count being odd or even
34   return  0x01 ^ (tmp & 1);
35 }
36 
37 /******** rabbit 2000 memory access helper functions *****************/
logical_addr_to_phys(u16_t logical_addr)38 u32_t  rabbit_mmu::logical_addr_to_phys( u16_t logical_addr ) {
39   u32_t  phys_addr = logical_addr;
40   unsigned     segnib = logical_addr >> 12;
41 
42   if (segnib >= 0xE000)
43   {
44     phys_addr += ((u32_t)xpc) << 12;
45   }
46   else if (segnib >= ((segsize >> 4) & 0x0F))
47   {
48     phys_addr += ((u32_t)stackseg) << 12;
49   }
50   else if (segnib >= (segsize & 0x0F))
51   {
52     phys_addr += ((u32_t)dataseg) << 12;
53   }
54 
55   return phys_addr;
56 }
57 
store1(u16_t addr,t_mem val)58 void cl_r2k::store1( u16_t addr, t_mem val ) {
59   u32_t  phys_addr;
60 
61   if (mmu.io_flag == IOI) {
62     if ((mmu.mmidr ^ 0x80) & 0x80)
63       /* bit 7 = 0 --> use only 8-bits for internal I/O addresses */
64       addr = addr & 0x0ff;
65 
66     if (addr == MMIDR) {
67       mmu.mmidr = val;
68       return;
69     }
70 
71     if (addr == SADR) {
72       /* serial A (console when using the rabbit programming cable) */
73       putchar(val);
74       fflush(stdout);
75     }
76     return;
77   }
78   if (mmu.io_flag == IOE) {
79     /* I/O operation for external device (such as an ethernet controller) */
80     return;
81   }
82 
83   phys_addr = mmu.logical_addr_to_phys( addr );
84   ram->write(phys_addr, val);
85 }
86 
store2(u16_t addr,u16_t val)87 void cl_r2k::store2( u16_t addr, u16_t val ) {
88   u32_t  phys_addr;
89 
90   if (mmu.io_flag == IOI) {
91     /* I/O operation for on-chip device (serial ports, timers, etc) */
92     return;
93   }
94 
95   if (mmu.io_flag == IOE) {
96     /* I/O operation for external device (such as an ethernet controller) */
97     return;
98   }
99 
100   phys_addr = mmu.logical_addr_to_phys( addr );
101 
102   ram->write(phys_addr,   val & 0xff);
103   ram->write(phys_addr+1, (val >> 8) & 0xff);
104 }
105 
get1(u16_t addr)106 u8_t  cl_r2k::get1( u16_t addr ) {
107   u32_t  phys_addr = mmu.logical_addr_to_phys( addr );
108 
109   if (mmu.io_flag == IOI) {
110     /* stub for on-chip device I/O */
111     return 0;
112   }
113   if (mmu.io_flag == IOE) {
114     /* stub for external device I/O */
115     return 0;
116   }
117 
118   return ram->read(phys_addr);
119 }
120 
get2(u16_t addr)121 u16_t  cl_r2k::get2( u16_t addr ) {
122   u32_t phys_addr = mmu.logical_addr_to_phys( addr );
123   u16_t  l, h;
124 
125   if (mmu.io_flag == IOI) {
126     /* stub for on-chip device I/O */
127     return 0;
128   }
129   if (mmu.io_flag == IOE) {
130     /* stub for external device I/O */
131     return 0;
132   }
133 
134   l = ram->read(phys_addr  );
135   h = ram->read(phys_addr+1);
136 
137   return (h << 8) | l;
138 }
139 
fetch1(void)140 t_mem       cl_r2k::fetch1( void ) {
141   return fetch( );
142 }
143 
fetch2(void)144 u16_t  cl_r2k::fetch2( void ) {
145   u16_t  c1, c2;
146 
147   c1 = fetch( );
148   c2 = fetch( );
149   return (c2 << 8) | c1;
150 }
151 
fetch(void)152 t_mem cl_r2k::fetch(void) {
153   /*
154    * Fetch without checking for breakpoint hit
155    *
156    * Used by bool cl_uc::fetch(t_mem *code) in sim.src/uc.cc
157    * which does check for a breakpoint hit
158    */
159 
160   u32_t phys_addr = mmu.logical_addr_to_phys( PC );
161   ulong code;
162 
163   if (!rom)
164     return(0);
165 
166   code= rom->read(phys_addr);
167   PC = (PC + 1) & 0xffffUL;
168   vc.fetch++;
169   return(code);
170 }
171 
172 /******** start rabbit 2000 specific codes *****************/
inst_add_sp_d(t_mem code)173 int cl_r2k::inst_add_sp_d(t_mem code) {
174   u16_t  d = fetch( );
175   /* sign-extend d from 8-bits to 16-bits */
176   d |= (d>>7)*0xFF00;
177   regs.SP = (regs.SP + d) & 0xffff;
178   return(resGO);
179 }
180 
inst_altd(t_mem code)181 int cl_r2k::inst_altd(t_mem code) {
182   // stub
183   return(resGO);
184 }
185 
186 int
inst_r2k_ld(t_mem code)187 cl_r2k::inst_r2k_ld(t_mem code)
188 {
189   /* 0xC4  ld hl,(sp+n)
190    * 0xD4  ld (sp+n),hl
191    * 0xE4  ld hl,(ix+d)
192    *   DD E4 = ld hl,(hl+d)   [note: (hl+d) breaks the normal prefix pattern]
193    *   FD E4 = ld hl,(iy+d)
194    * 0xF4  ld (ix+d),hl
195    *   DD F4 = ld (hl+d),hl
196    *   FD F4 = ld (iy+d),hl
197    */
198   switch(code) {
199   case 0xC4:  regs.HL = get2( add_u16_disp(regs.SP, fetch()) ); vc.rd+= 2; break;
200   case 0xD4:  store2( add_u16_disp(regs.SP, fetch()), regs.HL ); vc.wr+= 2; break;
201   case 0xE4:  regs.HL = get2( add_u16_disp(regs.IX, fetch()) ); vc.rd+= 2; break;
202   case 0xF4:  store2( add_u16_disp(regs.IX, fetch()), regs.HL ); vc.wr+= 2; break;
203   default:
204     return(resINV_INST);
205   }
206 
207   return(resGO);
208 }
209 
inst_r2k_ex(t_mem code)210 int cl_r2k::inst_r2k_ex (t_mem code) {
211   u16_t tempw;
212 
213   switch(code) {
214   case 0xE3:
215     // EX DE', HL  on rabbit processors
216     tempw = regs.aDE;
217     regs.aDE = regs.HL;
218     regs.HL = tempw;
219     return(resGO);
220 
221   default:
222     return(resINV_INST);
223   }
224 }
225 
inst_ljp(t_mem code)226 int cl_r2k::inst_ljp(t_mem code) {
227   u16_t  mn;
228 
229   mn = fetch2();  /* don't clobber PC before the fetch for xmem page */
230   mmu.xpc = fetch1();
231   PC = mn;
232 
233   return(resGO);
234 }
235 
inst_lcall(t_mem code)236 int cl_r2k::inst_lcall(t_mem code) {
237   u16_t  mn;
238 
239   push1(mmu.xpc);
240   push2(PC+2);
241   vc.wr+= 2;
242 
243   mn = fetch2();  /* don't clobber PC before the fetch for xmem page */
244   mmu.xpc = fetch1();
245   PC = mn;
246 
247   return(resGO);
248 }
249 
inst_bool(t_mem code)250 int cl_r2k::inst_bool(t_mem code) {
251   regs.raf.F &= ~BIT_ALL;
252   if (regs.HL)
253     regs.HL = 1;
254   else
255     regs.raf.F |= BIT_Z;
256   return(resGO);
257 }
258 
inst_r2k_and(t_mem code)259 int cl_r2k::inst_r2k_and(t_mem code) {  // AND HL,DE
260   regs.HL &= regs.DE;
261 
262   regs.raf.F &= ~BIT_ALL;
263   if (regs.DE & 0x8000)
264     regs.raf.F |= BIT_S;
265   if (regs.DE == 0)
266     regs.raf.F |= BIT_Z;
267   if (word_parity(regs.DE))
268     regs.raf.F |= BIT_P;
269   return(resGO);
270 }
271 
inst_r2k_or(t_mem code)272 int cl_r2k::inst_r2k_or (t_mem code) {  // OR  HL,DE
273   regs.HL |= regs.DE;
274 
275   regs.raf.F &= ~BIT_ALL;
276   if (regs.DE & 0x8000)
277     regs.raf.F |= BIT_S;
278   if (regs.DE == 0)
279     regs.raf.F |= BIT_Z;
280   if (word_parity(regs.DE))
281     regs.raf.F |= BIT_P;
282   return(resGO);
283 }
284 
inst_mul(t_mem code)285 int cl_r2k::inst_mul(t_mem code) {
286   long m;
287   long m1 = (long)(regs.BC & 0x7fff);
288   long m2 = (long)(regs.DE & 0x7fff);
289   if (regs.BC & 0x8000)
290     m1 -= (1 << 15);
291   if (regs.DE & 0x8000)
292     m2 -= (1 << 15);
293   m = m1 * m2;
294   regs.BC = ((unsigned long)(m) & 0xffff);
295   regs.HL = ((unsigned long)(m) >> 16) & 0xffff;
296   return(resGO);
297 }
298 
inst_rl_de(t_mem code)299 int cl_r2k::inst_rl_de(t_mem code) {
300   unsigned int oldcarry = (regs.raf.F & BIT_C);
301 
302   regs.raf.F &= ~BIT_ALL;
303   regs.raf.F |= (((regs.DE >> 15) & 1U) << BITPOS_C);
304   regs.DE = (regs.DE << 1) | (oldcarry >> BITPOS_C);
305 
306   if (regs.DE & 0x8000)
307     regs.raf.F |= BIT_S;
308   if (regs.DE == 0)
309     regs.raf.F |= BIT_Z;
310   if (word_parity(regs.DE))
311     regs.raf.F |= BIT_P;
312   return(resGO);
313 }
314 
inst_rr_de(t_mem code)315 int cl_r2k::inst_rr_de(t_mem code) {
316   unsigned int oldcarry = (regs.raf.F & BIT_C);
317 
318   regs.raf.F &= ~BIT_ALL;
319   regs.raf.F |= ((regs.DE & 1) << BITPOS_C);
320   regs.DE = (regs.DE >> 1) | (oldcarry << (15 - BITPOS_C));
321 
322   if (regs.DE & 0x8000)
323     regs.raf.F |= BIT_S;
324   if (regs.DE == 0)
325     regs.raf.F |= BIT_Z;
326   if (word_parity(regs.DE))
327     regs.raf.F |= BIT_P;
328   return(resGO);
329 }
330 
inst_rr_hl(t_mem code)331 int cl_r2k::inst_rr_hl(t_mem code)    // RR HL
332 {
333   unsigned int oldcarry = (regs.raf.F & BIT_C);
334 
335   regs.raf.F &= ~BIT_ALL;
336   regs.raf.F |= ((regs.HL & 1) << BITPOS_C);
337   regs.HL = (regs.HL >> 1) | (oldcarry << (15 - BITPOS_C));
338 
339   if (regs.HL & 0x8000)
340     regs.raf.F |= BIT_S;
341   if (regs.HL == 0)
342     regs.raf.F |= BIT_Z;
343   if (word_parity(regs.HL))
344     regs.raf.F |= BIT_P;
345   return(resGO);
346 }
347 
348 
349 int
inst_rst(t_mem code)350 cl_r2k::inst_rst(t_mem code)
351 {
352   switch(code) {
353     case 0xC7: // RST 0
354       push2(PC+2);
355       PC = 0x0;
356       vc.wr+= 2;
357     break;
358     case 0xCF: // RST 8
359       return(resINV_INST);
360 
361     case 0xD7: // RST 10H
362       push2(PC+2);
363       PC = 0x10;
364       vc.wr+= 2;
365     break;
366     case 0xDF: // RST 18H
367       push2(PC+2);
368       PC = 0x18;
369       vc.wr+= 2;
370     break;
371     case 0xE7: // RST 20H
372       push2(PC+2);
373       PC = 0x20;
374       vc.wr+= 2;
375     break;
376     case 0xEF: // RST 28H
377       //PC = 0x28;
378       switch (regs.raf.A) {
379         case 0:
380           return(resBREAKPOINT);
381 //          ::exit(0);
382         break;
383 
384         case 1:
385           //printf("PUTCHAR-----> %xH\n", regs.hl.l);
386           putchar(regs.hl.l);
387           fflush(stdout);
388         break;
389       }
390     break;
391     case 0xF7: // RST 30H
392       return(resINV_INST);  // opcode is used for MUL on rabbit 2000+
393     break;
394     case 0xFF: // RST 38H
395       push2(PC+2);
396       PC = 0x38;
397       vc.wr+= 2;
398     break;
399     default:
400       return(resINV_INST);
401     break;
402   }
403   return(resGO);
404 }
405 
inst_xd(t_mem prefix)406 int cl_r2k::inst_xd(t_mem prefix)
407 {
408   u16_t  *regs_IX_OR_IY = (prefix==0xdd)?(&regs.IX):(&regs.IY);
409   t_mem code;
410 
411   if (fetch(&code))
412     return(resBREAKPOINT);
413 
414   switch (code) {
415 
416     // 0x06 LD A,(IX+A) is r4k+ instruction
417   case 0x21: // LD IX,nnnn
418   case 0x22: // LD (nnnn),IX
419 
420   case 0x2A: // LD IX,(nnnn)
421   case 0x2E: // LD LX,nn
422   case 0x36: // LD (IX+dd),nn
423   case 0x46: // LD B,(IX+dd)
424   case 0x4E: // LD C,(IX+dd)
425   case 0x56: // LD D,(IX+dd)
426   case 0x5E: // LD E,(IX+dd)
427   case 0x66: // LD H,(IX+dd)
428   case 0x6E: // LD L,(IX+dd)
429 
430   case 0x70: // LD (IX+dd),B
431   case 0x71: // LD (IX+dd),C
432   case 0x72: // LD (IX+dd),D
433   case 0x73: // LD (IX+dd),E
434   case 0x74: // LD (IX+dd),H
435   case 0x75: // LD (IX+dd),L
436   case 0x77: // LD (IX+dd),A
437   case 0x7E: // LD A,(IX+dd)
438   case 0xF9: // LD SP,IX
439     if (prefix == 0xdd)
440       return(inst_dd_ld(code));
441     else
442       return(inst_fd_ld(code));
443 
444   case 0x7C: // LD HL,IX
445     regs.HL = *regs_IX_OR_IY;  // LD HL, IX|IY for rabbit processors
446     return(resGO);
447   case 0x7D: // LD IX,HL
448     *regs_IX_OR_IY = regs.HL;   // LD IX|IY,HL for rabbit processors
449     return(resGO);
450 
451   case 0x23: // INC IX
452   case 0x34: // INC (IX+dd)
453     if (prefix == 0xdd)
454       return(inst_dd_inc(code));
455     else
456       return(inst_fd_inc(code));
457 
458   case 0x09: // ADD IX,BC
459   case 0x19: // ADD IX,DE
460   case 0x29: // ADD IX,IX
461   case 0x39: // ADD IX,SP
462   case 0x86: // ADD A,(IX)
463     if (prefix == 0xdd)
464       return(inst_dd_add(code));
465     else
466       return(inst_fd_add(code));
467 
468   case 0x2B: // DEC IX
469   case 0x35: // DEC (IX+dd)
470     if (prefix == 0xdd)
471       return(inst_dd_dec(code));
472     else
473       return(inst_fd_dec(code));
474 
475     // 0x4C  TEST IX is r4k+
476 
477   case 0x8E: // ADC A,(IX)
478   case 0x96: // SUB (IX+dd)
479   case 0x9E: // SBC A,(IX+dd)
480   case 0xA6: // AND (IX+dd)
481   case 0xAE: // XOR (IX+dd)
482   case 0xB6: // OR (IX+dd)
483   case 0xBE: // CP (IX+dd)
484     if (prefix == 0xdd)
485       return(inst_dd_misc(code));
486     else
487       return(inst_fd_misc(code));
488 
489   case 0xC4: // LD IX,(SP+n)
490     *regs_IX_OR_IY = get2( add_u16_disp(regs.SP, fetch()) );
491     vc.rd+= 2;
492     return(resGO);
493 
494   case 0xCB: // escape, IX prefix to CB commands
495     // fixme: limit the opcodes passed through to those officially
496     // documented as present on the rabbit processors
497     if (prefix == 0xdd)
498       return(inst_ddcb()); /* see inst_ddcb.cc */
499     else
500       return(inst_fdcb()); /* see inst_fdcb.cc */
501 
502   case 0xCC: // BOOL IX|IY
503     if (*regs_IX_OR_IY)
504       *regs_IX_OR_IY = 1;
505 
506     // update flags
507     regs.raf.F &= ~BIT_ALL;
508     // bit 15 will never be set, so S<=0
509     if (*regs_IX_OR_IY == 0)
510       regs.raf.F |= BIT_Z;
511     // L/V and C are always cleared
512     return(resGO);
513 
514   case 0xD4: // LD (SP+n),IX|IY
515     store2( add_u16_disp(regs.SP, fetch()), *regs_IX_OR_IY );
516     vc.wr+= 2;
517     return(resGO);
518 
519   case 0xE1: // POP IX
520     *regs_IX_OR_IY = get2(regs.SP);
521     regs.SP+=2;
522     vc.rd+= 2;
523     return(resGO);
524 
525   case 0xE3: // EX (SP),IX
526   {
527     u16_t tempw;
528 
529     tempw = *regs_IX_OR_IY;
530     *regs_IX_OR_IY = get2(regs.SP);
531     store2(regs.SP, tempw);
532     vc.rd+= 2;
533     vc.wr+= 2;
534   }
535   return(resGO);
536 
537   case 0xE4:
538     if (prefix == 0xDD)
539       regs.HL = get2( add_u16_disp(regs.HL, fetch()) );
540     else
541       regs.HL = get2( add_u16_disp(regs.IY, fetch()) );
542     vc.rd+= 2;
543     return(resGO);
544 
545   case 0xE5: // PUSH IX
546     push2(*regs_IX_OR_IY);
547     vc.wr+= 2;
548     return(resGO);
549 
550   case 0xE9: // JP (IX)
551     PC = *regs_IX_OR_IY;
552     return(resGO);
553 
554   case 0xEA:
555     push2(PC);
556     PC = *regs_IX_OR_IY;
557     vc.wr+= 2;
558     return(resGO);
559 
560   case 0xDC: // AND IX|IY,DE  for rabbit processors
561   case 0xEC: // OR  IX|IY,DE  for rabbit processors
562     if (code == 0xDC)
563       *regs_IX_OR_IY &= regs.DE;
564     else
565       *regs_IX_OR_IY |= regs.DE;
566 
567     // update flags
568     regs.raf.F &= ~BIT_ALL;
569     if (*regs_IX_OR_IY & 0x8000)
570       regs.raf.F |= BIT_S;
571     if (regs_IX_OR_IY == 0)
572       regs.raf.F |= BIT_Z;
573     if (word_parity(*regs_IX_OR_IY))
574       regs.raf.F |= BIT_P;
575     return(resGO);
576 
577   case 0xF4: // LD (HL|IY+d),HL
578     if (prefix == 0xDD)
579       store2( add_u16_disp(regs.HL, fetch()), regs.HL );
580     else
581       store2( add_u16_disp(regs.IY, fetch()), regs.HL );
582     vc.wr+= 2;
583     return(resGO);
584 
585   case 0xFC: // RR IX|IY
586   {
587     u16_t  tmp = (regs.raf.F & BIT_C) << (15 - BITPOS_C);
588     tmp |= (*regs_IX_OR_IY >> 1);
589 
590     regs.raf.F = (regs.raf.F & ~BIT_C) | ((*regs_IX_OR_IY & 1) << BITPOS_C);
591 
592     if (*regs_IX_OR_IY & 0x8000)
593       regs.raf.F |= BIT_S;
594     if (*regs_IX_OR_IY == 0)
595       regs.raf.F |= BIT_Z;
596     if (word_parity(*regs_IX_OR_IY))
597       regs.raf.F |= BIT_P;
598     return(resGO);
599   }
600 
601   default:
602     return(resINV_INST);
603   }
604 
605   return(resINV_INST);
606 }
607