/[gxemul]/trunk/src/cpus/cpu_arm_coproc.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/cpus/cpu_arm_coproc.c

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

revision 14 by dpavlin, Mon Oct 8 16:18:51 2007 UTC revision 26 by dpavlin, Mon Oct 8 16:20:10 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2005-2006  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_arm_coproc.c,v 1.10 2005/10/07 22:10:51 debug Exp $   *  $Id: cpu_arm_coproc.c,v 1.24 2006/06/24 21:47:23 debug Exp $
29   *   *
30   *  ARM coprocessor emulation.   *  ARM coprocessor emulation.
31   */   */
# Line 33  Line 33 
33  #include <stdio.h>  #include <stdio.h>
34  #include <stdlib.h>  #include <stdlib.h>
35  #include <string.h>  #include <string.h>
36    #include <unistd.h>
37  #include <ctype.h>  #include <ctype.h>
38    
39  #include "cpu.h"  #include "cpu.h"
40    #include "machine.h"
41  #include "misc.h"  #include "misc.h"
42  #include "symbol.h"  #include "symbol.h"
43    
44    #include "i80321reg.h"
45    
46    
47  /*  /*
48   *  arm_coproc_15():   *  arm_coproc_15():
# Line 62  void arm_coproc_15(struct cpu *cpu, int Line 66  void arm_coproc_15(struct cpu *cpu, int
66    
67          switch (crn) {          switch (crn) {
68    
69          case 0: /*  Main ID register:  */          case 0: /*
70                  if (opcode2 != 0)                   *  Main ID register (and Cache Type register, on XScale)
71                          fatal("[ arm_coproc_15: TODO: cr0, opcode2=%i ]\n",                   *
72                     *  Writes are supposed to be ignored, according to Intel docs.
73                     */
74                    switch (opcode2) {
75                    case 0: if (l_bit)
76                                    cpu->cd.arm.r[rd] = cpu->cd.arm.cpu_type.cpu_id;
77                            else
78                                    fatal("[ arm_coproc_15: attempt to write "
79                                        "to the Main ID register? ]\n");
80                            break;
81                    case 1: if (l_bit)
82                                    cpu->cd.arm.r[rd] = cpu->cd.arm.cachetype;
83                            else
84                                    fatal("[ arm_coproc_15: attempt to write "
85                                        "to the Cache Type register? ]\n");
86                            break;
87                    default:fatal("[ arm_coproc_15: TODO: cr0, opcode2=%i ]\n",
88                              opcode2);                              opcode2);
89                  if (l_bit)                          exit(1);
90                          cpu->cd.arm.r[rd] = cpu->cd.arm.cpu_type.cpu_id;                  }
                 else  
                         fatal("[ arm_coproc_15: attempt to write to cr0? ]\n");  
