sim: bfin: stricter insn decoding
[external/binutils.git] / sim / bfin / dv-bfin_uart.c
1 /* Blackfin Universal Asynchronous Receiver/Transmitter (UART) model.
2    For "old style" UARTs on BF53x/etc... parts.
3
4    Copyright (C) 2010-2013 Free Software Foundation, Inc.
5    Contributed by Analog Devices, Inc.
6
7    This file is part of simulators.
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 3 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18
19    You should have received a copy of the GNU General Public License
20    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
21
22 #include "config.h"
23
24 #include "sim-main.h"
25 #include "dv-sockser.h"
26 #include "devices.h"
27 #include "dv-bfin_uart.h"
28
29 /* XXX: Should we bother emulating the TX/RX FIFOs ?  */
30
31 /* Internal state needs to be the same as bfin_uart2.  */
32 struct bfin_uart
33 {
34   /* This top portion matches common dv_bfin struct.  */
35   bu32 base;
36   struct hw *dma_master;
37   bool acked;
38
39   struct hw_event *handler;
40   char saved_byte;
41   int saved_count;
42
43   /* This is aliased to DLH.  */
44   bu16 ier;
45   /* These are aliased to DLL.  */
46   bu16 thr, rbr;
47
48   /* Order after here is important -- matches hardware MMR layout.  */
49   bu16 BFIN_MMR_16(dll);
50   bu16 BFIN_MMR_16(dlh);
51   bu16 BFIN_MMR_16(iir);
52   bu16 BFIN_MMR_16(lcr);
53   bu16 BFIN_MMR_16(mcr);
54   bu16 BFIN_MMR_16(lsr);
55   bu16 BFIN_MMR_16(msr);
56   bu16 BFIN_MMR_16(scr);
57   bu16 _pad0[2];
58   bu16 BFIN_MMR_16(gctl);
59 };
60 #define mmr_base()      offsetof(struct bfin_uart, dll)
61 #define mmr_offset(mmr) (offsetof(struct bfin_uart, mmr) - mmr_base())
62
63 static const char * const mmr_names[] =
64 {
65   "UART_RBR/UART_THR", "UART_IER", "UART_IIR", "UART_LCR", "UART_MCR",
66   "UART_LSR", "UART_MSR", "UART_SCR", "<INV>", "UART_GCTL",
67 };
68 static const char *mmr_name (struct bfin_uart *uart, bu32 idx)
69 {
70   if (uart->lcr & DLAB)
71     if (idx < 2)
72       return idx == 0 ? "UART_DLL" : "UART_DLH";
73   return mmr_names[idx];
74 }
75 #define mmr_name(off) mmr_name (uart, (off) / 4)
76
77 #ifndef HAVE_DV_SOCKSER
78 # define dv_sockser_status(sd) -1
79 # define dv_sockser_write(sd, byte) do { ; } while (0)
80 # define dv_sockser_read(sd) 0xff
81 #endif
82
83 static void
84 bfin_uart_poll (struct hw *me, void *data)
85 {
86   struct bfin_uart *uart = data;
87   bu16 lsr;
88
89   uart->handler = NULL;
90
91   lsr = bfin_uart_get_status (me);
92   if (lsr & DR)
93     hw_port_event (me, DV_PORT_RX, 1);
94
95   bfin_uart_reschedule (me);
96 }
97
98 void
99 bfin_uart_reschedule (struct hw *me)
100 {
101   struct bfin_uart *uart = hw_data (me);
102
103   if (uart->ier & ERBFI)
104     {
105       if (!uart->handler)
106         uart->handler = hw_event_queue_schedule (me, 10000,
107                                                  bfin_uart_poll, uart);
108     }
109   else
110     {
111       if (uart->handler)
112         {
113           hw_event_queue_deschedule (me, uart->handler);
114           uart->handler = NULL;
115         }
116     }
117 }
118
119 bu16
120 bfin_uart_write_byte (struct hw *me, bu16 thr, bu16 mcr)
121 {
122   struct bfin_uart *uart = hw_data (me);
123   unsigned char ch = thr;
124
125   if (mcr & LOOP_ENA)
126     {
127       /* XXX: This probably doesn't work exactly right with
128               external FIFOs ...  */
129       uart->saved_byte = thr;
130       uart->saved_count = 1;
131     }
132
133   bfin_uart_write_buffer (me, &ch, 1);
134
135   return thr;
136 }
137
138 static unsigned
139 bfin_uart_io_write_buffer (struct hw *me, const void *source,
140                            int space, address_word addr, unsigned nr_bytes)
141 {
142   struct bfin_uart *uart = hw_data (me);
143   bu32 mmr_off;
144   bu32 value;
145   bu16 *valuep;
146
147   value = dv_load_2 (source);
148   mmr_off = addr - uart->base;
149   valuep = (void *)((unsigned long)uart + mmr_base() + mmr_off);
150
151   HW_TRACE_WRITE ();
152
153   dv_bfin_mmr_require_16 (me, addr, nr_bytes, true);
154
155   /* XXX: All MMRs are "8bit" ... what happens to high 8bits ?  */
156   switch (mmr_off)
157     {
158     case mmr_offset(dll):
159       if (uart->lcr & DLAB)
160         uart->dll = value;
161       else
162         {
163           uart->thr = bfin_uart_write_byte (me, value, uart->mcr);
164
165           if (uart->ier & ETBEI)
166             hw_port_event (me, DV_PORT_TX, 1);
167         }
168       break;
169     case mmr_offset(dlh):
170       if (uart->lcr & DLAB)
171         uart->dlh = value;
172       else
173         {
174           uart->ier = value;
175           bfin_uart_reschedule (me);
176         }
177       break;
178     case mmr_offset(iir):
179     case mmr_offset(lsr):
180       /* XXX: Writes are ignored ?  */
181       break;
182     case mmr_offset(lcr):
183     case mmr_offset(mcr):
184     case mmr_offset(scr):
185     case mmr_offset(gctl):
186       *valuep = value;
187       break;
188     default:
189       dv_bfin_mmr_invalid (me, addr, nr_bytes, true);
190       break;
191     }
192
193   return nr_bytes;
194 }
195
196 /* Switch between socket and stdin on the fly.  */
197 bu16
198 bfin_uart_get_next_byte (struct hw *me, bu16 rbr, bu16 mcr, bool *fresh)
199 {
200   SIM_DESC sd = hw_system (me);
201   struct bfin_uart *uart = hw_data (me);
202   int status = dv_sockser_status (sd);
203   bool _fresh;
204
205   /* NB: The "uart" here may only use interal state.  */
206
207   if (!fresh)
208     fresh = &_fresh;
209
210   *fresh = false;
211
212   if (uart->saved_count > 0)
213     {
214       *fresh = true;
215       rbr = uart->saved_byte;
216       --uart->saved_count;
217     }
218   else if (mcr & LOOP_ENA)
219     {
220       /* RX is disconnected, so only return local data.  */
221     }
222   else if (status & DV_SOCKSER_DISCONNECTED)
223     {
224       char byte;
225       int ret = sim_io_poll_read (sd, 0/*STDIN*/, &byte, 1);
226
227       if (ret > 0)
228         {
229           *fresh = true;
230           rbr = byte;
231         }
232     }
233   else
234     rbr = dv_sockser_read (sd);
235
236   return rbr;
237 }
238
239 bu16
240 bfin_uart_get_status (struct hw *me)
241 {
242   SIM_DESC sd = hw_system (me);
243   struct bfin_uart *uart = hw_data (me);
244   int status = dv_sockser_status (sd);
245   bu16 lsr = 0;
246
247   if (status & DV_SOCKSER_DISCONNECTED)
248     {
249       if (uart->saved_count <= 0)
250         uart->saved_count = sim_io_poll_read (sd, 0/*STDIN*/,
251                                               &uart->saved_byte, 1);
252       lsr |= TEMT | THRE | (uart->saved_count > 0 ? DR : 0);
253     }
254   else
255     lsr |= (status & DV_SOCKSER_INPUT_EMPTY ? 0 : DR) |
256            (status & DV_SOCKSER_OUTPUT_EMPTY ? TEMT | THRE : 0);
257
258   return lsr;
259 }
260
261 static unsigned
262 bfin_uart_io_read_buffer (struct hw *me, void *dest,
263                           int space, address_word addr, unsigned nr_bytes)
264 {
265   struct bfin_uart *uart = hw_data (me);
266   bu32 mmr_off;
267   bu16 *valuep;
268
269   mmr_off = addr - uart->base;
270   valuep = (void *)((unsigned long)uart + mmr_base() + mmr_off);
271
272   HW_TRACE_READ ();
273
274   dv_bfin_mmr_require_16 (me, addr, nr_bytes, false);
275
276   switch (mmr_off)
277     {
278     case mmr_offset(dll):
279       if (uart->lcr & DLAB)
280         dv_store_2 (dest, uart->dll);
281       else
282         {
283           uart->rbr = bfin_uart_get_next_byte (me, uart->rbr, uart->mcr, NULL);
284           dv_store_2 (dest, uart->rbr);
285         }
286       break;
287     case mmr_offset(dlh):
288       if (uart->lcr & DLAB)
289         dv_store_2 (dest, uart->dlh);
290       else
291         dv_store_2 (dest, uart->ier);
292       break;
293     case mmr_offset(lsr):
294       /* XXX: Reads are destructive on most parts, but not all ...  */
295       uart->lsr |= bfin_uart_get_status (me);
296       dv_store_2 (dest, *valuep);
297       uart->lsr = 0;
298       break;
299     case mmr_offset(iir):
300       /* XXX: Reads are destructive ...  */
301     case mmr_offset(lcr):
302     case mmr_offset(mcr):
303     case mmr_offset(scr):
304     case mmr_offset(gctl):
305       dv_store_2 (dest, *valuep);
306       break;
307     default:
308       dv_bfin_mmr_invalid (me, addr, nr_bytes, false);
309       break;
310     }
311
312   return nr_bytes;
313 }
314
315 unsigned
316 bfin_uart_read_buffer (struct hw *me, unsigned char *buffer, unsigned nr_bytes)
317 {
318   SIM_DESC sd = hw_system (me);
319   struct bfin_uart *uart = hw_data (me);
320   int status = dv_sockser_status (sd);
321   unsigned i = 0;
322
323   if (status & DV_SOCKSER_DISCONNECTED)
324     {
325       int ret;
326
327       while (uart->saved_count > 0 && i < nr_bytes)
328         {
329           buffer[i++] = uart->saved_byte;
330           --uart->saved_count;
331         }
332
333       ret = sim_io_poll_read (sd, 0/*STDIN*/, (char *) buffer, nr_bytes - i);
334       if (ret > 0)
335         i += ret;
336     }
337   else
338     buffer[i++] = dv_sockser_read (sd);
339
340   return i;
341 }
342
343 static unsigned
344 bfin_uart_dma_read_buffer (struct hw *me, void *dest, int space,
345                            unsigned_word addr, unsigned nr_bytes)
346 {
347   HW_TRACE_DMA_READ ();
348   return bfin_uart_read_buffer (me, dest, nr_bytes);
349 }
350
351 unsigned
352 bfin_uart_write_buffer (struct hw *me, const unsigned char *buffer,
353                         unsigned nr_bytes)
354 {
355   SIM_DESC sd = hw_system (me);
356   int status = dv_sockser_status (sd);
357
358   if (status & DV_SOCKSER_DISCONNECTED)
359     {
360       sim_io_write_stdout (sd, (const char *) buffer, nr_bytes);
361       sim_io_flush_stdout (sd);
362     }
363   else
364     {
365       /* Normalize errors to a value of 0.  */
366       int ret = dv_sockser_write_buffer (sd, buffer, nr_bytes);
367       nr_bytes = CLAMP (ret, 0, nr_bytes);
368     }
369
370   return nr_bytes;
371 }
372
373 static unsigned
374 bfin_uart_dma_write_buffer (struct hw *me, const void *source,
375                             int space, unsigned_word addr,
376                             unsigned nr_bytes,
377                             int violate_read_only_section)
378 {
379   struct bfin_uart *uart = hw_data (me);
380   unsigned ret;
381
382   HW_TRACE_DMA_WRITE ();
383
384   ret = bfin_uart_write_buffer (me, source, nr_bytes);
385
386   if (ret == nr_bytes && (uart->ier & ETBEI))
387     hw_port_event (me, DV_PORT_TX, 1);
388
389   return ret;
390 }
391
392 static const struct hw_port_descriptor bfin_uart_ports[] =
393 {
394   { "tx",   DV_PORT_TX,   0, output_port, },
395   { "rx",   DV_PORT_RX,   0, output_port, },
396   { "stat", DV_PORT_STAT, 0, output_port, },
397   { NULL, 0, 0, 0, },
398 };
399
400 static void
401 attach_bfin_uart_regs (struct hw *me, struct bfin_uart *uart)
402 {
403   address_word attach_address;
404   int attach_space;
405   unsigned attach_size;
406   reg_property_spec reg;
407
408   if (hw_find_property (me, "reg") == NULL)
409     hw_abort (me, "Missing \"reg\" property");
410
411   if (!hw_find_reg_array_property (me, "reg", 0, &reg))
412     hw_abort (me, "\"reg\" property must contain three addr/size entries");
413
414   hw_unit_address_to_attach_address (hw_parent (me),
415                                      &reg.address,
416                                      &attach_space, &attach_address, me);
417   hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
418
419   if (attach_size != BFIN_MMR_UART_SIZE)
420     hw_abort (me, "\"reg\" size must be %#x", BFIN_MMR_UART_SIZE);
421
422   hw_attach_address (hw_parent (me),
423                      0, attach_space, attach_address, attach_size, me);
424
425   uart->base = attach_address;
426 }
427
428 static void
429 bfin_uart_finish (struct hw *me)
430 {
431   struct bfin_uart *uart;
432
433   uart = HW_ZALLOC (me, struct bfin_uart);
434
435   set_hw_data (me, uart);
436   set_hw_io_read_buffer (me, bfin_uart_io_read_buffer);
437   set_hw_io_write_buffer (me, bfin_uart_io_write_buffer);
438   set_hw_dma_read_buffer (me, bfin_uart_dma_read_buffer);
439   set_hw_dma_write_buffer (me, bfin_uart_dma_write_buffer);
440   set_hw_ports (me, bfin_uart_ports);
441
442   attach_bfin_uart_regs (me, uart);
443
444   /* Initialize the UART.  */
445   uart->dll = 0x0001;
446   uart->iir = 0x0001;
447   uart->lsr = 0x0060;
448 }
449
450 const struct hw_descriptor dv_bfin_uart_descriptor[] =
451 {
452   {"bfin_uart", bfin_uart_finish,},
453   {NULL, NULL},
454 };