ucsim-0.2.37-pre3 into cvs
[fw/sdcc] / sim / ucsim / z80.src / z80.cc
1 /*
2  * Simulator of microcontrollers (z80.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 #include "ddconfig.h"
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <ctype.h>
33 #include "i_string.h"
34
35 // prj
36 #include "pobjcl.h"
37
38 // sim
39 #include "simcl.h"
40
41 // local
42 #include "z80cl.h"
43 #include "glob.h"
44 #include "regsz80.h"
45
46
47 /*
48  * Base type of Z80 controllers
49  */
50
51 cl_z80::cl_z80(class cl_sim *asim):
52   cl_uc(asim)
53 {
54   type= CPU_Z80;
55 }
56
57 int
58 cl_z80::init(void)
59 {
60   cl_uc::init(); /* Memories now exist */
61   ram= mem(MEM_XRAM);
62   rom= mem(MEM_ROM);
63   return(0);
64 }
65
66 char *
67 cl_z80::id_string(void)
68 {
69   return("unspecified Z80");
70 }
71
72
73 /*
74  * Making elements of the controller
75  */
76
77 t_addr
78 cl_z80::get_mem_size(enum mem_class type)
79 {
80   switch(type)
81     {
82     case MEM_ROM: return(0x10000);
83     case MEM_XRAM: return(0x10000);
84     default: return(0);
85     }
86  return(cl_uc::get_mem_size(type));
87 }
88
89 /*int
90 cl_z80::get_mem_width(enum mem_class type)
91 {
92   if (type == MEM_ROM)
93     return(16);
94   return(cl_uc::get_mem_width(type));
95 }*/
96
97 void
98 cl_z80::mk_hw_elements(void)
99 {
100   //class cl_base *o;
101   /* t_uc::mk_hw() does nothing */
102 }
103
104
105 /*
106  * Help command interpreter
107  */
108
109 struct dis_entry *
110 cl_z80::dis_tbl(void)
111 {
112   return(disass_z80);
113 }
114
115 /*struct name_entry *
116 cl_z80::sfr_tbl(void)
117 {
118   return(0);
119 }*/
120
121 /*struct name_entry *
122 cl_z80::bit_tbl(void)
123 {
124   //FIXME
125   return(0);
126 }*/
127
128 char *
129 cl_z80::disass(uint addr, char *sep)
130 {
131   char work[256], temp[20];
132   char *buf, *p, *b, *t;
133   uint code, data= 0;
134   int i;
135
136   p= work;
137   
138   code= get_mem(MEM_ROM, addr);
139   i= 0;
140   while ((code & dis_tbl()[i].mask) != dis_tbl()[i].code &&
141          dis_tbl()[i].mnemonic)
142     i++;
143   if (dis_tbl()[i].mnemonic == NULL)
144     {
145       buf= (char*)malloc(30);
146       strcpy(buf, "UNKNOWN/INVALID");
147       return(buf);
148     }
149   b= dis_tbl()[i].mnemonic;
150
151   while (*b)
152     {
153       if (*b == '%')
154         {
155           b++;
156           switch (*(b++))
157             {
158             case 'd': // Rd   .... ...d dddd ....  0<=d<=31
159               if (!get_name(data= (code&0x01f0)>>4, sfr_tbl(), temp))
160                 sprintf(temp, "r%d", data);
161               break;
162             case 'D': // Rd   .... .... dddd ....  16<=d<=31
163               if (!get_name(data= 16+((code&0xf0)>>4), sfr_tbl(), temp))
164                 sprintf(temp, "r%d", data);
165               break;
166             case 'K': // K    .... KKKK .... KKKK  0<=K<=255
167               sprintf(temp, "%d", ((code&0xf00)>>4)|(code&0xf));
168               break;
169             case 'r': // Rr   .... ..r. .... rrrr  0<=r<=31
170               if (!get_name(data= ((code&0x0200)>>5)|(code&0x000f),
171                             sfr_tbl(), temp))
172                 sprintf(temp, "r%d", data);
173               break;
174             case '2': // Rdl  .... .... ..dd ....  dl= {24,26,28,30}
175               if (!get_name(data= 24+(2*((code&0x0030)>>4)),
176                             sfr_tbl(), temp))
177                 sprintf(temp, "r%d", data);
178               break;
179             case '6': // K    .... .... KK.. KKKK  0<=K<=63
180               sprintf(temp, "%d", ((code&0xc0)>>2)|(code&0xf));
181               break;
182             case 's': // s    .... .... .sss ....  0<=s<=7
183               sprintf(temp, "%d", (code&0x70)>>4);
184               break;
185             case 'b': // b    .... .... .... .bbb  0<=b<=7
186               sprintf(temp, "%d", code&0x7);
187               break;
188             case 'k': // k    .... ..kk kkkk k...  -64<=k<=+63
189               {
190                 int k= (code&0x3f8)>>3;
191                 if (code&0x200)
192                   k|= -128;
193                 sprintf(temp, "0x%06x", k+1+(signed int)addr);
194                 break;
195               }
196             case 'A': // k    .... ...k kkkk ...k  0<=k<=64K
197                       //      kkkk kkkk kkkk kkkk  0<=k<=4M
198               sprintf(temp, "0x%06x",
199                       (((code&0x1f0)>>3)|(code&1))*0x10000+
200                       (uint)get_mem(MEM_ROM, addr+1));
201               break;
202             case 'P': // P    .... .... pppp p...  0<=P<=31
203               data= (code&0xf8)>>3;
204               if (!get_name(data+0x20, sfr_tbl(), temp))
205                 sprintf(temp, "%d", data);
206               break;
207             case 'p': // P    .... .PP. .... PPPP  0<=P<=63
208               data= ((code&0x600)>>5)|(code&0xf);
209               if (!get_name(data+0x20, sfr_tbl(), temp))
210                 sprintf(temp, "%d", data);
211               break;
212             case 'q': // q    ..q. qq.. .... .qqq  0<=q<=63
213               sprintf(temp, "%d",
214                       ((code&0x2000)>>8)|((code&0xc00)>>7)|(code&7));
215               break;
216             case 'R': // k    SRAM address on second word 0<=k<=65535
217               sprintf(temp, "0x%06x", (uint)get_mem(MEM_ROM, addr+1));
218               break;
219             case 'a': // k    .... kkkk kkkk kkkk  -2k<=k<=2k
220               {
221                 int k= code&0xfff;
222                 if (code&0x800)
223                   k|= -4096;
224                 sprintf(temp, "0x%06lx",
225                         (k+1+(signed int)addr) % rom->size);
226                 break;
227               }
228             default:
229               strcpy(temp, "?");
230               break;
231             }
232           t= temp;
233           while (*t)
234             *(p++)= *(t++);
235         }
236       else
237         *(p++)= *(b++);
238     }
239   *p= '\0';
240
241   p= strchr(work, ' ');
242   if (!p)
243     {
244       buf= strdup(work);
245       return(buf);
246     }
247   if (sep == NULL)
248     buf= (char *)malloc(6+strlen(p)+1);
249   else
250     buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1);
251   for (p= work, b= buf; *p != ' '; p++, b++)
252     *b= *p;
253   p++;
254   *b= '\0';
255   if (sep == NULL)
256     {
257       while (strlen(buf) < 6)
258         strcat(buf, " ");
259     }
260   else
261     strcat(buf, sep);
262   strcat(buf, p);
263   return(buf);
264 }
265
266 void
267 cl_z80::print_disass(uint addr, class cl_console *con)
268 {
269   char *dis;
270   class cl_brk *b;
271   int i;
272
273   b  = fbrk_at(addr);
274   dis= disass(addr, NULL);
275   if (b)
276     con->printf("%c", (b->perm == brkFIX)?'F':'D');
277   else
278     con->printf(" ");
279   con->printf("%c %06x %04x",
280               inst_at(addr)?' ':'*',
281               addr, get_mem(MEM_ROM, addr));
282   for (i= 1; i < inst_length(get_mem(MEM_ROM, addr)); i++)
283     con->printf(" %04x", get_mem(MEM_ROM, addr+i));
284   while (i < 2)
285     {
286       con->printf("     ");
287       i++;
288     }
289   con->printf(" %s\n", dis);
290   free(dis);
291 }
292
293 void
294 cl_z80::print_regs(class cl_console *con)
295 {
296   con->printf("SZ-A--P-C  Flags= 0x%02x %3d %c  ",
297               regs.F, regs.F, isprint(regs.F)?regs.F:'.');
298   con->printf("A= 0x%02x %3d %c\n",
299               regs.A, regs.A, isprint(regs.A)?regs.A:'.');
300   con->printf("%c%c-%c--%c-%c\n",
301               (regs.F&BIT_S)?'1':'0',
302               (regs.F&BIT_Z)?'1':'0',
303               (regs.F&BIT_A)?'1':'0',
304               (regs.F&BIT_P)?'1':'0',
305               (regs.F&BIT_C)?'1':'0');
306   con->printf("BC= 0x%04x [BC]= %02x %3d %c  ",
307               regs.BC, ram->get(regs.BC), ram->get(regs.BC),
308               isprint(ram->get(regs.BC))?ram->get(regs.BC):'.');
309   con->printf("DE= 0x%04x [DE]= %02x %3d %c  ",
310               regs.DE, ram->get(regs.DE), ram->get(regs.DE),
311               isprint(ram->get(regs.DE))?ram->get(regs.DE):'.');
312   con->printf("HL= 0x%04x [HL]= %02x %3d %c\n",
313               regs.HL, ram->get(regs.HL), ram->get(regs.HL),
314               isprint(ram->get(regs.HL))?ram->get(regs.HL):'.');
315   con->printf("IX= 0x%04x [IX]= %02x %3d %c  ",
316               regs.IX, ram->get(regs.IX), ram->get(regs.IX),
317               isprint(ram->get(regs.IX))?ram->get(regs.IX):'.');
318   con->printf("IY= 0x%04x [IY]= %02x %3d %c  ",
319               regs.IY, ram->get(regs.IY), ram->get(regs.IY),
320               isprint(ram->get(regs.IY))?ram->get(regs.IY):'.');
321   con->printf("SP= 0x%04x [SP]= %02x %3d %c\n",
322               regs.SP, ram->get(regs.SP), ram->get(regs.SP),
323               isprint(ram->get(regs.SP))?ram->get(regs.SP):'.');
324   
325   print_disass(PC, con);
326 }
327
328
329 /*
330  * Execution
331  */
332
333 int
334 cl_z80::exec_inst(void)
335 {
336   t_mem code;
337
338   if (fetch(&code))
339     return(resBREAKPOINT);
340   tick(1);
341   switch (code)
342     {
343     case 0x00:
344       return(nop(code));
345     }
346   if (PC)
347     PC--;
348   else
349     PC= get_mem_size(MEM_ROM)-1;
350   //tick(-clock_per_cycle());
351   sim->stop(resINV_INST);
352   return(resINV_INST);
353 }
354
355
356 /* End of z80.src/z80.cc */