5fbfb8676dcb9c39b60853697f3c65d0ece4dc93
[fw/sdcc] / sim / ucsim / s51.src / uc390.cc
1 /*
2  * Simulator of microcontrollers (uc390.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  * uc390.cc - module created by Karl Bongers 2001, karl@turbobit.com
9  */
10
11 /* This file is part of microcontroller simulator: ucsim.
12
13 UCSIM is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 UCSIM is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with UCSIM; see the file COPYING.  If not, write to the Free
25 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
26 02111-1307, USA. */
27 /*@1@*/
28
29 #include "ddconfig.h"
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <ctype.h>
34 #include "i_string.h"
35
36 #include "glob.h"
37 #include "uc390cl.h"
38 #include "regs51.h"
39
40 /*
41  * Names of instructions
42  */
43
44 struct dis_entry disass_390f[] = {
45   { 0x00, 0xff, ' ', 1, "NOP"},
46    { 0x01, 0xff, 'A', 3, "AJMP %A"},
47    { 0x02, 0xff, 'L', 4, "LJMP %l"},
48   { 0x03, 0xff, ' ', 1, "RR A"},
49   { 0x04, 0xff, ' ', 1, "INC A"},
50   { 0x05, 0xff, ' ', 2, "INC %a"},
51   { 0x06, 0xff, ' ', 1, "INC @R0"},
52   { 0x07, 0xff, ' ', 1, "INC @R1"},
53   { 0x08, 0xff, ' ', 1, "INC R0"},
54   { 0x09, 0xff, ' ', 1, "INC R1"},
55   { 0x0a, 0xff, ' ', 1, "INC R2"},
56   { 0x0b, 0xff, ' ', 1, "INC R3"},
57   { 0x0c, 0xff, ' ', 1, "INC R4"},
58   { 0x0d, 0xff, ' ', 1, "INC R5"},
59   { 0x0e, 0xff, ' ', 1, "INC R6"},
60   { 0x0f, 0xff, ' ', 1, "INC R7"},
61   { 0x10, 0xff, 'R', 3, "JBC %b,%R"},
62    { 0x11, 0xff, 'a', 3, "ACALL %A"},
63    { 0x12, 0xff, 'l', 4, "LCALL %l"},
64   { 0x13, 0xff, ' ', 1, "RRC A"},
65   { 0x14, 0xff, ' ', 1, "DEC A"},
66   { 0x15, 0xff, ' ', 2, "DEC %a"},
67   { 0x16, 0xff, ' ', 1, "DEC @R0"},
68   { 0x17, 0xff, ' ', 1, "DEC @R1"},
69   { 0x18, 0xff, ' ', 1, "DEC R0"},
70   { 0x19, 0xff, ' ', 1, "DEC R1"},
71   { 0x1a, 0xff, ' ', 1, "DEC R2"},
72   { 0x1b, 0xff, ' ', 1, "DEC R3"},
73   { 0x1c, 0xff, ' ', 1, "DEC R4"},
74   { 0x1d, 0xff, ' ', 1, "DEC R5"},
75   { 0x1e, 0xff, ' ', 1, "DEC R6"},
76   { 0x1f, 0xff, ' ', 1, "DEC R7"},
77   { 0x20, 0xff, 'R', 3, "JB %b,%R"},
78    { 0x21, 0xff, 'A', 3, "AJMP %A"},
79    { 0x22, 0xff, '_', 1, "RET"},
80   { 0x23, 0xff, ' ', 1, "RL A"},
81   { 0x24, 0xff, ' ', 2, "ADD A,#%d"},
82   { 0x25, 0xff, ' ', 2, "ADD A,%a"},
83   { 0x26, 0xff, ' ', 1, "ADD A,@R0"},
84   { 0x27, 0xff, ' ', 1, "ADD A,@R1"},
85   { 0x28, 0xff, ' ', 1, "ADD A,R0"},
86   { 0x29, 0xff, ' ', 1, "ADD A,R1"},
87   { 0x2a, 0xff, ' ', 1, "ADD A,R2"},
88   { 0x2b, 0xff, ' ', 1, "ADD A,R3"},
89   { 0x2c, 0xff, ' ', 1, "ADD A,R4"},
90   { 0x2d, 0xff, ' ', 1, "ADD A,R5"},
91   { 0x2e, 0xff, ' ', 1, "ADD A,R6"},
92   { 0x2f, 0xff, ' ', 1, "ADD A,R7"},
93   { 0x30, 0xff, 'R', 3, "JNB %b,%R"},
94    { 0x31, 0xff, 'a', 3, "ACALL %A"},
95    { 0x32, 0xff, '_', 1, "RETI"},
96   { 0x33, 0xff, ' ', 1, "RLC A"},
97   { 0x34, 0xff, ' ', 2, "ADDC A,#%d"},
98   { 0x35, 0xff, ' ', 2, "ADDC A,%a"},
99   { 0x36, 0xff, ' ', 1, "ADDC A,@R0"},
100   { 0x37, 0xff, ' ', 1, "ADDC A,@R1"},
101   { 0x38, 0xff, ' ', 1, "ADDC A,R0"},
102   { 0x39, 0xff, ' ', 1, "ADDC A,R1"},
103   { 0x3a, 0xff, ' ', 1, "ADDC A,R2"},
104   { 0x3b, 0xff, ' ', 1, "ADDC A,R3"},
105   { 0x3c, 0xff, ' ', 1, "ADDC A,R4"},
106   { 0x3d, 0xff, ' ', 1, "ADDC A,R5"},
107   { 0x3e, 0xff, ' ', 1, "ADDC A,R6"},
108   { 0x3f, 0xff, ' ', 1, "ADDC A,R7"},
109   { 0x40, 0xff, 'r', 2, "JC %r"},
110    { 0x41, 0xff, 'A', 3, "AJMP %A"},
111   { 0x42, 0xff, ' ', 2, "ORL %a,A"},
112   { 0x43, 0xff, ' ', 3, "ORL %a,#%D"},
113   { 0x44, 0xff, ' ', 2, "ORL A,#%d"},
114   { 0x45, 0xff, ' ', 2, "ORL A,%a"},
115   { 0x46, 0xff, ' ', 1, "ORL A,@R0"},
116   { 0x47, 0xff, ' ', 1, "ORL A,@R1"},
117   { 0x48, 0xff, ' ', 1, "ORL A,R0"},
118   { 0x49, 0xff, ' ', 1, "ORL A,R1"},
119   { 0x4a, 0xff, ' ', 1, "ORL A,R2"},
120   { 0x4b, 0xff, ' ', 1, "ORL A,R3"},
121   { 0x4c, 0xff, ' ', 1, "ORL A,R4"},
122   { 0x4d, 0xff, ' ', 1, "ORL A,R5"},
123   { 0x4e, 0xff, ' ', 1, "ORL A,R6"},
124   { 0x4f, 0xff, ' ', 1, "ORL A,R7"},
125   { 0x50, 0xff, 'r', 2, "JNC %r"},
126    { 0x51, 0xff, 'a', 3, "ACALL %A"},
127   { 0x52, 0xff, ' ', 2, "ANL %a,A"},
128   { 0x53, 0xff, ' ', 3, "ANL %a,#%D"},
129   { 0x54, 0xff, ' ', 2, "ANL A,#%d"},
130   { 0x55, 0xff, ' ', 2, "ANL A,%a"},
131   { 0x56, 0xff, ' ', 1, "ANL A,@R0"},
132   { 0x57, 0xff, ' ', 1, "ANL A,@R1"},
133   { 0x58, 0xff, ' ', 1, "ANL A,R0"},
134   { 0x59, 0xff, ' ', 1, "ANL A,R1"},
135   { 0x5a, 0xff, ' ', 1, "ANL A,R2"},
136   { 0x5b, 0xff, ' ', 1, "ANL A,R3"},
137   { 0x5c, 0xff, ' ', 1, "ANL A,R4"},
138   { 0x5d, 0xff, ' ', 1, "ANL A,R5"},
139   { 0x5e, 0xff, ' ', 1, "ANL A,R6"},
140   { 0x5f, 0xff, ' ', 1, "ANL A,R7"},
141   { 0x60, 0xff, 'r', 2, "JZ %r"},
142    { 0x61, 0xff, 'A', 3, "AJMP %A"},
143   { 0x62, 0xff, ' ', 2, "XRL %a,A"},
144   { 0x63, 0xff, ' ', 3, "XRL %a,#%D"},
145   { 0x64, 0xff, ' ', 2, "XRL A,#%d"},
146   { 0x65, 0xff, ' ', 2, "XRL A,%a"},
147   { 0x66, 0xff, ' ', 1, "XRL A,@R0"},
148   { 0x67, 0xff, ' ', 1, "XRL A,@R1"},
149   { 0x68, 0xff, ' ', 1, "XRL A,R0"},
150   { 0x69, 0xff, ' ', 1, "XRL A,R1"},
151   { 0x6a, 0xff, ' ', 1, "XRL A,R2"},
152   { 0x6b, 0xff, ' ', 1, "XRL A,R3"},
153   { 0x6c, 0xff, ' ', 1, "XRL A,R4"},
154   { 0x6d, 0xff, ' ', 1, "XRL A,R5"},
155   { 0x6e, 0xff, ' ', 1, "XRL A,R6"},
156   { 0x6f, 0xff, ' ', 1, "XRL A,R7"},
157   { 0x70, 0xff, 'r', 2, "JNZ %r"},
158    { 0x71, 0xff, 'a', 3, "ACALL %A"},
159   { 0x72, 0xff, ' ', 2, "ORL C,%b"},
160   { 0x73, 0xff, '_', 1, "JMP @A+DPTR"},
161   { 0x74, 0xff, ' ', 2, "MOV A,#%d"},
162   { 0x75, 0xff, ' ', 3, "MOV %a,#%D"},
163   { 0x76, 0xff, ' ', 2, "MOV @R0,#%d"},
164   { 0x77, 0xff, ' ', 2, "MOV @R1,#%d"},
165   { 0x78, 0xff, ' ', 2, "MOV R0,#%d"},
166   { 0x79, 0xff, ' ', 2, "MOV R1,#%d"},
167   { 0x7a, 0xff, ' ', 2, "MOV R2,#%d"},
168   { 0x7b, 0xff, ' ', 2, "MOV R3,#%d"},
169   { 0x7c, 0xff, ' ', 2, "MOV R4,#%d"},
170   { 0x7d, 0xff, ' ', 2, "MOV R5,#%d"},
171   { 0x7e, 0xff, ' ', 2, "MOV R6,#%d"},
172   { 0x7f, 0xff, ' ', 2, "MOV R7,#%d"},
173   { 0x80, 0xff, 's', 2, "SJMP %r"},
174    { 0x81, 0xff, 'A', 3, "AJMP %A"},
175   { 0x82, 0xff, ' ', 2, "ANL C,%b"},
176   { 0x83, 0xff, ' ', 1, "MOVC A,@A+PC"},
177   { 0x84, 0xff, ' ', 1, "DIV AB"},
178   { 0x85, 0xff, ' ', 3, "MOV %8,%a"},
179   { 0x86, 0xff, ' ', 2, "MOV %a,@R0"},
180   { 0x87, 0xff, ' ', 2, "MOV %a,@R1"},
181   { 0x88, 0xff, ' ', 2, "MOV %a,R0"},
182   { 0x89, 0xff, ' ', 2, "MOV %a,R1"},
183   { 0x8a, 0xff, ' ', 2, "MOV %a,R2"},
184   { 0x8b, 0xff, ' ', 2, "MOV %a,R3"},
185   { 0x8c, 0xff, ' ', 2, "MOV %a,R4"},
186   { 0x8d, 0xff, ' ', 2, "MOV %a,R5"},
187   { 0x8e, 0xff, ' ', 2, "MOV %a,R6"},
188   { 0x8f, 0xff, ' ', 2, "MOV %a,R7"},
189    { 0x90, 0xff, ' ', 4, "MOV DPTR,#%l"},
190    { 0x91, 0xff, 'a', 3, "ACALL %A"},
191   { 0x92, 0xff, ' ', 2, "MOV %b,C"},
192   { 0x93, 0xff, ' ', 1, "MOVC A,@A+DPTR"},
193   { 0x94, 0xff, ' ', 2, "SUBB A,#%d"},
194   { 0x95, 0xff, ' ', 2, "SUBB A,%a"},
195   { 0x96, 0xff, ' ', 1, "SUBB A,@R0"},
196   { 0x97, 0xff, ' ', 1, "SUBB A,@R1"},
197   { 0x98, 0xff, ' ', 1, "SUBB A,R0"},
198   { 0x99, 0xff, ' ', 1, "SUBB A,R1"},
199   { 0x9a, 0xff, ' ', 1, "SUBB A,R2"},
200   { 0x9b, 0xff, ' ', 1, "SUBB A,R3"},
201   { 0x9c, 0xff, ' ', 1, "SUBB A,R4"},
202   { 0x9d, 0xff, ' ', 1, "SUBB A,R5"},
203   { 0x9e, 0xff, ' ', 1, "SUBB A,R6"},
204   { 0x9f, 0xff, ' ', 1, "SUBB A,R7"},
205   { 0xa0, 0xff, ' ', 2, "ORL C,/%b"},
206    { 0xa1, 0xff, 'A', 3, "AJMP %A"},
207   { 0xa2, 0xff, ' ', 2, "MOV C,%b"},
208   { 0xa3, 0xff, ' ', 1, "INC DPTR"},
209   { 0xa4, 0xff, ' ', 1, "MUL AB"},
210   { 0xa5, 0xff, '_', 1, "-"},
211   { 0xa6, 0xff, ' ', 2, "MOV @R0,%a"},
212   { 0xa7, 0xff, ' ', 2, "MOV @R1,%a"},
213   { 0xa8, 0xff, ' ', 2, "MOV R0,%a"},
214   { 0xa9, 0xff, ' ', 2, "MOV R1,%a"},
215   { 0xaa, 0xff, ' ', 2, "MOV R2,%a"},
216   { 0xab, 0xff, ' ', 2, "MOV R3,%a"},
217   { 0xac, 0xff, ' ', 2, "MOV R4,%a"},
218   { 0xad, 0xff, ' ', 2, "MOV R5,%a"},
219   { 0xae, 0xff, ' ', 2, "MOV R6,%a"},
220   { 0xaf, 0xff, ' ', 2, "MOV R7,%a"},
221   { 0xb0, 0xff, ' ', 2, "ANL C,/%b"},
222    { 0xb1, 0xff, 'a', 3, "ACALL %A"},
223   { 0xb2, 0xff, ' ', 2, "CPL %b"},
224   { 0xb3, 0xff, ' ', 1, "CPL C"},
225   { 0xb4, 0xff, 'R', 3, "CJNE A,#%d,%R"},
226   { 0xb5, 0xff, 'R', 3, "CJNE A,%a,%R"},
227   { 0xb6, 0xff, 'R', 3, "CJNE @R0,#%d,%R"},
228   { 0xb7, 0xff, 'R', 3, "CJNE @R1,#%d,%R"},
229   { 0xb8, 0xff, 'R', 3, "CJNE R0,#%d,%R"},
230   { 0xb9, 0xff, 'R', 3, "CJNE R1,#%d,%R"},
231   { 0xba, 0xff, 'R', 3, "CJNE R2,#%d,%R"},
232   { 0xbb, 0xff, 'R', 3, "CJNE R3,#%d,%R"},
233   { 0xbc, 0xff, 'R', 3, "CJNE R4,#%d,%R"},
234   { 0xbd, 0xff, 'R', 3, "CJNE R5,#%d,%R"},
235   { 0xbe, 0xff, 'R', 3, "CJNE R6,#%d,%R"},
236   { 0xbf, 0xff, 'R', 3, "CJNE R7,#%d,%R"},
237    { 0xc0, 0xff, ' ', 2, "PUSH %a"},
238    { 0xc1, 0xff, 'A', 3, "AJMP %A"},
239   { 0xc2, 0xff, ' ', 2, "CLR %b"},
240   { 0xc3, 0xff, ' ', 1, "CLR C"},
241   { 0xc4, 0xff, ' ', 1, "SWAP A"},
242   { 0xc5, 0xff, ' ', 2, "XCH A,%a"},
243   { 0xc6, 0xff, ' ', 1, "XCH A,@R0"},
244   { 0xc7, 0xff, ' ', 1, "XCH A,@R1"},
245   { 0xc8, 0xff, ' ', 1, "XCH A,R0"},
246   { 0xc9, 0xff, ' ', 1, "XCH A,R1"},
247   { 0xca, 0xff, ' ', 1, "XCH A,R2"},
248   { 0xcb, 0xff, ' ', 1, "XCH A,R3"},
249   { 0xcc, 0xff, ' ', 1, "XCH A,R4"},
250   { 0xcd, 0xff, ' ', 1, "XCH A,R5"},
251   { 0xce, 0xff, ' ', 1, "XCH A,R6"},
252   { 0xcf, 0xff, ' ', 1, "XCH A,R7"},
253    { 0xd0, 0xff, ' ', 2, "POP %a"},
254    { 0xd1, 0xff, 'a', 3, "ACALL %A"},
255   { 0xd2, 0xff, ' ', 2, "SETB %b"},
256   { 0xd3, 0xff, ' ', 1, "SETB C"},
257   { 0xd4, 0xff, ' ', 1, "DA A"},
258   { 0xd5, 0xff, 'R', 3, "DJNZ %a,%R"},
259   { 0xd6, 0xff, ' ', 1, "XCHD A,@R0"},
260   { 0xd7, 0xff, ' ', 1, "XCHD A,@R1"},
261   { 0xd8, 0xff, 'r', 2, "DJNZ R0,%r"},
262   { 0xd9, 0xff, 'r', 2, "DJNZ R1,%r"},
263   { 0xda, 0xff, 'r', 2, "DJNZ R2,%r"},
264   { 0xdb, 0xff, 'r', 2, "DJNZ R3,%r"},
265   { 0xdc, 0xff, 'r', 2, "DJNZ R4,%r"},
266   { 0xdd, 0xff, 'r', 2, "DJNZ R5,%r"},
267   { 0xde, 0xff, 'r', 2, "DJNZ R6,%r"},
268   { 0xdf, 0xff, 'r', 2, "DJNZ R7,%r"},
269   { 0xe0, 0xff, ' ', 1, "MOVX A,@DPTR"},
270    { 0xe1, 0xff, 'A', 3, "AJMP %A"},
271   { 0xe2, 0xff, ' ', 1, "MOVX A,@R0"},
272   { 0xe3, 0xff, ' ', 1, "MOVX A,@R1"},
273   { 0xe4, 0xff, ' ', 1, "CLR A"},
274   { 0xe5, 0xff, ' ', 2, "MOV A,%a"},
275   { 0xe6, 0xff, ' ', 1, "MOV A,@R0"},
276   { 0xe7, 0xff, ' ', 1, "MOV A,@R1"},
277   { 0xe8, 0xff, ' ', 1, "MOV A,R0"},
278   { 0xe9, 0xff, ' ', 1, "MOV A,R1"},
279   { 0xea, 0xff, ' ', 1, "MOV A,R2"},
280   { 0xeb, 0xff, ' ', 1, "MOV A,R3"},
281   { 0xec, 0xff, ' ', 1, "MOV A,R4"},
282   { 0xed, 0xff, ' ', 1, "MOV A,R5"},
283   { 0xee, 0xff, ' ', 1, "MOV A,R6"},
284   { 0xef, 0xff, ' ', 1, "MOV A,R7"},
285   { 0xf0, 0xff, ' ', 1, "MOVX @DPTR,A"},
286    { 0xf1, 0xff, 'a', 3, "ACALL %A"},
287   { 0xf2, 0xff, ' ', 1, "MOVX @R0,A"},
288   { 0xf3, 0xff, ' ', 1, "MOVX @R1,A"},
289   { 0xf4, 0xff, ' ', 1, "CPL A"},
290   { 0xf5, 0xff, ' ', 2, "MOV %a,A"},
291   { 0xf6, 0xff, ' ', 1, "MOV @R0,A"},
292   { 0xf7, 0xff, ' ', 1, "MOV @R1,A"},
293   { 0xf8, 0xff, ' ', 1, "MOV R0,A"},
294   { 0xf9, 0xff, ' ', 1, "MOV R1,A"},
295   { 0xfa, 0xff, ' ', 1, "MOV R2,A"},
296   { 0xfb, 0xff, ' ', 1, "MOV R3,A"},
297   { 0xfc, 0xff, ' ', 1, "MOV R4,A"},
298   { 0xfd, 0xff, ' ', 1, "MOV R5,A"},
299   { 0xfe, 0xff, ' ', 1, "MOV R6,A"},
300   { 0xff, 0xff, ' ', 1, "MOV R7,A"},
301   { 0, 0, 0, 0, NULL }
302 };
303
304 /*
305  * Making an 390 CPU object
306  */
307
308 t_uc390::t_uc390 (int Itype, int Itech, class cl_sim *asim):
309   t_uc52 (Itype, Itech, asim)
310 {
311   if (Itype == CPU_DS390F)
312     {
313       printf ("FLAT24 MODE SET, warning: experimental code\n");
314       flat24_flag = 1;
315     }
316 }
317
318   // strcpy (mem(MEM_ROM) ->addr_format, "0x%06x");
319   // strcpy (mem(MEM_XRAM)->addr_format, "0x%06x");
320
321 t_addr
322 t_uc390::get_mem_size (enum mem_class type)
323 {
324   //if ((sfr->get (ACON) & 0x3) == 2)
325   if (!flat24_flag)
326     return t_uc52::get_mem_size (type);
327   switch (type)
328     {
329       case MEM_ROM:
330         return 128*1024;        // 4*1024*1024; 4 Meg possible
331       case MEM_XRAM:
332         return 128*1024 + 1024; // 4*1024*1024 + 1024; 4 Meg + 1k possible
333       case MEM_IRAM:
334         return 256;
335       case MEM_SFR:
336         return 256;
337       case MEM_TYPES:
338       default:
339         return 0;
340     }
341   return 0;
342 }
343
344 ulong
345 t_uc390::read_mem(enum mem_class type, t_mem addr)
346 {
347   //if ((sfr->get (ACON) & 0x3) == 2)
348
349   if (type == MEM_XRAM &&
350       flat24_flag &&
351       addr >= 0x400000)
352     addr -= 0x400000 - get_mem_size (MEM_XRAM) + 1024;
353 /*
354     addr -= 0x400000;
355     addr += get_mem_size (MEM_XRAM);
356     addr -= 1024;
357 */
358   return t_uc51::read_mem (type, addr);
359 }
360
361 ulong
362 t_uc390::get_mem (enum mem_class type, t_addr addr)
363 {
364   if (type == MEM_XRAM &&
365       flat24_flag &&
366       addr >= 0x400000)
367     addr -= 0x400000 - get_mem_size (MEM_XRAM) + 1024;
368   return t_uc51::get_mem (type, addr);
369 }
370
371 void
372 t_uc390::write_mem (enum mem_class type, t_addr addr, t_mem val)
373 {
374   if (type == MEM_XRAM &&
375       flat24_flag &&
376       addr >= 0x400000)
377     addr -= 0x400000 - get_mem_size (MEM_XRAM) + 1024;
378   t_uc51::write_mem (type, addr, val);
379 }
380
381 void
382 t_uc390::set_mem (enum mem_class type, t_addr addr, t_mem val)
383 {
384   if (type == MEM_XRAM &&
385       flat24_flag &&
386       addr >= 0x400000)
387     addr -= 0x400000 - get_mem_size (MEM_XRAM) + 1024;
388   t_uc51::set_mem (type, addr, val);
389 }
390
391 /*
392  *____________________________________________________________________________
393  */
394
395 int
396 t_uc390::push_byte (uchar uc)
397 {
398   int res;
399
400   sfr->add (SP, 1);
401   if (sfr->get (ACON) & 0x04) /* SA: 10 bit stack */
402     {
403       uint sp10;
404
405       if (get_mem (MEM_SFR, SP) == 0x00) /* overflow SP */
406         sfr->add (ESP, 1);
407       sp10 = (get_mem (MEM_SFR, ESP) & 0x3) * 256 +
408              get_mem (MEM_SFR, SP);
409       write_mem (MEM_XRAM, sp10 + 0x400000, uc);
410       res = 0;
411     }
412   else
413     {
414       uchar *sp;
415
416       sp = get_indirect (sfr->get (SP), &res);
417       if (res != resGO)
418         res = resSTACK_OV;
419       *sp = uc;
420     }
421   return res;
422 }
423
424 //    proc_write_sp (*aof_SP); TODO
425
426 uchar
427 t_uc390::pop_byte (int *Pres)
428 {
429   uchar uc;
430
431   if (sfr->get (ACON) & 0x04) /* SA: 10 bit stack */
432     {
433       uint sp10;
434
435       sp10 = (get_mem (MEM_SFR, ESP) & 0x3) * 256 +
436              get_mem (MEM_SFR, SP);
437       sfr->add (SP, -1);
438       if (get_mem (MEM_SFR, SP) == 0xff) /* underflow SP */
439         sfr->add (ESP, -1);
440       uc = get_mem (MEM_XRAM, sp10 + 0x400000);
441       *Pres = 0;
442     }
443   else
444     {
445       uchar *sp;
446
447       sp = get_indirect (get_mem (MEM_SFR, SP), Pres);
448       if (*Pres != resGO)
449         *Pres = resSTACK_OV;
450       sfr->add (SP, -1);
451       uc = *sp;
452     }
453   return uc;
454 }
455
456 /*
457  * 0x05 2 12 INC addr
458  *____________________________________________________________________________
459  *
460  */
461 int
462 t_uc390::inst_inc_addr (uchar code)
463 {
464   uchar *addr;
465
466   addr = get_direct (fetch (), &event_at.wi, &event_at.ws);
467
468   /* mask off the 2Hex bit adjacent to the 1H bit which selects
469      which DPTR we use.  This is a feature of 80C390.
470      You can do INC DPS and it only effects bit 1. */
471   if (code == DPS)
472     (*addr) ^= 1;  /* just toggle */
473   else
474     (*addr)++;
475
476   proc_write (addr);
477   return resGO;
478 }
479
480 /*
481  * 0xa3 1 24 INC DPTR
482  *____________________________________________________________________________
483  *
484  */
485
486 int
487 t_uc390::inst_inc_dptr (uchar code)
488 {
489   ulong dptr;
490
491   uchar pl, ph, px, dps;
492
493   dps = sfr->get (DPS);
494   if (dps & 1)
495     {
496       pl = DPL1;
497       ph = DPH1;
498       px = DPX1;
499     }
500   else
501     {
502       pl = DPL;
503       ph = DPH;
504       px = DPX;
505     }
506
507   dptr = sfr->get (ph) * 256 + sfr->get (pl);
508   //if ((sfr->get (ACON) & 0x3) == 2)
509   if (flat24_flag)
510     dptr += sfr->get (px) *256*256;
511   if (dps & 0x80) /* decr set */
512     dptr--;
513   else
514     dptr++;
515
516   //if ((sfr->get (ACON) & 0x3) == 2)
517   if (flat24_flag)
518     sfr->set (px, (dptr >> 16) & 0xff);
519   sfr->set (event_at.ws = ph, (dptr >> 8) & 0xff);
520   sfr->set (pl, dptr & 0xff);
521
522   if (dps & 0x20)                      /* auto-switch dptr */
523     sfr->set (DPS, (dps ^ 1));  /* toggle dual-dptr switch */
524   tick (1);
525   return resGO;
526 }
527
528 /*
529  * 0x73 1 24 JMP @A+DPTR
530  *____________________________________________________________________________
531  *
532  */
533
534 int
535 t_uc390::inst_jmp_$a_dptr (uchar code)
536 {
537   uchar pl, ph, px, dps;
538
539   dps = sfr->get (DPS);
540   if (dps & 1)
541     {
542       pl = DPL1;
543       ph = DPH1;
544       px = DPX1;
545     }
546   else
547     {
548       pl = DPL;
549       ph = DPH;
550       px = DPX;
551     }
552
553   PC = (sfr->get (ph) * 256 + sfr->get (pl) +
554       read_mem (MEM_SFR, ACC)) &
555       (EROM_SIZE - 1);
556   //if ((sfr->get (ACON) & 0x3) == 2)
557   if (flat24_flag)
558     PC += sfr->get (px) * 256*256;
559
560   tick (1);
561   return resGO;
562 }
563
564 /*
565  * 0x90 3 24 MOV DPTR,#data
566  *____________________________________________________________________________
567  *
568  */
569
570 int
571 t_uc390::inst_mov_dptr_$data (uchar code)
572 {
573   uchar pl, ph, px, dps;
574
575   dps = sfr->get (DPS);
576   if (dps & 1)
577     {
578       pl = DPL1;
579       ph = DPH1;
580       px = DPX1;
581     }
582   else
583     {
584       pl = DPL;
585       ph = DPH;
586       px = DPX;
587     }
588
589   //if ((sfr->get (ACON) & 0x3) == 2)
590   if (flat24_flag)
591     sfr->set (px, fetch ());
592   sfr->set (event_at.ws = ph, fetch ());
593   sfr->set (pl, fetch ());
594
595   if (dps & 0x20)                      /* auto-switch dptr */
596     sfr->set (DPS, (dps ^ 1));  /* toggle dual-dptr switch */
597
598   tick (1);
599   return resGO;
600 }
601
602
603 /*
604  * 0x93 1 24 MOVC A,@A+DPTR
605  *____________________________________________________________________________
606  *
607  */
608
609 int
610 t_uc390::inst_movc_a_$a_dptr (uchar code)
611 {
612   uchar pl, ph, px, dps;
613
614   dps = sfr->get (DPS);
615   if (dps & 1)
616     {
617       pl = DPL1;
618       ph = DPH1;
619       px = DPX1;
620     }
621   else
622     {
623       pl = DPL;
624       ph = DPH;
625       px = DPX;
626     }
627
628   //if ((sfr->get (ACON) & 0x3) == 2)
629   if (flat24_flag)
630     sfr->set (ACC, get_mem (MEM_ROM,
631               event_at.rc =
632               (sfr->get (px) * 256*256 + sfr->get (ph) * 256 + sfr->get (pl) +
633               sfr->get (ACC)) & (EROM_SIZE-1)));
634   else
635     sfr->set (ACC, get_mem (MEM_ROM, event_at.rc =
636               (sfr->get (ph) * 256 + sfr->get (pl) +
637               sfr->get (ACC)) & (EROM_SIZE-1)));
638
639   if (dps & 0x20)                      /* auto-switch dptr */
640     sfr->set (DPS, (dps ^ 1));  /* toggle dual-dptr switch */
641
642   tick (1);
643   return resGO;
644 }
645
646 /*
647  * 0xc0 2 24 PUSH addr
648  *____________________________________________________________________________
649  *
650  */
651
652 int
653 t_uc390::inst_push (uchar code)
654 {
655   uchar *addr;
656   int res;
657
658   addr = get_direct (fetch (), &event_at.wi, &event_at.ws);
659   res = push_byte (read (addr));
660   tick (1);
661   return res;
662 }
663
664
665 /*
666  * 0xd0 2 24 POP addr
667  *____________________________________________________________________________
668  *
669  */
670
671 int
672 t_uc390::inst_pop (uchar code)
673 {
674   uchar *addr;
675   int res;
676
677   addr = get_direct (fetch (), &event_at.wi, &event_at.ws);
678   *addr = pop_byte (&res);
679   proc_write (addr);
680   tick (1);
681   return res;
682 }
683
684
685 /*
686  * 0xe0 1 24 MOVX A,@DPTR
687  *____________________________________________________________________________
688  *
689  */
690
691 int
692 t_uc390::inst_movx_a_$dptr (uchar code)
693 {
694   uchar pl, ph, px, dps;
695
696   dps = sfr->get (DPS);
697   if (dps & 1)
698     {
699       pl = DPL1;
700       ph = DPH1;
701       px = DPX1;
702     }
703   else
704     {
705       pl = DPL;
706       ph = DPH;
707       px = DPX;
708     }
709
710   //if ((sfr->get (ACON) & 0x3) == 2)
711   if (flat24_flag)
712     sfr->set (event_at.ws = ACC,
713               get_mem (MEM_XRAM,
714               event_at.rx = sfr->get (px) * 256*256 + sfr->get (ph) * 256 + sfr->get (pl)));
715   else
716     sfr->set (event_at.ws = ACC,
717              get_mem (MEM_XRAM,
718              event_at.rx = sfr->get (ph) * 256 + sfr->get (pl)));
719
720   if (dps & 0x20)                      /* auto-switch dptr */
721     sfr->set (DPS, (dps ^ 1));  /* toggle dual-dptr switch */
722
723   tick (1);
724   return resGO;
725 }
726
727 /*
728  * 0xf0 1 24 MOVX @DPTR,A
729  *____________________________________________________________________________
730  *
731  */
732
733 int
734 t_uc390::inst_movx_$dptr_a (uchar code)
735 {
736   uchar pl, ph, px, dps;
737
738   dps = sfr->get (DPS);
739   if (dps & 1)
740     {
741       pl = DPL1;
742       ph = DPH1;
743       px = DPX1;
744     }
745   else
746     {
747       pl = DPL;
748       ph = DPH;
749       px = DPX;
750     }
751
752   //if ((sfr->get (ACON) & 0x3) == 2)
753   if (flat24_flag)
754     set_mem (MEM_XRAM,
755              event_at.wx = sfr->get (px) * 256*256 + sfr->get (ph) * 256 + sfr->get (pl),
756              sfr->get (event_at.rs = ACC));
757   else
758     set_mem (MEM_XRAM,
759              event_at.wx = sfr->get (ph) * 256 + sfr->get (pl),
760              sfr->get (event_at.rs = ACC));
761
762   if (dps & 0x20)                      /* auto-switch dptr */
763     sfr->set (DPS, (dps ^ 1));  /* toggle dual-dptr switch */
764
765   tick (1);
766   return resGO;
767 }
768
769 /*
770  * 0x[02468ace]1 2 24 AJMP addr
771  *____________________________________________________________________________
772  *
773  */
774
775 int
776 t_uc390::inst_ajmp_addr (uchar code)
777 {
778   uchar x, h, l;
779
780   //if ((sfr->get (ACON) & 0x3) == 2)
781   if (flat24_flag)
782     {
783       x = (code >> 5) & 0x07;
784       h = fetch ();
785       l = fetch ();
786       PC = (PC & 0xf800) | (x * 256*256 + h * 256 + l);
787     }
788   else
789     {
790       h = (code >> 5) & 0x07;
791       l = fetch ();
792       PC = (PC & 0xf800) | (h * 256 + l);
793     }
794   tick (1);
795   return resGO;
796 }
797
798 /*
799  * 0x02 3 24 LJMP addr
800  *____________________________________________________________________________
801  *
802  */
803
804 int
805 t_uc390::inst_ljmp (uchar code)
806 {
807   uchar x, h, l;
808
809   //if ((sfr->get (ACON) & 0x3) == 2)
810   if (flat24_flag)
811     {
812       x = fetch ();
813       h = fetch ();
814       l = fetch ();
815       PC = x * 256*256 + h * 256 + l;
816     }
817   else
818     {
819       h = fetch ();
820       l = fetch ();
821       PC = h * 256 + l;
822     }
823   tick (1);
824   return resGO;
825 }
826
827 /*
828  * 0x[13579bdf]1 2 24 ACALL addr
829  *____________________________________________________________________________
830  *
831  */
832
833 int
834 t_uc390::inst_acall_addr (uchar code)
835 {
836   uchar x, h, l, *sp, *aof_SP;
837   int res;
838
839   //if ((sfr->get (ACON) & 0x3) == 2)
840   if (flat24_flag)
841     {
842       x = (code >> 5) & 0x07;
843       h = fetch ();
844       l = fetch ();
845
846       res = push_byte ( PC        & 0xff); /* push low byte  */
847       res = push_byte ((PC >>  8) & 0xff); /* push high byte */
848       res = push_byte ((PC >> 16) & 0xff); /* push x byte    */
849
850       PC = (PC & 0xf800) | (x * 256*256 + h * 256 + l);
851     }
852   else
853     {
854       /* stock mcs51 mode */
855       h = (code >> 5) & 0x07;
856       l = fetch ();
857       aof_SP = &((sfr->umem8)[SP]);
858
859       //MEM(MEM_SFR)[SP]++;
860       (*aof_SP)++;
861       proc_write_sp (*aof_SP);
862       sp = get_indirect (*aof_SP/*sfr->get (SP)*/, &res);
863       if (res != resGO)
864         res = resSTACK_OV;
865       *sp = PC & 0xff; // push low byte
866
867       //MEM(MEM_SFR)[SP]++;
868       (*aof_SP)++;
869       proc_write_sp (*aof_SP);
870       sp = get_indirect (*aof_SP/*sfr->get (SP)*/, &res);
871       if (res != resGO)
872         res = resSTACK_OV;
873       *sp = (PC >> 8) & 0xff; // push high byte
874
875       PC = (PC & 0xf800) | (h * 256 + l);
876     }
877   tick (1);
878   return res;
879 }
880
881
882 /*
883  * 0x12 3 24 LCALL addr
884  *____________________________________________________________________________
885  *
886  */
887
888 int
889 t_uc390::inst_lcall (uchar code, uint addr)
890 {
891   uchar x = 0, h = 0, l = 0;
892   int res;
893
894   if (!addr)
895     { /* this is a normal lcall */
896       //if ((sfr->get (ACON) & 0x3) == 2)
897       if (flat24_flag)
898         x = fetch ();
899       h = fetch ();
900       l = fetch ();
901     }
902     /* else, this is interrupt processing */
903
904   res = push_byte ( PC       & 0xff); /* push low byte  */
905   res = push_byte ((PC >> 8) & 0xff); /* push high byte */
906
907   //if ((sfr->get (ACON) & 0x3) == 2)
908   if (flat24_flag)
909     {
910       res = push_byte ((PC >> 16) & 0xff); /* push x byte */
911       if (addr)
912         PC = addr & 0xfffful; /* if interrupt: x-Byte is 0 */
913       else
914         PC = x * 256*256 + h * 256 + l;
915     }
916   else
917     {
918       if (addr)
919         PC = addr;
920       else
921         PC = h * 256 + l;
922     }
923   return res;
924 }
925
926 /*
927  * 0x22 1 24 RET
928  *____________________________________________________________________________
929  *
930  */
931
932 int
933 t_uc390::inst_ret (uchar code)
934 {
935   uchar x = 0, h, l;
936   int res;
937
938   //if ((sfr->get (ACON) & 0x3) == 2)
939   if (flat24_flag)
940     x = pop_byte (&res);
941   h = pop_byte (&res);
942   l = pop_byte (&res);
943
944   tick (1);
945
946   //if ((sfr->get (ACON) & 0x3) == 2)
947   if (flat24_flag)
948     {
949       tick (1);
950       PC = x * 256*256 + h * 256 + l;
951     }
952   else
953     PC = h * 256 + l;
954
955   return res;
956 }
957
958 /*
959  * 0x32 1 24 RETI
960  *____________________________________________________________________________
961  *
962  */
963
964 int
965 t_uc390::inst_reti (uchar code)
966 {
967   uchar x = 0, h, l;
968   int res;
969
970   //if ((sfr->get (ACON) & 0x3) == 2)
971   if (flat24_flag)
972   if (flat24_flag)
973     x = pop_byte (&res);
974   h = pop_byte (&res);
975   l = pop_byte (&res);
976   tick (1);
977
978   //if ((sfr->get (ACON) & 0x3) == 2)
979   if (flat24_flag)
980     {
981       tick (1);
982       PC = x * 256*256 + h * 256 + l;
983     }
984   else
985     PC = h * 256 + l;
986
987   was_reti = DD_TRUE;
988   class it_level *il = (class it_level *) (it_levels->top ());
989   if (il &&
990       il->level >= 0)
991     {
992       il = (class it_level *) (it_levels->pop ());
993       delete il;
994     }
995
996   return res;
997 }
998
999 /*
1000  * Disassembling an instruction
1001  */
1002
1003 struct dis_entry *
1004 t_uc390::dis_tbl (void)
1005 {
1006   //if ((sfr->get (ACON) & 0x3) == 2)
1007   if (!flat24_flag)
1008     return disass_51;
1009     //t_uc51::dis_tbl ();
1010
1011   return disass_390f;
1012 }
1013
1014 char *
1015 t_uc390::disass (t_addr addr, char *sep)
1016 {
1017   char work[256], temp[20], c[2];
1018   char *buf, *p, *b, *t;
1019   t_mem code;
1020
1021   //if ((sfr->get (ACON) & 0x3) == 2)
1022   if (!flat24_flag)
1023     return t_uc51::disass (addr, sep);
1024   code = get_mem (MEM_ROM, addr);
1025
1026   p = work;
1027   b = dis_tbl ()[code].mnemonic;
1028   while (*b)
1029     {
1030       if (*b == '%')
1031         {
1032           b++;
1033           switch (*(b++))
1034             {
1035               case 'A': // absolute address
1036                 // stock:
1037                 // sprintf (temp, "%04lx",
1038                 //          (addr & 0xf800)|
1039                 //          (((code >> 5) & 0x07) * 256 +
1040                 //          get_mem (MEM_ROM, addr + 1)));
1041
1042                 sprintf (temp, "%06lx",
1043                          (addr & 0xf80000) |
1044                          (((code >> 5) & 0x07) * (256 * 256) +
1045                          (get_mem (MEM_ROM, addr + 1) * 256) +
1046                           get_mem (MEM_ROM, addr + 2)));
1047               break;
1048             case 'l': // long address
1049               sprintf (temp, "%06lx",
1050                        get_mem (MEM_ROM, addr + 1) * (256*256) +
1051                        get_mem (MEM_ROM, addr + 2) * 256 +
1052                        get_mem (MEM_ROM, addr + 3));
1053                        // get_mem (MEM_ROM, addr + 1) * 256 + get_mem (MEM_ROM, addr + 2));
1054               break;
1055             case 'a': // addr8 (direct address) at 2nd byte
1056                if (!get_name (get_mem (MEM_ROM, addr + 1), sfr_tbl (), temp))
1057                  sprintf (temp, "%02lx", get_mem (MEM_ROM, addr + 1));
1058               break;
1059             case '8': // addr8 (direct address) at 3rd byte
1060               if (!get_name (get_mem (MEM_ROM, addr + 2), sfr_tbl (), temp))
1061                 sprintf (temp, "%02lx", get_mem (MEM_ROM, addr + 1));
1062               sprintf (temp, "%02lx", get_mem (MEM_ROM, addr + 2));
1063               break;
1064             case 'b': // bitaddr at 2nd byte
1065               if (get_name (get_mem (MEM_ROM, addr + 1), bit_tbl (), temp))
1066                 break;
1067               if (get_name (get_bitidx (get_mem (MEM_ROM, addr + 1)),
1068                             sfr_tbl (), temp))
1069                 {
1070                   strcat (temp, ".");
1071                   sprintf (c, "%1ld", get_mem (MEM_ROM, addr + 1) & 0x07);
1072                   strcat (temp, c);
1073                   break;
1074                 }
1075               sprintf (temp, "%02x.%ld",
1076                        get_bitidx (get_mem (MEM_ROM, addr + 1)),
1077                        get_mem (MEM_ROM, addr + 1) & 0x07);
1078               break;
1079             case 'r': // rel8 address at 2nd byte
1080               sprintf (temp, "%04lx",
1081                        addr + 2 + (signed char) (get_mem (MEM_ROM, addr + 1)));
1082               break;
1083             case 'R': // rel8 address at 3rd byte
1084               sprintf (temp, "%04lx",
1085                        addr + 3 + (signed char) (get_mem (MEM_ROM, addr + 2)));
1086               break;
1087             case 'd': // data8 at 2nd byte
1088               sprintf (temp, "%02lx", get_mem (MEM_ROM, addr + 1));
1089               break;
1090             case 'D': // data8 at 3rd byte
1091               sprintf (temp, "%02lx", get_mem (MEM_ROM, addr + 2));
1092               break;
1093             default:
1094               strcpy (temp, "?");
1095               break;
1096             }
1097           t = temp;
1098           while (*t)
1099             *p++ = *t++;
1100         }
1101       else
1102         *p++ = *b++;
1103     }
1104   *p = '\0';
1105
1106   p = strchr (work, ' ');
1107   if (!p)
1108     {
1109       buf = strdup (work);
1110       return buf;
1111     }
1112   if (sep == NULL)
1113     buf = (char *) malloc (6 + strlen (p) + 1);
1114   else
1115     buf = (char *) malloc ((p - work) + strlen (sep) + strlen (p) + 1);
1116   for (p = work, b = buf; *p != ' '; p++, b++)
1117     *b = *p;
1118   p++;
1119   *b = '\0';
1120   if (sep == NULL)
1121     while (strlen (buf) < 6)
1122       strcat (buf, " ");
1123   else
1124     strcat (buf, sep);
1125   strcat (buf, p);
1126   return buf;
1127 }
1128
1129 void
1130 t_uc390::print_regs(class cl_console *con)
1131 {
1132   t_addr start;
1133   uchar data;
1134
1135   //if ((sfr->get (ACON) & 0x3) == 2)
1136   if (!flat24_flag)
1137     {
1138       t_uc51::print_regs (con);
1139       return;
1140     }
1141   start = sfr->get (PSW) & 0x18;
1142   //dump_memory(iram, &start, start+7, 8, /*sim->cmd_out()*/con, sim);
1143   iram->dump (start, start + 7, 8, con);
1144   start = sfr->get (PSW) & 0x18;
1145   data = iram->get (iram->get (start));
1146   con->printf ("%06x %02x %c",
1147                iram->get (start), data, isprint (data) ? data : '.');
1148   con->printf ("  ACC= 0x%02x %3d %c  B= 0x%02x",
1149                sfr->get (ACC), sfr->get (ACC),
1150                isprint (sfr->get (ACC)) ? (sfr->get (ACC)) : '.', sfr->get (B));
1151   eram2xram ();
1152   data = get_mem (MEM_XRAM,
1153                   sfr->get (DPX) * 256*256 + sfr->get (DPH) * 256 + sfr->get (DPL));
1154   con->printf ("   DPTR= 0x%02x%02x%02x @DPTR= 0x%02x %3d %c\n",
1155                sfr->get (DPX), sfr->get (DPH), sfr->get (DPL),
1156                data, data, isprint (data) ? data : '.');
1157   data = iram->get (iram->get (start + 1));
1158   con->printf ("%06x %02x %c", iram->get (start + 1), data,
1159                isprint (data) ? data : '.');
1160   data= sfr->get (PSW);
1161   con->printf ("  PSW= 0x%02x CY=%c AC=%c OV=%c P=%c    ",
1162                data,
1163                (data & bmCY) ? '1' : '0', (data & bmAC) ? '1' : '0',
1164                (data & bmOV) ? '1' : '0', (data & bmP ) ? '1' : '0'
1165                );
1166   /* show stack pointer */
1167   if (sfr->get (ACON) & 0x04)
1168     /* SA: 10 bit stack */
1169     con->printf ("SP10 0x%03x %3d\n",
1170                  (sfr->get (ESP) & 3) * 256 + sfr->get (SP),
1171                  get_mem (MEM_XRAM, (sfr->get (ESP) & 3) * 256 + sfr->get (SP) + 0x400000)
1172                 );
1173   else
1174     con->printf ("SP 0x%02x %3d\n",
1175                  sfr->get (SP),
1176                  iram->get (sfr->get (SP))
1177                 );
1178   print_disass (PC, con);
1179 }
1180 /* End of s51.src/uc390.cc */