version 0.2.39: fix of arith insts and start of re-structure
[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 void
90 cl_z80::mk_hw_elements(void)
91 {
92   //class cl_base *o;
93   /* t_uc::mk_hw() does nothing */
94 }
95
96
97 /*
98  * Help command interpreter
99  */
100
101 struct dis_entry *
102 cl_z80::dis_tbl(void)
103 {
104   return(disass_z80);
105 }
106
107 /*struct name_entry *
108 cl_z80::sfr_tbl(void)
109 {
110   return(0);
111 }*/
112
113 /*struct name_entry *
114 cl_z80::bit_tbl(void)
115 {
116   //FIXME
117   return(0);
118 }*/
119
120 char *
121 cl_z80::disass(t_addr addr, char *sep)
122 {
123   char work[256], temp[20];
124   char *buf, *p, *b, *t;
125   uint code, data= 0;
126   int i;
127
128   p= work;
129   
130   code= get_mem(MEM_ROM, addr);
131   i= 0;
132   while ((code & dis_tbl()[i].mask) != dis_tbl()[i].code &&
133          dis_tbl()[i].mnemonic)
134     i++;
135   if (dis_tbl()[i].mnemonic == NULL)
136     {
137       buf= (char*)malloc(30);
138       strcpy(buf, "UNKNOWN/INVALID");
139       return(buf);
140     }
141   b= dis_tbl()[i].mnemonic;
142
143   while (*b)
144     {
145       if (*b == '%')
146         {
147           b++;
148           switch (*(b++))
149             {
150             case 'd': // Rd   .... ...d dddd ....  0<=d<=31
151               if (!get_name(data= (code&0x01f0)>>4, sfr_tbl(), temp))
152                 sprintf(temp, "r%d", data);
153               break;
154             case 'D': // Rd   .... .... dddd ....  16<=d<=31
155               if (!get_name(data= 16+((code&0xf0)>>4), sfr_tbl(), temp))
156                 sprintf(temp, "r%d", data);
157               break;
158             case 'K': // K    .... KKKK .... KKKK  0<=K<=255
159               sprintf(temp, "%d", ((code&0xf00)>>4)|(code&0xf));
160               break;
161             case 'r': // Rr   .... ..r. .... rrrr  0<=r<=31
162               if (!get_name(data= ((code&0x0200)>>5)|(code&0x000f),
163                             sfr_tbl(), temp))
164                 sprintf(temp, "r%d", data);
165               break;
166             case '2': // Rdl  .... .... ..dd ....  dl= {24,26,28,30}
167               if (!get_name(data= 24+(2*((code&0x0030)>>4)),
168                             sfr_tbl(), temp))
169                 sprintf(temp, "r%d", data);
170               break;
171             case '6': // K    .... .... KK.. KKKK  0<=K<=63
172               sprintf(temp, "%d", ((code&0xc0)>>2)|(code&0xf));
173               break;
174             case 's': // s    .... .... .sss ....  0<=s<=7
175               sprintf(temp, "%d", (code&0x70)>>4);
176               break;
177             case 'b': // b    .... .... .... .bbb  0<=b<=7
178               sprintf(temp, "%d", code&0x7);
179               break;
180             case 'k': // k    .... ..kk kkkk k...  -64<=k<=+63
181               {
182                 int k= (code&0x3f8)>>3;
183                 if (code&0x200)
184                   k|= -128;
185                 sprintf(temp, "0x%06x", k+1+(signed int)addr);
186                 break;
187               }
188             case 'A': // k    .... ...k kkkk ...k  0<=k<=64K
189                       //      kkkk kkkk kkkk kkkk  0<=k<=4M
190               sprintf(temp, "0x%06x",
191                       (((code&0x1f0)>>3)|(code&1))*0x10000+
192                       (uint)get_mem(MEM_ROM, addr+1));
193               break;
194             case 'P': // P    .... .... pppp p...  0<=P<=31
195               data= (code&0xf8)>>3;
196               if (!get_name(data+0x20, sfr_tbl(), temp))
197                 sprintf(temp, "%d", data);
198               break;
199             case 'p': // P    .... .PP. .... PPPP  0<=P<=63
200               data= ((code&0x600)>>5)|(code&0xf);
201               if (!get_name(data+0x20, sfr_tbl(), temp))
202                 sprintf(temp, "%d", data);
203               break;
204             case 'q': // q    ..q. qq.. .... .qqq  0<=q<=63
205               sprintf(temp, "%d",
206                       ((code&0x2000)>>8)|((code&0xc00)>>7)|(code&7));
207               break;
208             case 'R': // k    SRAM address on second word 0<=k<=65535
209               sprintf(temp, "0x%06x", (uint)get_mem(MEM_ROM, addr+1));
210               break;
211             case 'a': // k    .... kkkk kkkk kkkk  -2k<=k<=2k
212               {
213                 int k= code&0xfff;
214                 if (code&0x800)
215                   k|= -4096;
216                 sprintf(temp, "0x%06lx",
217                         (k+1+(signed int)addr) % rom->size);
218                 break;
219               }
220             default:
221               strcpy(temp, "?");
222               break;
223             }
224           t= temp;
225           while (*t)
226             *(p++)= *(t++);
227         }
228       else
229         *(p++)= *(b++);
230     }
231   *p= '\0';
232
233   p= strchr(work, ' ');
234   if (!p)
235     {
236       buf= strdup(work);
237       return(buf);
238     }
239   if (sep == NULL)
240     buf= (char *)malloc(6+strlen(p)+1);
241   else
242     buf= (char *)malloc((p-work)+strlen(sep)+strlen(p)+1);
243   for (p= work, b= buf; *p != ' '; p++, b++)
244     *b= *p;
245   p++;
246   *b= '\0';
247   if (sep == NULL)
248     {
249       while (strlen(buf) < 6)
250         strcat(buf, " ");
251     }
252   else
253     strcat(buf, sep);
254   strcat(buf, p);
255   return(buf);
256 }
257
258
259 void
260 cl_z80::print_regs(class cl_console *con)
261 {
262   con->printf("SZ-A--P-C  Flags= 0x%02x %3d %c  ",
263               regs.F, regs.F, isprint(regs.F)?regs.F:'.');
264   con->printf("A= 0x%02x %3d %c\n",
265               regs.A, regs.A, isprint(regs.A)?regs.A:'.');
266   con->printf("%c%c-%c--%c-%c\n",
267               (regs.F&BIT_S)?'1':'0',
268               (regs.F&BIT_Z)?'1':'0',
269               (regs.F&BIT_A)?'1':'0',
270               (regs.F&BIT_P)?'1':'0',
271               (regs.F&BIT_C)?'1':'0');
272   con->printf("BC= 0x%04x [BC]= %02x %3d %c  ",
273               regs.BC, ram->get(regs.BC), ram->get(regs.BC),
274               isprint(ram->get(regs.BC))?ram->get(regs.BC):'.');
275   con->printf("DE= 0x%04x [DE]= %02x %3d %c  ",
276               regs.DE, ram->get(regs.DE), ram->get(regs.DE),
277               isprint(ram->get(regs.DE))?ram->get(regs.DE):'.');
278   con->printf("HL= 0x%04x [HL]= %02x %3d %c\n",
279               regs.HL, ram->get(regs.HL), ram->get(regs.HL),
280               isprint(ram->get(regs.HL))?ram->get(regs.HL):'.');
281   con->printf("IX= 0x%04x [IX]= %02x %3d %c  ",
282               regs.IX, ram->get(regs.IX), ram->get(regs.IX),
283               isprint(ram->get(regs.IX))?ram->get(regs.IX):'.');
284   con->printf("IY= 0x%04x [IY]= %02x %3d %c  ",
285               regs.IY, ram->get(regs.IY), ram->get(regs.IY),
286               isprint(ram->get(regs.IY))?ram->get(regs.IY):'.');
287   con->printf("SP= 0x%04x [SP]= %02x %3d %c\n",
288               regs.SP, ram->get(regs.SP), ram->get(regs.SP),
289               isprint(ram->get(regs.SP))?ram->get(regs.SP):'.');
290   
291   print_disass(PC, con);
292 }
293
294
295 /*
296  * Execution
297  */
298
299 int
300 cl_z80::exec_inst(void)
301 {
302   t_mem code;
303
304   if (fetch(&code))
305     return(resBREAKPOINT);
306   tick(1);
307   switch (code)
308     {
309     case 0x00:
310       return(nop(code));
311     }
312   if (PC)
313     PC--;
314   else
315     PC= get_mem_size(MEM_ROM)-1;
316   //tick(-clock_per_cycle());
317   sim->stop(resINV_INST);
318   return(resINV_INST);
319 }
320
321
322 /* End of z80.src/z80.cc */