91                  break;                  break;
92    
93          case 1: /*  Control Register:  */          case 1: /*  Control Register:  */
94                  if (l_bit) {                  if (l_bit) {
95                          cpu->cd.arm.r[rd] = cpu->cd.arm.control;                          /*  Load from the normal/aux control register:  */
96                            switch (opcode2) {
97                            case 0: cpu->cd.arm.r[rd] = cpu->cd.arm.control;
98                                    break;
99                            case 1: cpu->cd.arm.r[rd] = cpu->cd.arm.auxctrl;
100                                    break;
101                            default:fatal("Unimplemented opcode2 = %i\n", opcode2);
102                                    fatal("(opcode1=%i crn=%i crm=%i rd=%i l=%i)\n",
103                                        opcode1, crn, crm, rd, l_bit);
104                                    exit(1);
105                            }
106                          return;                          return;
107                  }                  }
108    
109                    if (opcode2 == 1) {
110                            /*  Write to auxctrl:  */
111                            old_control = cpu->cd.arm.auxctrl;
112                            cpu->cd.arm.auxctrl = cpu->cd.arm.r[rd];
113                            if ((old_control & ARM_AUXCTRL_MD) !=
114                                (cpu->cd.arm.auxctrl & ARM_AUXCTRL_MD)) {
115                                    debug("[ setting the minidata cache attribute"
116                                        " to 0x%x ]\n", (cpu->cd.arm.auxctrl &
117                                        ARM_AUXCTRL_MD) >> ARM_AUXCTRL_MD_SHIFT);
118                            }
119                            if ((old_control & ARM_AUXCTRL_K) !=
120                                (cpu->cd.arm.auxctrl & ARM_AUXCTRL_K)) {
121                                    debug("[ %s write buffer coalescing ]\n",
122                                        cpu->cd.arm.auxctrl & ARM_AUXCTRL_K?
123                                        "Disabling" : "Enabling");
124                            }
125                            return;
126                    } else if (opcode2 != 0) {
127                            fatal("Unimplemented write, opcode2 = %i\n", opcode2);
128                            fatal("(opcode1=%i crn=%i crm=%i rd=%i l=%i)\n",
129                                opcode1, crn, crm, rd, l_bit);
130                            exit(1);
131                    }
132                            
133                  /*                  /*
134                   *  Write to control:  Check each bit individually:                   *  Write to control:  Check each bit individually:
135                   */                   */
136                  old_control = cpu->cd.arm.control;                  old_control = cpu->cd.arm.control;
137                  cpu->cd.arm.control = cpu->cd.arm.r[rd];                  cpu->cd.arm.control = cpu->cd.arm.r[rd];
138                  if ((old_control & ARM_CONTROL_MMU) !=                  if ((old_control & ARM_CONTROL_MMU) !=
139                      (cpu->cd.arm.control & ARM_CONTROL_MMU))                      (cpu->cd.arm.control & ARM_CONTROL_MMU)) {
140                          debug("[ %s the MMU ]\n", cpu->cd.arm.control &                          debug("[ %s the MMU ]\n", cpu->cd.arm.control &
141                              ARM_CONTROL_MMU? "enabling" : "disabling");                              ARM_CONTROL_MMU? "enabling" : "disabling");
142                            cpu->translate_v2p =
143                                cpu->cd.arm.control & ARM_CONTROL_MMU?
144                                arm_translate_v2p_mmu : arm_translate_v2p;
145                    }
146                  if ((old_control & ARM_CONTROL_ALIGN) !=                  if ((old_control & ARM_CONTROL_ALIGN) !=
147                      (cpu->cd.arm.control & ARM_CONTROL_ALIGN))                      (cpu->cd.arm.control & ARM_CONTROL_ALIGN))
148                          debug("[ %s alignment checks ]\n", cpu->cd.arm.control &                          debug("[ %s alignment checks ]\n", cpu->cd.arm.control &
# Line 163  void arm_coproc_15(struct cpu *cpu, int Line 220  void arm_coproc_15(struct cpu *cpu, int
220                  /*  fatal("[ arm_coproc_15: TLB: op2=%i crm=%i rd=0x%08x ]\n",                  /*  fatal("[ arm_coproc_15: TLB: op2=%i crm=%i rd=0x%08x ]\n",
221                      opcode2, crm, cpu->cd.arm.r[rd]);  */                      opcode2, crm, cpu->cd.arm.r[rd]);  */
222                  if (opcode2 == 0)                  if (opcode2 == 0)
223                          cpu->invalidate_translation_caches_paddr(cpu, 0,                          cpu->invalidate_translation_caches(cpu, 0,
224                              INVALIDATE_ALL);                              INVALIDATE_ALL);
225                  else                  else
226                          cpu->invalidate_translation_caches_paddr(cpu,                          cpu->invalidate_translation_caches(cpu,
227                              cpu->cd.arm.r[rd], INVALIDATE_VADDR);                              cpu->cd.arm.r[rd], INVALIDATE_VADDR);
228                  break;                  break;
229    
230            case 9: /*  Cache lockdown:  */
231                    fatal("[ arm_coproc_15: cache lockdown: TODO ]\n");
232                    /*  TODO  */
233                    break;
234    
235          case 13:/*  Process ID Register:  */          case 13:/*  Process ID Register:  */
236                  if (opcode2 != 0)                  if (opcode2 != 0)
237                          fatal("[ arm_coproc_15: PID access, but opcode2 "                          fatal("[ arm_coproc_15: PID access, but opcode2 "
# Line 188  void arm_coproc_15(struct cpu *cpu, int Line 250  void arm_coproc_15(struct cpu *cpu, int
250                  }                  }
251                  break;                  break;
252    
253          case 15:/*  IMPLEMENTATION DEPENDANT!  */          /*  case 14:  */
254                  fatal("[ arm_coproc_15: TODO: IMPLEMENTATION DEPENDANT! ]\n");                  /*  Breakpoint registers on XScale (possibly others?)  */
255                    /*  TODO  */
256                    /*  break;  */
257    
258            case 15:/*  IMPLEMENTATION DEPENDENT!  */
259                    switch (crm) {
260                    case 1: /*
261                             *  On XScale (and others? TODO), this is the
262                             *  CoProcessor Access Register.  Note/TODO: This isn't
263                             *  really used throughout the rest of the code yet.
264                             */
265                            if (l_bit)
266                                    cpu->cd.arm.r[rd] = cpu->cd.arm.cpar;
267                            else
268                                    cpu->cd.arm.cpar = cpu->cd.arm.r[rd];
269                            break;
270                    default:fatal("[ arm_coproc_15: TODO: IMPLEMENTATION "
271                                "DEPENDENT! ]\n");
272                            exit(1);
273                    }
274                  break;                  break;
275    
276          default:fatal("arm_coproc_15: unimplemented crn = %i\n", crn);          default:fatal("arm_coproc_15: unimplemented crn = %i\n", crn);
# Line 200  void arm_coproc_15(struct cpu *cpu, int Line 281  void arm_coproc_15(struct cpu *cpu, int
281  }  }
282    
283    
 /*****************************************************************************/  
   
   
