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

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

revision 29 by dpavlin, Mon Oct 8 16:20:26 2007 UTC revision 30 by dpavlin, Mon Oct 8 16:20:40 2007 UTC
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: cpu_transputer_instr.c,v 1.2 2006/07/21 05:46:45 debug Exp $   *  $Id: cpu_transputer_instr.c,v 1.6 2006/07/23 19:36:14 debug Exp $
29   *   *
30   *  INMOS transputer instructions.   *  INMOS transputer instructions.
31   *   *
# Line 34  Line 34 
34   *  call. If no instruction was executed, then it should be decreased. If, say,   *  call. If no instruction was executed, then it should be decreased. If, say,
35   *  4 instructions were combined into one function and executed, then it should   *  4 instructions were combined into one function and executed, then it should
36   *  be increased by 3.)   *  be increased by 3.)
37     *
38     *  NOTE: The PC does not need to be synched before e.g. memory_rw(), because
39     *        there is no MMU in the Transputer, and hence there can not be any
40     *        exceptions on memory accesses.
41   */   */
42    
43    
 /*  
  *  nop:  Do nothing.  
  */  
 X(nop)  
 {  
 }  
   
   
44  /*****************************************************************************/  /*****************************************************************************/
45    
46    
47  /*  /*
48   *  j:  Relative jump   *  j:  Relative jump
  *  
  *  arg[0] = relative distance from the _current_ instruction.  
49   */   */
50  X(j)  X(j)
51  {  {
# Line 59  X(j) Line 53  X(j)
53          int low_pc = ((size_t)ic - (size_t)cpu->cd.transputer.cur_ic_page)          int low_pc = ((size_t)ic - (size_t)cpu->cd.transputer.cur_ic_page)
54              / sizeof(struct transputer_instr_call);              / sizeof(struct transputer_instr_call);
55          cpu->pc &= ~(TRANSPUTER_IC_ENTRIES_PER_PAGE-1);          cpu->pc &= ~(TRANSPUTER_IC_ENTRIES_PER_PAGE-1);
56          cpu->pc += low_pc + ic->arg[0];          cpu->pc += low_pc + ic->arg[0] + 1 + cpu->cd.transputer.oreg;
57            cpu->cd.transputer.oreg = 0;
58          quick_pc_to_pointers(cpu);          quick_pc_to_pointers(cpu);
59  }  }
60    
61    
62  /*  /*
63   *  ldc: Load constant   *  ldlp: Load local pointer
64     */
65    X(ldlp)
66    {
67            cpu->cd.transputer.c = cpu->cd.transputer.b;
68            cpu->cd.transputer.b = cpu->cd.transputer.a;
69            cpu->cd.transputer.oreg |= ic->arg[0];
70            cpu->cd.transputer.a = cpu->cd.transputer.oreg * sizeof(uint32_t) +
71                cpu->cd.transputer.wptr;
72            cpu->cd.transputer.oreg = 0;
73    }
74    
75    
76    /*
77     *  pfix: Prefix
78   *   *
79   *  arg[0] = constant   *  arg[0] = nibble
80     */
81    X(pfix)
82    {
83            cpu->cd.transputer.oreg |= ic->arg[0];
84            cpu->cd.transputer.oreg <<= 4;
85    }
86    
87    
88    /*
89     *  ldnl: Load non-local
90     */
91    X(ldnl)
92    {
93            uint32_t addr, w32;
94            uint8_t word[sizeof(uint32_t)];
95            unsigned char *page;
96    
97            cpu->cd.transputer.oreg |= ic->arg[0];
98            addr = cpu->cd.transputer.oreg * sizeof(uint32_t) +
99                cpu->cd.transputer.a;
100    
101            page = cpu->cd.transputer.host_load[TRANSPUTER_ADDR_TO_PAGENR(addr)];
102            if (page == NULL) {
103                    cpu->memory_rw(cpu, cpu->mem, addr, word, sizeof(word),
104                        MEM_READ, CACHE_DATA);
105                    w32 = *(uint32_t *) &word[0];
106            } else {
107                    w32 = *(uint32_t *) &page[TRANSPUTER_PC_TO_IC_ENTRY(addr)];
108            }
109    
110            cpu->cd.transputer.a = LE32_TO_HOST(w32);
111            cpu->cd.transputer.oreg = 0;
112    }
113    
114    
115    /*
116     *  ldc: Load constant
117   */   */
118  X(ldc)  X(ldc)
119  {  {
         /*  TODO: Is oreg really cleared like this?  */  
         cpu->cd.transputer.oreg = ic->arg[0];  
120          cpu->cd.transputer.c = cpu->cd.transputer.b;          cpu->cd.transputer.c = cpu->cd.transputer.b;
121          cpu->cd.transputer.b = cpu->cd.transputer.a;          cpu->cd.transputer.b = cpu->cd.transputer.a;
122          cpu->cd.transputer.a = ic->arg[0];          cpu->cd.transputer.a = cpu->cd.transputer.oreg | ic->arg[0];
123            cpu->cd.transputer.oreg = 0;
124    }
125    
126    
127    /*
128     *  ldnlp: Load non-local pointer
129     */
130    X(ldnlp)
131    {
132            cpu->cd.transputer.a += (cpu->cd.transputer.oreg | ic->arg[0])
133                * sizeof(uint32_t);
134            cpu->cd.transputer.oreg = 0;
135    }
136    
137    
138    /*
139     *  nfix: Negative prefix
140     */
141    X(nfix)
142    {
143            cpu->cd.transputer.oreg |= ic->arg[0];
144            cpu->cd.transputer.oreg = (~cpu->cd.transputer.oreg) << 4;
145    }
146    
147    
148    /*
149     *  ldl: Load local
150     */
151    X(ldl)
152    {
153            uint32_t addr;
154            uint8_t word[sizeof(uint32_t)];
155            uint32_t w32;
156            unsigned char *page;
157    
158            cpu->cd.transputer.c = cpu->cd.transputer.b;
159            cpu->cd.transputer.b = cpu->cd.transputer.a;
160            cpu->cd.transputer.oreg |= ic->arg[0];
161            addr = cpu->cd.transputer.oreg * sizeof(uint32_t) +
162                cpu->cd.transputer.wptr;
163    
164            page = cpu->cd.transputer.host_load[TRANSPUTER_ADDR_TO_PAGENR(addr)];
165            if (page == NULL) {
166                    cpu->memory_rw(cpu, cpu->mem, addr, word, sizeof(word),
167                        MEM_READ, CACHE_DATA);
168                    w32 = *(uint32_t *) &word[0];
169    printf("A w32 = %08"PRIx32"\n", w32);
170            } else {
171                    w32 = *(uint32_t *) &page[TRANSPUTER_PC_TO_IC_ENTRY(addr)];
172    printf("B w32 = %08"PRIx32"\n", w32);
173            }
174    
175            cpu->cd.transputer.a = LE32_TO_HOST(w32);
176            cpu->cd.transputer.oreg = 0;
177    }
178    
179    
180    /*
181     *  ajw: Adjust workspace
182     */
183    X(ajw)
184    {
185            cpu->cd.transputer.oreg |= ic->arg[0];
186            cpu->cd.transputer.wptr += (cpu->cd.transputer.oreg * sizeof(uint32_t));
187            cpu->cd.transputer.oreg = 0;
188    }
189    
190    
191    /*
192     *  eqc: Equal to constant
193     */
194    X(eqc)
195    {
196            cpu->cd.transputer.a = (cpu->cd.transputer.a ==
197                (cpu->cd.transputer.oreg | ic->arg[0]));
198            cpu->cd.transputer.oreg = 0;
199    }
200    
201    
202    /*
203     *  stl: Store local
204     */
205    X(stl)
206    {
207            uint32_t addr, w32;
208            unsigned char *page;
209    
210            w32 = LE32_TO_HOST(cpu->cd.transputer.a);
211            cpu->cd.transputer.oreg |= ic->arg[0];
212            addr = cpu->cd.transputer.oreg * sizeof(uint32_t) +
213                cpu->cd.transputer.wptr;
214    
215            page = cpu->cd.transputer.host_store[TRANSPUTER_ADDR_TO_PAGENR(addr)];
216            if (page == NULL) {
217                    cpu->memory_rw(cpu, cpu->mem, addr, (void *)&w32, sizeof(w32),
218                        MEM_WRITE, CACHE_DATA);
219            } else {
220                    *((uint32_t *) &page[TRANSPUTER_PC_TO_IC_ENTRY(addr)]) = w32;
221            }
222    
223            cpu->cd.transputer.a = cpu->cd.transputer.b;
224            cpu->cd.transputer.b = cpu->cd.transputer.c;
225            cpu->cd.transputer.oreg = 0;
226    }
227    
228    
229    /*
230     *  stnl: Store non-local
231     */
232    X(stnl)
233    {
234            uint32_t addr, w32;
235            unsigned char *page;
236    
237            w32 = LE32_TO_HOST(cpu->cd.transputer.b);
238            cpu->cd.transputer.oreg |= ic->arg[0];
239            addr = cpu->cd.transputer.oreg * sizeof(uint32_t) +
240                cpu->cd.transputer.a;
241    
242            page = cpu->cd.transputer.host_store[TRANSPUTER_ADDR_TO_PAGENR(addr)];
243            if (page == NULL) {
244                    cpu->memory_rw(cpu, cpu->mem, addr, (void *)&w32, sizeof(w32),
245                        MEM_WRITE, CACHE_DATA);
246            } else {
247                    *((uint32_t *) &page[TRANSPUTER_PC_TO_IC_ENTRY(addr)]) = w32;
248            }
249    
250            cpu->cd.transputer.a = cpu->cd.transputer.c;
251            cpu->cd.transputer.oreg = 0;
252    }
253    
254    
255    /*
256     *  opr: Operate
257     *
258     *  TODO/NOTE: This doesn't work too well with the way dyntrans is designed
259     *             to work. Maybe it should be rewritten some day. But how?
260     *             Right now it works almost 100% like an old-style interpretation
261     *             function.
262     */
263    X(opr)
264    {
265            cpu->cd.transputer.oreg |= ic->arg[0];
266    
267            switch (cpu->cd.transputer.oreg) {
268    
269            case T_OPC_F_REV:
270                    {
271                            uint32_t tmp = cpu->cd.transputer.b;
272                            cpu->cd.transputer.b = cpu->cd.transputer.a;
273                            cpu->cd.transputer.a = tmp;
274                    }
275                    break;
276    
277            case T_OPC_F_ADD:
278                    {
279                            uint32_t old_a = cpu->cd.transputer.a;
280                            cpu->cd.transputer.a = cpu->cd.transputer.b + old_a;
281                            if ((cpu->cd.transputer.a & 0x80000000) !=
282                                (cpu->cd.transputer.b & old_a & 0x80000000))
283                                    cpu->cd.transputer.error = 1;
284                            cpu->cd.transputer.b = cpu->cd.transputer.c;
285                    }
286                    break;
287    
288            case T_OPC_F_SUB:
289                    {
290                            uint32_t old_a = cpu->cd.transputer.a;
291                            cpu->cd.transputer.a = cpu->cd.transputer.b - old_a;
292                            if ((cpu->cd.transputer.a & 0x80000000) !=
293                                (cpu->cd.transputer.b & old_a & 0x80000000))
294                                    cpu->cd.transputer.error = 1;
295                            cpu->cd.transputer.b = cpu->cd.transputer.c;
296                    }
297                    break;
298    
299            case T_OPC_F_LDPI:
300                    /*  Load pointer to (next) instruction  */
301                    {
302                            int low_pc = ((size_t)ic -
303                                (size_t)cpu->cd.transputer.cur_ic_page)
304                                / sizeof(struct transputer_instr_call);
305                            cpu->pc &= ~(TRANSPUTER_IC_ENTRIES_PER_PAGE-1);
306                            cpu->pc += low_pc;
307                            cpu->cd.transputer.a += cpu->pc + 1;
308                    }
309                    break;
310    
311            case T_OPC_F_STHF:
312                    cpu->cd.transputer.fptrreg0 = cpu->cd.transputer.a;
313                    cpu->cd.transputer.a = cpu->cd.transputer.b;
314                    cpu->cd.transputer.b = cpu->cd.transputer.c;
315                    break;
316    
317            case T_OPC_F_STLF:
318                    cpu->cd.transputer.fptrreg1 = cpu->cd.transputer.a;
319                    cpu->cd.transputer.a = cpu->cd.transputer.b;
320                    cpu->cd.transputer.b = cpu->cd.transputer.c;
321                    break;
322    
323            case T_OPC_F_BCNT:
324                    cpu->cd.transputer.a <<= 2;
325                    break;
326    
327            case T_OPC_F_GAJW:
328                    {
329                            uint32_t old_wptr = cpu->cd.transputer.wptr;
330                            cpu->cd.transputer.wptr = cpu->cd.transputer.a & ~3;
331                            cpu->cd.transputer.a = old_wptr;
332                    }
333                    break;
334    
335            case T_OPC_F_WCNT:
336                    cpu->cd.transputer.c = cpu->cd.transputer.b;
337                    cpu->cd.transputer.b = cpu->cd.transputer.a & 3;
338                    cpu->cd.transputer.a >>= 2;
339                    break;
340    
341            case T_OPC_F_MINT:
342                    cpu->cd.transputer.c = cpu->cd.transputer.b;
343                    cpu->cd.transputer.b = cpu->cd.transputer.a;
344                    cpu->cd.transputer.a = 0x80000000;
345                    break;
346    
347            case T_OPC_F_MOVE:
348                    /*  TODO: This can be optimized a lot by using the host's
349                        memmove(). The only important thing to consider is
350                        if src or dst crosses a host memblock boundary.  */
351                    {
352                            uint32_t i, src = cpu->cd.transputer.c,
353                                dst = cpu->cd.transputer.b;
354                            uint8_t byte;
355                            for (i=1; i<=cpu->cd.transputer.a; i++) {
356                                    cpu->memory_rw(cpu, cpu->mem, src ++, &byte,
357                                        1, MEM_READ, CACHE_DATA);
358                                    cpu->memory_rw(cpu, cpu->mem, dst ++, &byte,
359                                        1, MEM_WRITE, CACHE_DATA);
360                            }
361                    }
362                    break;
363    
364            default:fatal("UNIMPLEMENTED opr oreg 0x%"PRIx32"\n",
365                        cpu->cd.transputer.oreg);
366                    exit(1);
367            }
368    
369            cpu->cd.transputer.oreg = 0;
370  }  }
371    
372    
# Line 157  X(to_be_translated) Line 448  X(to_be_translated)
448    
449          switch (ib[0] >> 4) {          switch (ib[0] >> 4) {
450    
451          case 0: /*  j, relative jump  */          case T_OPC_J:
452                    /*  relative jump  */
453                  ic->f = instr(j);                  ic->f = instr(j);
                 ic->arg[0] = (ib[0] & 0xf) + 1;  
454                  /*  TODO: Samepage jump!  */                  /*  TODO: Samepage jump!  */
455    
456                  if (cpu->cd.transputer.cpu_type.features & T_DEBUG                  if (cpu->cd.transputer.cpu_type.features & T_DEBUG
# Line 174  X(to_be_translated) Line 465  X(to_be_translated)
465                  }                  }
466                  break;                  break;
467    
468          case 4: /*  ldc, load constant  */          case T_OPC_LDLP:
469                    /*  load local pointer  */
470                    ic->f = instr(ldlp);
471                    break;
472    
473            case T_OPC_PFIX:
474                    /*  prefix  */
475                    ic->f = instr(pfix);
476                    break;
477    
478            case T_OPC_LDNL:
479                    /*  load non-local  */
480                    ic->f = instr(ldnl);
481                    break;
482    
483            case T_OPC_LDC:
484                    /*  load constant  */
485                  ic->f = instr(ldc);                  ic->f = instr(ldc);
486                  break;                  break;
487    
488            case T_OPC_LDNLP:
489                    /*  load non-local pointer  */
490                    ic->f = instr(ldnlp);
491                    break;
492    
493            case T_OPC_NFIX:
494                    /*  negative prefix  */
495                    ic->f = instr(nfix);
496                    break;
497    
498            case T_OPC_LDL:
499                    /*  load local  */
500                    ic->f = instr(ldl);
501                    break;
502    
503            case T_OPC_AJW:
504                    /*  adjust workspace  */
505                    ic->f = instr(ajw);
506                    break;
507    
508            case T_OPC_EQC:
509                    /*  equal to constant  */
510                    ic->f = instr(eqc);
511                    break;
512    
513            case T_OPC_STL:
514                    /*  store local  */
515                    ic->f = instr(stl);
516                    break;
517    
518            case T_OPC_STNL:
519                    /*  store non-local  */
520                    ic->f = instr(stnl);
521                    break;
522    
523            case T_OPC_OPR:
524                    /*  operate  */
525                    ic->f = instr(opr);
526                    break;
527    
528          default:fatal("UNIMPLEMENTED opcode 0x%02x\n", ib[0]);          default:fatal("UNIMPLEMENTED opcode 0x%02x\n", ib[0]);
529                  goto bad;                  goto bad;
530          }          }

Legend:
Removed from v.29  
changed lines
  Added in v.30

  ViewVC Help
Powered by ViewVC 1.1.26