/[gxemul]/trunk/src/devices/dev_sh4.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /trunk/src/devices/dev_sh4.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 37 by dpavlin, Mon Oct 8 16:21:34 2007 UTC revision 38 by dpavlin, Mon Oct 8 16:21:53 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *     *  
27   *   *
28   *  $Id: dev_sh4.c,v 1.32 2007/03/16 18:47:26 debug Exp $   *  $Id: dev_sh4.c,v 1.39 2007/04/13 16:12:39 debug Exp $
29   *     *  
30   *  SH4 processor specific memory mapped registers (0xf0000000 - 0xffffffff).   *  SH4 processor specific memory mapped registers (0xf0000000 - 0xffffffff).
31   *   *
32   *  TODO: Lots and lots of stuff.   *  TODO: Among other things:
33     *
34     *      x)  Interrupt masks (msk register stuff).
35     *      x)  BSC (Bus state controller).
36     *      x)  DMA
37     *      x)  UBC
38     *      x)  ...
39   */   */
40    
41  #include <stdio.h>  #include <stdio.h>
# Line 54  Line 60 
60  #include "sh4_mmu.h"  #include "sh4_mmu.h"
61  #include "sh4_rtcreg.h"  #include "sh4_rtcreg.h"
62  #include "sh4_scifreg.h"  #include "sh4_scifreg.h"
63    #include "sh4_scireg.h"
64  #include "sh4_tmureg.h"  #include "sh4_tmureg.h"
65    
66    
# Line 61  Line 68 
68  #define SH4_TICK_SHIFT          14  #define SH4_TICK_SHIFT          14
69  #define N_SH4_TIMERS            3  #define N_SH4_TIMERS            3
70    
71    #define SCIF_TX_FIFO_SIZE       16
72    
73  /*  General-purpose I/O stuff:  */  /*  General-purpose I/O stuff:  */
74  #define SH4_PCTRA               0xff80002c  #define SH4_PCTRA               0xff80002c
75  #define SH4_PDTRA               0xff800030  #define SH4_PDTRA               0xff800030
# Line 80  struct sh4_data { Line 89  struct sh4_data {
89          uint16_t        scif_scr;          uint16_t        scif_scr;
90          uint16_t        scif_ssr;          uint16_t        scif_ssr;
91          uint16_t        scif_fcr;          uint16_t        scif_fcr;
92            uint16_t        scif_lsr;
93          int             scif_delayed_tx;          int             scif_delayed_tx;
94          int             scif_console_handle;          int             scif_console_handle;
95            uint8_t         scif_tx_fifo[SCIF_TX_FIFO_SIZE + 1];
96            int             scif_tx_fifo_cursize;
97          struct interrupt scif_tx_irq;          struct interrupt scif_tx_irq;
98          struct interrupt scif_rx_irq;          struct interrupt scif_rx_irq;
99            int             scif_tx_irq_asserted;
100            int             scif_rx_irq_asserted;
101    
102          /*  Bus State Controller:  */          /*  Bus State Controller:  */
103          uint32_t        bsc_bcr1;          uint32_t        bsc_bcr1;
# Line 101  struct sh4_data { Line 115  struct sh4_data {
115          uint32_t        pctrb;          /*  Port Control Register B  */          uint32_t        pctrb;          /*  Port Control Register B  */
116          uint32_t        pdtrb;          /*  Port Data Register B  */          uint32_t        pdtrb;          /*  Port Data Register B  */
117    
118            /*  SCI (serial interface):  */
119            int             sci_bits_outputed;
120            int             sci_bits_read;
121            uint8_t         sci_scsptr;
122            uint8_t         sci_curbyte;
123            uint8_t         sci_cur_addr;
124    
125          /*  SD-RAM:  */          /*  SD-RAM:  */
126          uint16_t        sdmr2;          uint16_t        sdmr2;
127          uint16_t        sdmr3;          uint16_t        sdmr3;
# Line 122  struct sh4_data { Line 143  struct sh4_data {
143  };  };
144    
145    
146  #define SH4_PSEUDO_TIMER_HZ     100.0  #define SH4_PSEUDO_TIMER_HZ     110.0
147    
148    
149  /*  /*
# Line 186  static void sh4_timer_tick(struct timer Line 207  static void sh4_timer_tick(struct timer
207    
208  static void scif_reassert_interrupts(struct sh4_data *d)  static void scif_reassert_interrupts(struct sh4_data *d)
209  {  {
210          if (d->scif_scr & SCSCR2_RIE) {          int old_tx_asserted = d->scif_tx_irq_asserted;
211                  if (d->scif_ssr & SCSSR2_DR)          int old_rx_asserted = d->scif_rx_irq_asserted;
212                          INTERRUPT_ASSERT(d->scif_rx_irq);  
213          } else {          d->scif_rx_irq_asserted =
214                d->scif_scr & SCSCR2_RIE && d->scif_ssr & SCSSR2_DR;
215    
216            if (d->scif_rx_irq_asserted && !old_rx_asserted)
217                    INTERRUPT_ASSERT(d->scif_rx_irq);
218            else if (!d->scif_rx_irq_asserted && old_rx_asserted)
219                  INTERRUPT_DEASSERT(d->scif_rx_irq);                  INTERRUPT_DEASSERT(d->scif_rx_irq);
220          }  
221          if (d->scif_scr & SCSCR2_TIE) {          d->scif_tx_irq_asserted =
222                  if (d->scif_ssr & (SCSSR2_TDFE | SCSSR2_TEND))              d->scif_scr & SCSCR2_TIE &&
223                          INTERRUPT_ASSERT(d->scif_tx_irq);              d->scif_ssr & (SCSSR2_TDFE | SCSSR2_TEND);
224          } else {  
225            if (d->scif_tx_irq_asserted && !old_tx_asserted)
226                    INTERRUPT_ASSERT(d->scif_tx_irq);
227            else if (!d->scif_tx_irq_asserted && old_tx_asserted)
228                  INTERRUPT_DEASSERT(d->scif_tx_irq);                  INTERRUPT_DEASSERT(d->scif_tx_irq);
         }  
229  }  }
230    
231    
# Line 206  DEVICE_TICK(sh4) Line 234  DEVICE_TICK(sh4)
234          struct sh4_data *d = (struct sh4_data *) extra;          struct sh4_data *d = (struct sh4_data *) extra;
235          int i;          int i;
236    
237          /*  Serial controller interrupts:  */          /*
238          /*  TODO: Which bits go to which interrupt?  */           *  Serial controller interrupts:
239             *
240             *  RX: Cause interrupt if any char is available.
241             *  TX: Send entire TX FIFO contents, and interrupt.
242             */
243          if (console_charavail(d->scif_console_handle))          if (console_charavail(d->scif_console_handle))
244                  d->scif_ssr |= SCSSR2_DR;                  d->scif_ssr |= SCSSR2_DR;
245          else          else
246                  d->scif_ssr &= SCSSR2_DR;                  d->scif_ssr &= ~SCSSR2_DR;
247    
248          if (d->scif_delayed_tx) {          if (d->scif_delayed_tx) {
249                  if (--d->scif_delayed_tx == 0)                  if (--d->scif_delayed_tx == 0) {
250                            /*  Send TX FIFO contents:  */
251                            for (i=0; i<d->scif_tx_fifo_cursize; i++)
252                                    console_putchar(d->scif_console_handle,
253                                        d->scif_tx_fifo[i]);
254    
255                            /*  Clear FIFO:  */
256                            d->scif_tx_fifo_cursize = 0;
257    
258                            /*  Done sending; cause a transmit end interrupt:  */
259                          d->scif_ssr |= SCSSR2_TDFE | SCSSR2_TEND;                          d->scif_ssr |= SCSSR2_TDFE | SCSSR2_TEND;
260                    }
261          }          }
262    
263          scif_reassert_interrupts(d);          scif_reassert_interrupts(d);
# Line 228  DEVICE_TICK(sh4) Line 271  DEVICE_TICK(sh4)
271  }  }
272    
273    
274    /*
275     *  sh_sci_cmd():
276     *
277     *  Handle a SCI command byte.
278     *
279     *  Bit:   Meaning:
280     *   7      Ignored (usually 1?)
281     *   6      0=Write, 1=Read
282     *   5      AD: Address transfer
283     *   4      DT: Data transfer
284     *   3..0   Data or address bits
285     */
286    static void sh_sci_cmd(struct sh4_data *d, struct cpu *cpu)
287    {
288            uint8_t cmd = d->sci_curbyte;
289            int writeflag = cmd & 0x40? 0 : 1;
290            int address_transfer;
291    
292            /*  fatal("[ CMD BYTE %02x ]\n", cmd);  */
293    
294            if (!(cmd & 0x80)) {
295                    fatal("SCI cmd bit 7 not set? TODO\n");
296                    exit(1);
297            }
298    
299            if ((cmd & 0x30) == 0x20)
300                    address_transfer = 1;
301            else if ((cmd & 0x30) == 0x10)
302                    address_transfer = 0;
303            else {
304                    fatal("SCI: Neither data nor address transfer? TODO\n");
305                    exit(1);
306            }
307    
308            if (address_transfer)
309                    d->sci_cur_addr = cmd & 0x0f;
310    
311            if (!writeflag) {
312                    /*  Read data from the current address:  */
313                    uint8_t data_byte;
314    
315                    cpu->memory_rw(cpu, cpu->mem, SCI_DEVICE_BASE + d->sci_cur_addr,
316                        &data_byte, 1, MEM_READ, PHYSICAL);
317    
318                    debug("[ SCI: read addr=%x data=%x ]\n",
319                        d->sci_cur_addr, data_byte);
320    
321                    d->sci_curbyte = data_byte;
322    
323                    /*  Set bit 7 right away:  */
324                    d->sci_scsptr &= ~SCSPTR_SPB1DT;
325                    if (data_byte & 0x80)
326                            d->sci_scsptr |= SCSPTR_SPB1DT;
327            }
328    
329            if (writeflag && !address_transfer) {
330                    /*  Write the 4 data bits to the current address:  */
331                    uint8_t data_byte = cmd & 0x0f;
332    
333                    debug("[ SCI: write addr=%x data=%x ]\n",
334                        d->sci_cur_addr, data_byte);
335    
336                    cpu->memory_rw(cpu, cpu->mem, SCI_DEVICE_BASE + d->sci_cur_addr,
337                        &data_byte, 1, MEM_WRITE, PHYSICAL);
338            }
339    }
340    
341    
342    /*
343     *  sh_sci_access():
344     *
345     *  Reads or writes a bit via the SH4's serial interface. If writeflag is
346     *  non-zero, input is used. If writeflag is zero, a bit is outputed as
347     *  the return value from this function.
348     */
349    static uint8_t sh_sci_access(struct sh4_data *d, struct cpu *cpu,
350            int writeflag, uint8_t input)
351    {
352            if (writeflag) {
353                    /*  WRITE:  */
354                    int clockpulse;
355                    uint8_t old = d->sci_scsptr;
356                    d->sci_scsptr = input;
357    
358                    /*
359                     *  Clock pulse (SCSPTR_SPB0DT going from 0 to 1,
360                     *  when SCSPTR_SPB0IO was already set):
361                     */
362                    clockpulse = old & SCSPTR_SPB0IO &&
363                        d->sci_scsptr & SCSPTR_SPB0DT &&
364                        !(old & SCSPTR_SPB0DT);
365    
366                    if (!clockpulse)
367                            return 0;
368    
369                    /*  Are we in output or input mode?  */
370                    if (d->sci_scsptr & SCSPTR_SPB1IO) {
371                            /*  Output:  */
372                            int bit = d->sci_scsptr & SCSPTR_SPB1DT? 1 : 0;
373                            d->sci_curbyte <<= 1;
374                            d->sci_curbyte |= bit;
375                            d->sci_bits_outputed ++;
376                            if (d->sci_bits_outputed == 8) {
377                                    /*  4 control bits and 4 address/data bits have
378                                        been written.  */
379                                    sh_sci_cmd(d, cpu);
380                                    d->sci_bits_outputed = 0;
381                            }
382                    } else {
383                            /*  Input:  */
384                            int bit;
385                            d->sci_bits_read ++;
386                            d->sci_bits_read &= 7;
387    
388                            bit = d->sci_curbyte & (0x80 >> d->sci_bits_read);
389    
390                            d->sci_scsptr &= ~SCSPTR_SPB1DT;
391                            if (bit)
392                                    d->sci_scsptr |= SCSPTR_SPB1DT;
393                    }
394    
395                    /*  Return (value doesn't matter).  */
396                    return 0;
397            } else {
398                    /*  READ:  */
399                    return d->sci_scsptr;
400            }
401    }
402    
403    
404  DEVICE_ACCESS(sh4_itlb_aa)  DEVICE_ACCESS(sh4_itlb_aa)
405  {  {
406          uint64_t idata = 0, odata = 0;          uint64_t idata = 0, odata = 0;
# Line 368  DEVICE_ACCESS(sh4_utlb_aa) Line 541  DEVICE_ACCESS(sh4_utlb_aa)
541                                          continue;                                          continue;
542    
543                                  if (i < 0) {                                  if (i < 0) {
544                                          cpu->cd.sh.itlb_lo[i] &= ~SH4_PTEL_V;                                          cpu->cd.sh.itlb_lo[i +
545                                                SH_N_ITLB_ENTRIES] &= ~SH4_PTEL_V;
546                                          if (idata & SH4_UTLB_AA_V)                                          if (idata & SH4_UTLB_AA_V)
547                                                  cpu->cd.sh.itlb_lo[i] |=                                                  cpu->cd.sh.itlb_lo[
548                                                        i+SH_N_ITLB_ENTRIES] |=
549                                                      SH4_PTEL_V;                                                      SH4_PTEL_V;
550                                  } else {                                  } else {
551                                          cpu->cd.sh.utlb_lo[i] &=                                          cpu->cd.sh.utlb_lo[i] &=
# Line 739  DEVICE_ACCESS(sh4) Line 914  DEVICE_ACCESS(sh4)
914                                  exit(1);                                  exit(1);
915                          }                          }
916    
917                            INTERRUPT_DEASSERT(d->timer_irq[timer_nr]);
918    
919                          if (d->tcr[timer_nr] & TCR_UNF && !(idata & TCR_UNF)) {                          if (d->tcr[timer_nr] & TCR_UNF && !(idata & TCR_UNF)) {
                                 INTERRUPT_DEASSERT(d->timer_irq[timer_nr]);  
920                                  if (d->timer_interrupts_pending[timer_nr] > 0)                                  if (d->timer_interrupts_pending[timer_nr] > 0)
921                                          d->timer_interrupts_pending[timer_nr]--;                                          d->timer_interrupts_pending[timer_nr]--;
922                          }                          }
# Line 947  DEVICE_ACCESS(sh4) Line 1123  DEVICE_ACCESS(sh4)
1123                  break;                  break;
1124    
1125    
1126            /****************************/
1127            /*  SCI:  Serial Interface  */
1128    
1129            case SHREG_SCSPTR:
1130                    odata = sh_sci_access(d, cpu,
1131                        writeflag == MEM_WRITE? 1 : 0, idata);
1132                    break;
1133    
1134    
1135          /*********************************/          /*********************************/
1136          /*  INTC:  Interrupt Controller  */          /*  INTC:  Interrupt Controller  */
1137    
# Line 963  DEVICE_ACCESS(sh4) Line 1148  DEVICE_ACCESS(sh4)
1148          case SH4_IPRA:          case SH4_IPRA:
1149                  if (writeflag == MEM_READ)                  if (writeflag == MEM_READ)
1150                          odata = cpu->cd.sh.intc_ipra;                          odata = cpu->cd.sh.intc_ipra;
1151                  else                  else {
1152                          cpu->cd.sh.intc_ipra = idata;                          cpu->cd.sh.intc_ipra = idata;
1153                            sh_update_interrupt_priorities(cpu);
1154                    }
1155                  break;                  break;
1156    
1157          case SH4_IPRB:          case SH4_IPRB:
1158                  if (writeflag == MEM_READ)                  if (writeflag == MEM_READ)
1159                          odata = cpu->cd.sh.intc_iprb;                          odata = cpu->cd.sh.intc_iprb;
1160                  else                  else {
1161                          cpu->cd.sh.intc_iprb = idata;                          cpu->cd.sh.intc_iprb = idata;
1162                            sh_update_interrupt_priorities(cpu);
1163                    }
1164                  break;                  break;
1165    
1166          case SH4_IPRC:          case SH4_IPRC:
1167                  if (writeflag == MEM_READ)                  if (writeflag == MEM_READ)
1168                          odata = cpu->cd.sh.intc_iprc;                          odata = cpu->cd.sh.intc_iprc;
1169                  else                  else {
1170                          cpu->cd.sh.intc_iprc = idata;                          cpu->cd.sh.intc_iprc = idata;
1171                            sh_update_interrupt_priorities(cpu);
1172                    }
1173                  break;                  break;
1174    
1175          case SH4_IPRD:          case SH4_IPRD:
1176                  if (writeflag == MEM_READ)                  if (writeflag == MEM_READ)
1177                          odata = cpu->cd.sh.intc_iprd;                          odata = cpu->cd.sh.intc_iprd;
1178                  else                  else {
1179                          cpu->cd.sh.intc_iprd = idata;                          cpu->cd.sh.intc_iprd = idata;
1180                            sh_update_interrupt_priorities(cpu);
1181                    }
1182                    break;
1183    
1184            case SH4_INTPRI00:
1185                    if (writeflag == MEM_READ)
1186                            odata = cpu->cd.sh.intc_intpri00;
1187                    else {
1188                            cpu->cd.sh.intc_intpri00 = idata;
1189                            sh_update_interrupt_priorities(cpu);
1190                    }
1191                    break;
1192    
1193            case SH4_INTPRI00 + 4:
1194                    if (writeflag == MEM_READ)
1195                            odata = cpu->cd.sh.intc_intpri04;
1196                    else {
1197                            cpu->cd.sh.intc_intpri04 = idata;
1198                            sh_update_interrupt_priorities(cpu);
1199                    }
1200                    break;
1201    
1202            case SH4_INTPRI00 + 8:
1203                    if (writeflag == MEM_READ)
1204                            odata = cpu->cd.sh.intc_intpri08;
1205                    else {
1206                            cpu->cd.sh.intc_intpri08 = idata;
1207                            sh_update_interrupt_priorities(cpu);
1208                    }
1209                    break;
1210    
1211            case SH4_INTPRI00 + 0xc:
1212                    if (writeflag == MEM_READ)
1213                            odata = cpu->cd.sh.intc_intpri0c;
1214                    else {
1215                            cpu->cd.sh.intc_intpri0c = idata;
1216                            sh_update_interrupt_priorities(cpu);
1217                    }
1218                    break;
1219    
1220            case SH4_INTMSK00:
1221                    /*  Note: Writes can only set bits, not clear them.  */
1222                    if (writeflag == MEM_READ)
1223                            odata = cpu->cd.sh.intc_intmsk00;
1224                    else
1225                            cpu->cd.sh.intc_intmsk00 |= idata;
1226                    break;
1227    
1228            case SH4_INTMSK00 + 4:
1229                    /*  Note: Writes can only set bits, not clear them.  */
1230                    if (writeflag == MEM_READ)
1231                            odata = cpu->cd.sh.intc_intmsk04;
1232                    else
1233                            cpu->cd.sh.intc_intmsk04 |= idata;
1234                    break;
1235    
1236            case SH4_INTMSKCLR00:
1237                    /*  Note: Writes can only clear bits, not set them.  */
1238                    if (writeflag == MEM_WRITE)
1239                            cpu->cd.sh.intc_intmsk00 &= ~idata;
1240                    break;
1241    
1242            case SH4_INTMSKCLR00 + 4:
1243                    /*  Note: Writes can only clear bits, not set them.  */
1244                    if (writeflag == MEM_WRITE)
1245                            cpu->cd.sh.intc_intmsk04 &= ~idata;
1246                  break;                  break;
1247    
1248    
# Line 1019  DEVICE_ACCESS(sh4) Line 1276  DEVICE_ACCESS(sh4)
1276    
1277          case SH4_SCIF_BASE + SCIF_FTDR:          case SH4_SCIF_BASE + SCIF_FTDR:
1278                  if (writeflag == MEM_WRITE) {                  if (writeflag == MEM_WRITE) {
1279                          console_putchar(d->scif_console_handle, idata);                          /*  Add to TX fifo:  */
1280                          d->scif_delayed_tx = 1;                          if (d->scif_tx_fifo_cursize >= sizeof(
1281                                d->scif_tx_fifo)) {
1282                                    fatal("[ SCIF TX fifo overrun! ]\n");
1283                                    d->scif_tx_fifo_cursize = 0;
1284                            }
1285    
1286                            d->scif_tx_fifo[d->scif_tx_fifo_cursize++] = idata;
1287                            d->scif_delayed_tx = 2;
1288                  }                  }
1289                  break;                  break;
1290    
# Line 1028  DEVICE_ACCESS(sh4) Line 1292  DEVICE_ACCESS(sh4)
1292                  if (writeflag == MEM_READ) {                  if (writeflag == MEM_READ) {
1293                          odata = d->scif_ssr;                          odata = d->scif_ssr;
1294                  } else {                  } else {
1295                          d->scif_ssr &= ~idata;                          d->scif_ssr = idata;
1296                          scif_reassert_interrupts(d);                          scif_reassert_interrupts(d);
1297                  }                  }
1298                  break;                  break;
# Line 1039  DEVICE_ACCESS(sh4) Line 1303  DEVICE_ACCESS(sh4)
1303                          if (x == 13)                          if (x == 13)
1304                                  x = 10;                                  x = 10;
1305                          odata = x < 0? 0 : x;                          odata = x < 0? 0 : x;
1306                          d->scif_ssr &= ~SCSSR2_DR;                          if (console_charavail(d->scif_console_handle))
1307                                    d->scif_ssr |= SCSSR2_DR;
1308                            else
1309                                    d->scif_ssr &= ~SCSSR2_DR;
1310                            scif_reassert_interrupts(d);
1311                  }                  }
1312                  break;                  break;
1313    
# Line 1051  DEVICE_ACCESS(sh4) Line 1319  DEVICE_ACCESS(sh4)
1319                  }                  }
1320                  break;                  break;
1321    
1322            case SH4_SCIF_BASE + SCIF_LSR:
1323                    /*  TODO: Implement all bits.  */
1324                    odata = 0;
1325                    break;
1326    
1327          case SH4_SCIF_BASE + SCIF_FDR:          case SH4_SCIF_BASE + SCIF_FDR:
1328                  odata = console_charavail(d->scif_console_handle);                  odata = (console_charavail(d->scif_console_handle)? 1 : 0)
1329                        + (d->scif_tx_fifo_cursize << 8);
1330                  break;                  break;
1331    
1332    
# Line 1200  DEVINIT(sh4) Line 1474  DEVINIT(sh4)
1474                  exit(1);                  exit(1);
1475          }          }
1476    
1477          /*  Bus State Controller initial values:  */          /*
1478             *  Bus State Controller initial values, according to the
1479             *  SH7760 manual:
1480             */
1481          d->bsc_bcr2 = 0x3ffc;          d->bsc_bcr2 = 0x3ffc;
1482          d->bsc_wcr1 = 0x77777777;          d->bsc_wcr1 = 0x77777777;
1483          d->bsc_wcr2 = 0xfffeefff;          d->bsc_wcr2 = 0xfffeefff;

Legend:
Removed from v.37  
changed lines
  Added in v.38

  ViewVC Help
Powered by ViewVC 1.1.26