284  /*  /*
285   *  arm_coproc_i80321():   *  arm_coproc_i80321_6():
286   *   *
287   *  Intel 80321 coprocessor.   *  Intel 80321 coprocessor 6.
288   */   */
289  void arm_coproc_i80321(struct cpu *cpu, int opcode1, int opcode2, int l_bit,  void arm_coproc_i80321_6(struct cpu *cpu, int opcode1, int opcode2, int l_bit,
290          int crn, int crm, int rd)          int crn, int crm, int rd)
291  {  {
292          switch (crm) {          switch (crm) {
293          case 0: fatal("[ 80321: crm 0: TODO ]\n");  
294            case 0: switch (crn) {
295                    case 0: if (l_bit) {
296                                    cpu->cd.arm.r[rd] = cpu->cd.arm.i80321_inten;
297                                    fatal("TODO: XScale read from inten?\n");
298                                    exit(1);
299                            } else
300                                    cpu->cd.arm.i80321_inten = cpu->cd.arm.r[rd];
301                            break;
302                    case 4: if (l_bit)
303                                    cpu->cd.arm.r[rd] = cpu->cd.arm.i80321_isteer;
304                            else {
305                                    cpu->cd.arm.i80321_isteer = cpu->cd.arm.r[rd];
306                                    if (cpu->cd.arm.r[rd] != 0) {
307                                            fatal("ARM xscale interrupt steering"
308                                                " is not yet implemented\n");
309                                            exit(1);
310                                    }
311                            }
312                            break;
313                    case 8: if (l_bit)
314                                    cpu->cd.arm.r[rd] = cpu->cd.arm.i80321_isrc;
315                            else {
316                                    cpu->cd.arm.i80321_isrc = cpu->cd.arm.r[rd];
317                                    fatal("TODO: XScale int ack?\n");
318                                    exit(1);
319                            }
320                            break;
321                    default:goto unknown;
322                    }
323                  break;                  break;
324          case 1: fatal("[ 80321: crm 1: TODO ]\n");  
325            case 1: /*  fatal("TIMER opcode1=%i opcode2=%i crn="
326        "%i crm=%i rd=%i l=%i)\n", opcode1, opcode2, crn, crm, rd, l_bit);  */
327    
328                  switch (crn) {                  switch (crn) {
329                  case 0: /*  tmr0:  */                  case 0: /*  tmr0:  */
330                            if (l_bit)
331                                    cpu->cd.arm.r[rd] = cpu->cd.arm.tmr0;
332                            else
333                                    cpu->cd.arm.tmr0 = cpu->cd.arm.r[rd];
334                            break;
335                    case 1: /*  tmr1:  */
336                            if (l_bit)
337                                    cpu->cd.arm.r[rd] = cpu->cd.arm.tmr1;
338                            else
339                                    cpu->cd.arm.tmr1 = cpu->cd.arm.r[rd];
340                          break;                          break;
341                  case 2: /*  tcr0:  */                  case 2: /*  tcr0:  */
342                            if (l_bit) {
343                                    /*  NOTE/TODO: Ugly hack: timer increment  */
344                                    cpu->cd.arm.tcr0 ++;
345                                    cpu->cd.arm.r[rd] = cpu->cd.arm.tcr0;
346                            } else {
347                                    cpu->cd.arm.tcr0 = cpu->cd.arm.r[rd];
348                            }
349                            break;
350                    case 3: /*  tcr1:  */
351                            if (l_bit) {
352                                    /*  NOTE/TODO: Ugly hack: timer increment  */
353                                    cpu->cd.arm.tcr1 ++;
354                                    cpu->cd.arm.r[rd] = cpu->cd.arm.tcr1;
355                            } else {
356                                    cpu->cd.arm.tcr1 = cpu->cd.arm.r[rd];
357                            }
358                          break;                          break;
359                  case 4: /*  trr0:  */                  case 4: /*  trr0:  */
360                            if (l_bit)
361                                    cpu->cd.arm.r[rd] = cpu->cd.arm.trr0;
362                            else
363                                    cpu->cd.arm.trr0 = cpu->cd.arm.r[rd];
364                            break;
365                    case 5: /*  trr1:  */
366                            if (l_bit)
367                                    cpu->cd.arm.r[rd] = cpu->cd.arm.trr1;
368                            else
369                                    cpu->cd.arm.trr1 = cpu->cd.arm.r[rd];
370                          break;                          break;
371                  case 6: /*  tisr:  */                  case 6: /*  tisr:  */
372                            if (l_bit)
373                                    cpu->cd.arm.r[rd] = cpu->cd.arm.tisr;
374                            else {
375                                    /*  Writing clears interrupts:  */
376                                    cpu->cd.arm.tisr &= ~cpu->cd.arm.r[rd];
377                                    if (!(cpu->cd.arm.tisr & TISR_TMR0))
378                                            cpu_interrupt_ack(cpu, 9);  /* TMR0 */
379                                    if (!(cpu->cd.arm.tisr & TISR_TMR1))
380                                            cpu_interrupt_ack(cpu, 10); /* TMR1 */
381                            }
382                          break;                          break;
383                  default:fatal("arm_coproc_i80321: unimplemented crn = %i\n",                  case 7: /*  wdtcr:  */
384                              crn);                          if (l_bit)
385                          fatal("(opcode1=%i opcode2=%i crm=%i rd=%i l=%i)\n",                                  cpu->cd.arm.r[rd] = cpu->cd.arm.wdtcr;
386                              opcode1, opcode2, crm, rd, l_bit);                          else
387                          exit(1);                                  cpu->cd.arm.wdtcr = cpu->cd.arm.r[rd];
388                            break;
389                    default:goto unknown;
390                  }                  }
391                  break;                  break;
392          default:fatal("arm_coproc_i80321: unimplemented opcode1=%i opcode2=%i"  
393                      " crn=%i crm=%i rd=%i l=%i)\n", opcode1, opcode2,          default:goto unknown;
                     crn, crm, rd, l_bit);  
                 exit(1);  
394          }          }
395    
396            return;
397    
398    unknown:
399            fatal("arm_coproc_i80321_6: unimplemented opcode1=%i opcode2=%i crn="
400                "%i crm=%i rd=%i l=%i)\n", opcode1, opcode2, crn, crm, rd, l_bit);
401            exit(1);
402  }  }
403    
404    
405  /*  /*
406   *  arm_coproc_i80321_14():   *  arm_coproc_xscale_14():
407   *   *
408   *  Intel 80321 coprocessor 14.   *  XScale coprocessor 14, Performance Monitoring Unit.
409   */   */
410  void arm_coproc_i80321_14(struct cpu *cpu, int opcode1, int opcode2, int l_bit,  void arm_coproc_xscale_14(struct cpu *cpu, int opcode1, int opcode2, int l_bit,
411          int crn, int crm, int rd)          int crn, int crm, int rd)
412  {  {
413            if (opcode2 != 0) {
414                    fatal("TODO: opcode2 = %i\n", opcode2);
415                    goto unknown;
416            }
417    
418          switch (crm) {          switch (crm) {
419          case 0: fatal("[ 80321_14: crm 0: TODO ]\n");  
420            case 0: switch (crn) {
421                    case 0: if (l_bit)
422                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc1_pmnc;
423                            else
424                                    cpu->cd.arm.xsc1_pmnc = cpu->cd.arm.r[rd];
425                            break;
426                    case 1: if (l_bit)
427                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc1_ccnt;
428                            else
429                                    cpu->cd.arm.xsc1_ccnt = cpu->cd.arm.r[rd];
430                            break;
431                    case 2: if (l_bit)
432                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc1_pmn0;
433                            else
434                                    cpu->cd.arm.xsc1_pmn0 = cpu->cd.arm.r[rd];
435                            break;
436                    case 3: if (l_bit)
437                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc1_pmn1;
438                            else
439                                    cpu->cd.arm.xsc1_pmn1 = cpu->cd.arm.r[rd];
440                            break;
441                    case 7: /*  UNIMPLEMENTED!!! TODO  */
442                            /*  Possibly some kind of idle or sleep function.  */
443                            break;
444                    default:goto unknown;
445                    }
446                  break;                  break;
447          default:fatal("arm_coproc_i80321_14: unimplemented opcode1=%i opcode2="  
448                      "%i crn=%i crm=%i rd=%i l=%i)\n", opcode1, opcode2,          case 1: switch (crn) {
449                      crn, crm, rd, l_bit);                  case 0: if (l_bit)
450                  exit(1);                                  cpu->cd.arm.r[rd] = cpu->cd.arm.xsc2_pmnc;
451                            else
452                                    cpu->cd.arm.xsc2_pmnc = cpu->cd.arm.r[rd];
453                            break;
454                    case 1: if (l_bit)
455                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc2_ccnt;
456                            else
457                                    cpu->cd.arm.xsc2_ccnt = cpu->cd.arm.r[rd];
458                            break;
459                    case 4: if (l_bit)
460                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc2_inten;
461                            else
462                                    cpu->cd.arm.xsc2_inten = cpu->cd.arm.r[rd];
463                            break;
464                    case 5: if (l_bit)
465                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc2_flag;
466                            else
467                                    cpu->cd.arm.xsc2_flag = cpu->cd.arm.r[rd];
468                            break;
469                    case 8: if (l_bit)
470                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc2_evtsel;
471                            else
472                                    cpu->cd.arm.xsc2_evtsel = cpu->cd.arm.r[rd];
473                            break;
474                    default:goto unknown;
475                    }
476                    break;
477    
478            case 2: switch (crn) {
479                    case 0: if (l_bit)
480                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc2_pmn0;
481                            else
482                                    cpu->cd.arm.xsc2_pmn0 = cpu->cd.arm.r[rd];
483                            break;
484                    case 1: if (l_bit)
485                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc2_pmn1;
486                            else
487                                    cpu->cd.arm.xsc2_pmn1 = cpu->cd.arm.r[rd];
488                            break;
489                    case 2: if (l_bit)
490                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc2_pmn2;
491                            else
492                                    cpu->cd.arm.xsc2_pmn2 = cpu->cd.arm.r[rd];
493                            break;
494                    case 3: if (l_bit)
495                                    cpu->cd.arm.r[rd] = cpu->cd.arm.xsc2_pmn3;
496                            else
497                                    cpu->cd.arm.xsc2_pmn3 = cpu->cd.arm.r[rd];
498                            break;
499                    default:goto unknown;
500                    }
501                    break;
502    
503            default:goto unknown;
504          }          }
505    
506            return;
507    
508    unknown:
509            fatal("arm_coproc_xscale_14: unimplemented opcode1=%i opcode2="
510                "%i crn=%i crm=%i rd=%i l=%i)\n", opcode1, opcode2, crn,
511                crm, rd, l_bit);
512            exit(1);
513  }  }
514    

Legend:
Removed from v.14  
changed lines
  Added in v.26

  ViewVC Help
Powered by ViewVC 1.1.26