OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [branches/] [stable_0_2_x/] [or1ksim/] [cpu/] [or32/] [dyn_rec.c] - Blame information for rev 1483

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1452 nogj
/* dyn_rec.c -- Dynamic recompiler implementation for or32
2
   Copyright (C) 2005 György `nog' Jeney, nog@sdf.lonestar.org
3
 
4
This file is part of OpenRISC 1000 Architectural Simulator.
5
 
6
This program is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2 of the License, or
9
(at your option) any later version.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
GNU General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
19
 
20
#include <stdio.h>
21
#include <stdlib.h>
22
#include <string.h>
23
#include <sys/mman.h>
24
#include <signal.h>
25
#include <errno.h>
26
#include <execinfo.h>
27
 
28
#include "config.h"
29
 
30
#ifdef HAVE_INTTYPES_H
31
#include <inttypes.h>
32
#endif
33
 
34
#include "port.h"
35
#include "arch.h"
36
#include "immu.h"
37
#include "abstract.h"
38
#include "opcode/or32.h"
39
#include "spr_defs.h"
40
#include "execute.h"
41
#include "except.h"
42
#include "spr_defs.h"
43
#include "sim-config.h"
44
#include "sched.h"
45
 
46
#include "rec_i386.h"
47
#include "i386_regs.h"
48
 
49
#include "dyn_rec.h"
50
#include "gen_ops.h"
51
 
52
#include "op_support.h"
53
 
54
/* NOTE: All openrisc (or) addresses in this file are *PHYSICAL* addresses */
55
 
56
/* FIXME: Optimise sorted list adding */
57
 
58
typedef void (*generic_gen_op)(struct op_queue *opq, int end);
59
typedef void (*imm_gen_op)(struct op_queue *opq, int end, uorreg_t imm);
60
 
61
void gen_l_invalid(struct op_queue *opq, int param_t[3], orreg_t param[3],
62
                   int delay_slot);
63
 
64
static const generic_gen_op gen_op_move_gpr_t[NUM_T_REGS][32] = {
65
 { NULL,
66
   gen_op_move_gpr1_t0,
67
   gen_op_move_gpr2_t0,
68
   gen_op_move_gpr3_t0,
69
   gen_op_move_gpr4_t0,
70
   gen_op_move_gpr5_t0,
71
   gen_op_move_gpr6_t0,
72
   gen_op_move_gpr7_t0,
73
   gen_op_move_gpr8_t0,
74
   gen_op_move_gpr9_t0,
75
   gen_op_move_gpr10_t0,
76
   gen_op_move_gpr11_t0,
77
   gen_op_move_gpr12_t0,
78
   gen_op_move_gpr13_t0,
79
   gen_op_move_gpr14_t0,
80
   gen_op_move_gpr15_t0,
81
   gen_op_move_gpr16_t0,
82
   gen_op_move_gpr17_t0,
83
   gen_op_move_gpr18_t0,
84
   gen_op_move_gpr19_t0,
85
   gen_op_move_gpr20_t0,
86
   gen_op_move_gpr21_t0,
87
   gen_op_move_gpr22_t0,
88
   gen_op_move_gpr23_t0,
89
   gen_op_move_gpr24_t0,
90
   gen_op_move_gpr25_t0,
91
   gen_op_move_gpr26_t0,
92
   gen_op_move_gpr27_t0,
93
   gen_op_move_gpr28_t0,
94
   gen_op_move_gpr29_t0,
95
   gen_op_move_gpr30_t0,
96
   gen_op_move_gpr31_t0 },
97
 { NULL,
98
   gen_op_move_gpr1_t1,
99
   gen_op_move_gpr2_t1,
100
   gen_op_move_gpr3_t1,
101
   gen_op_move_gpr4_t1,
102
   gen_op_move_gpr5_t1,
103
   gen_op_move_gpr6_t1,
104
   gen_op_move_gpr7_t1,
105
   gen_op_move_gpr8_t1,
106
   gen_op_move_gpr9_t1,
107
   gen_op_move_gpr10_t1,
108
   gen_op_move_gpr11_t1,
109
   gen_op_move_gpr12_t1,
110
   gen_op_move_gpr13_t1,
111
   gen_op_move_gpr14_t1,
112
   gen_op_move_gpr15_t1,
113
   gen_op_move_gpr16_t1,
114
   gen_op_move_gpr17_t1,
115
   gen_op_move_gpr18_t1,
116
   gen_op_move_gpr19_t1,
117
   gen_op_move_gpr20_t1,
118
   gen_op_move_gpr21_t1,
119
   gen_op_move_gpr22_t1,
120
   gen_op_move_gpr23_t1,
121
   gen_op_move_gpr24_t1,
122
   gen_op_move_gpr25_t1,
123
   gen_op_move_gpr26_t1,
124
   gen_op_move_gpr27_t1,
125
   gen_op_move_gpr28_t1,
126
   gen_op_move_gpr29_t1,
127
   gen_op_move_gpr30_t1,
128
   gen_op_move_gpr31_t1 },
129
 { NULL,
130
   gen_op_move_gpr1_t2,
131
   gen_op_move_gpr2_t2,
132
   gen_op_move_gpr3_t2,
133
   gen_op_move_gpr4_t2,
134
   gen_op_move_gpr5_t2,
135
   gen_op_move_gpr6_t2,
136
   gen_op_move_gpr7_t2,
137
   gen_op_move_gpr8_t2,
138
   gen_op_move_gpr9_t2,
139
   gen_op_move_gpr10_t2,
140
   gen_op_move_gpr11_t2,
141
   gen_op_move_gpr12_t2,
142
   gen_op_move_gpr13_t2,
143
   gen_op_move_gpr14_t2,
144
   gen_op_move_gpr15_t2,
145
   gen_op_move_gpr16_t2,
146
   gen_op_move_gpr17_t2,
147
   gen_op_move_gpr18_t2,
148
   gen_op_move_gpr19_t2,
149
   gen_op_move_gpr20_t2,
150
   gen_op_move_gpr21_t2,
151
   gen_op_move_gpr22_t2,
152
   gen_op_move_gpr23_t2,
153
   gen_op_move_gpr24_t2,
154
   gen_op_move_gpr25_t2,
155
   gen_op_move_gpr26_t2,
156
   gen_op_move_gpr27_t2,
157
   gen_op_move_gpr28_t2,
158
   gen_op_move_gpr29_t2,
159
   gen_op_move_gpr30_t2,
160
   gen_op_move_gpr31_t2 } };
161
 
162
static const generic_gen_op gen_op_move_t_gpr[NUM_T_REGS][32] = {
163
 { NULL,
164
   gen_op_move_t0_gpr1,
165
   gen_op_move_t0_gpr2,
166
   gen_op_move_t0_gpr3,
167
   gen_op_move_t0_gpr4,
168
   gen_op_move_t0_gpr5,
169
   gen_op_move_t0_gpr6,
170
   gen_op_move_t0_gpr7,
171
   gen_op_move_t0_gpr8,
172
   gen_op_move_t0_gpr9,
173
   gen_op_move_t0_gpr10,
174
   gen_op_move_t0_gpr11,
175
   gen_op_move_t0_gpr12,
176
   gen_op_move_t0_gpr13,
177
   gen_op_move_t0_gpr14,
178
   gen_op_move_t0_gpr15,
179
   gen_op_move_t0_gpr16,
180
   gen_op_move_t0_gpr17,
181
   gen_op_move_t0_gpr18,
182
   gen_op_move_t0_gpr19,
183
   gen_op_move_t0_gpr20,
184
   gen_op_move_t0_gpr21,
185
   gen_op_move_t0_gpr22,
186
   gen_op_move_t0_gpr23,
187
   gen_op_move_t0_gpr24,
188
   gen_op_move_t0_gpr25,
189
   gen_op_move_t0_gpr26,
190
   gen_op_move_t0_gpr27,
191
   gen_op_move_t0_gpr28,
192
   gen_op_move_t0_gpr29,
193
   gen_op_move_t0_gpr30,
194
   gen_op_move_t0_gpr31 },
195
 { NULL,
196
   gen_op_move_t1_gpr1,
197
   gen_op_move_t1_gpr2,
198
   gen_op_move_t1_gpr3,
199
   gen_op_move_t1_gpr4,
200
   gen_op_move_t1_gpr5,
201
   gen_op_move_t1_gpr6,
202
   gen_op_move_t1_gpr7,
203
   gen_op_move_t1_gpr8,
204
   gen_op_move_t1_gpr9,
205
   gen_op_move_t1_gpr10,
206
   gen_op_move_t1_gpr11,
207
   gen_op_move_t1_gpr12,
208
   gen_op_move_t1_gpr13,
209
   gen_op_move_t1_gpr14,
210
   gen_op_move_t1_gpr15,
211
   gen_op_move_t1_gpr16,
212
   gen_op_move_t1_gpr17,
213
   gen_op_move_t1_gpr18,
214
   gen_op_move_t1_gpr19,
215
   gen_op_move_t1_gpr20,
216
   gen_op_move_t1_gpr21,
217
   gen_op_move_t1_gpr22,
218
   gen_op_move_t1_gpr23,
219
   gen_op_move_t1_gpr24,
220
   gen_op_move_t1_gpr25,
221
   gen_op_move_t1_gpr26,
222
   gen_op_move_t1_gpr27,
223
   gen_op_move_t1_gpr28,
224
   gen_op_move_t1_gpr29,
225
   gen_op_move_t1_gpr30,
226
   gen_op_move_t1_gpr31 },
227
 { NULL,
228
   gen_op_move_t2_gpr1,
229
   gen_op_move_t2_gpr2,
230
   gen_op_move_t2_gpr3,
231
   gen_op_move_t2_gpr4,
232
   gen_op_move_t2_gpr5,
233
   gen_op_move_t2_gpr6,
234
   gen_op_move_t2_gpr7,
235
   gen_op_move_t2_gpr8,
236
   gen_op_move_t2_gpr9,
237
   gen_op_move_t2_gpr10,
238
   gen_op_move_t2_gpr11,
239
   gen_op_move_t2_gpr12,
240
   gen_op_move_t2_gpr13,
241
   gen_op_move_t2_gpr14,
242
   gen_op_move_t2_gpr15,
243
   gen_op_move_t2_gpr16,
244
   gen_op_move_t2_gpr17,
245
   gen_op_move_t2_gpr18,
246
   gen_op_move_t2_gpr19,
247
   gen_op_move_t2_gpr20,
248
   gen_op_move_t2_gpr21,
249
   gen_op_move_t2_gpr22,
250
   gen_op_move_t2_gpr23,
251
   gen_op_move_t2_gpr24,
252
   gen_op_move_t2_gpr25,
253
   gen_op_move_t2_gpr26,
254
   gen_op_move_t2_gpr27,
255
   gen_op_move_t2_gpr28,
256
   gen_op_move_t2_gpr29,
257
   gen_op_move_t2_gpr30,
258
   gen_op_move_t2_gpr31 } };
259
 
260
static const imm_gen_op calc_insn_ea_table[NUM_T_REGS] =
261
 { gen_op_calc_insn_ea_t0, gen_op_calc_insn_ea_t1, gen_op_calc_insn_ea_t2 };
262
 
263
/* Linker stubs.  This will allow the linker to link in op.o.  The relocations
264
 * that the linker does for these will be irrelevent anyway, since we patch the
265
 * relocations during recompilation. */
266
uorreg_t __op_param1;
267
uorreg_t __op_param2;
268
uorreg_t __op_param3;
269
 
270
/* The number of bytes that a dynamicly recompiled page should be enlarged by */
271
#define RECED_PAGE_ENLARGE_BY 51200
272
 
273
/* The number of entries that the micro operations array in op_queue should be
274
 * enlarged by */
275
#define OPS_ENLARGE_BY 5
276
 
277
#define T_NONE (-1)
278
 
279
void *rec_stack_base;
280
 
281
/* FIXME: Put this into some header */
282
extern int do_stats;
283
 
284
static int sigsegv_state = 0;
285
static void *sigsegv_addr = NULL;
286
 
287
void dyn_ret_stack_prot(void);
288
 
289
void dyn_sigsegv_debug(int u, siginfo_t *siginf, void *dat)
290
{
291
  struct dyn_page *dp;
292
  FILE *f;
293
  char filen[18]; /* 18 == strlen("or_page.%08x") + 1 */
294
  void *stack;
295
  int i, j;
296
  void *trace[10];
297
  int num_trace;
298
  char **trace_names;
299
 
300
  if(!sigsegv_state) {
301
    sigsegv_addr = siginf->si_addr;
302
  } else {
303
    printf("Nested SIGSEGV occured, dumping next chuck of info\n");
304
    sigsegv_state++;
305
  }
306
 
307
  /* First dump all the data that does not need dereferenceing to get */
308
  switch(sigsegv_state) {
309
  case 0:
310
    fflush(stdout);
311
    printf("Segmentation fault at %p (or address: 0x%"PRIxADDR")\n\n",
312
           sigsegv_addr, get_pc());
313
    sigsegv_state++;
314
  case 1:
315
    /* Run through the recompiled pages, dumping them to disk as we go */
316
    for(dp = cpu_state.dyn_pages; dp; dp = dp->next) {
317
      printf("Dumping%s page 0x%"PRIxADDR" recompiled to %p (len: %u) to disk\n",
318
             dp->dirty ? " dirty" : "", dp->or_page, dp->host_page,
319
             dp->host_len);
320
      fflush(stdout);
321
 
322
      sprintf(filen, "or_page.%"PRIxADDR, dp->or_page);
323
      if(!(f = fopen(filen, "w"))) {
324
        fprintf(stderr, "Unable to open %s to dump the recompiled page to: %s\n",
325
                filen, strerror(errno));
326
        continue;
327
      }
328
      if(fwrite(dp->host_page, dp->host_len, 1, f) < 1)
329
        fprintf(stderr, "Unable to write recompiled data to file: %s\n",
330
                strerror(errno));
331
 
332
      fclose(f);
333
    }
334
    sigsegv_state++;
335
  case 2:
336
    /* Dump the contents of the stack */
337
    printf("Stack dump: ");
338
    fflush(stdout);
339
 
340
    num_trace = backtrace(trace, 10);
341
 
342
    trace_names = backtrace_symbols(trace, num_trace);
343
 
344
    stack = get_sp();
345
    printf("(of stack at %p, base: %p)\n", stack, rec_stack_base);
346
    fflush(stdout);
347
    for(i = 0; stack < rec_stack_base; i++, stack += 4) {
348
      printf(" <%i> 0x%08x", i, *(uint32_t *)stack);
349
      /* Try to find a symbolic name with this entry */
350
      for(j = 0; j < num_trace; j++) {
351
        if(trace[j] == *(void **)stack)
352
          printf(" <%s>", trace_names[j]);
353
      }
354
      printf("\n");
355
      fflush(stdout);
356
    }
357
    sigsegv_state++;
358 1481 nogj
  case 3:
359 1452 nogj
    sim_done();
360
  }
361
}
362
 
363
static void add_to_dp(struct dyn_page *new)
364
{
365
  struct dyn_page *cur;
366
  struct dyn_page *prev;
367
 
368
  /* Find the location to insert the address */
369
  for(cur = cpu_state.dyn_pages, prev = NULL; cur; prev = cur, cur = cur->next) {
370
    if(cur->or_page > new->or_page)
371
      break;
372
  }
373
 
374
  if(prev)
375
    prev->next = new;
376
  else
377
    cpu_state.dyn_pages = new;
378
  new->next = cur;
379
}
380
 
381
struct dyn_page *new_dp(oraddr_t page)
382
{
383
  struct dyn_page *dp = malloc(sizeof(struct dyn_page));
384
  dp->or_page = ADDR_PAGE(page);
385
 
386 1483 nogj
  dp->locs = malloc(sizeof(void *) * (config.immu.pagesize / 4));
387 1452 nogj
 
388
  dp->host_len = 0;
389
  dp->host_page = NULL;
390
  dp->dirty = 1;
391
 
392
  add_to_dp(dp);
393
  return dp;
394
}
395
 
396
struct dyn_page *find_dynd_page(oraddr_t addr)
397
{
398
  struct dyn_page *cur = cpu_state.dyn_pages;
399
 
400 1483 nogj
  addr &= ~(config.immu.pagesize - 1);
401 1452 nogj
  while(cur) {
402
    if(cur->or_page == addr)
403
      return cur;
404
    if(cur->or_page > addr)
405
      return NULL; /* The dyn_page linked list is ordered */
406
    cur = cur->next;
407
  }
408
  return NULL;
409
}
410
 
411
/* This is called whenever the immu is either enabled/disabled or reconfigured
412
 * while enabled.  This checks if an itlb miss would occour and updates the immu
413
 * hit delay counter */
414
void recheck_immu(int got_en_dis)
415
{
416
  oraddr_t addr = get_pc();
417
  extern int immu_ex_from_insn;
418
 
419
  if(cpu_state.delay_insn) {
420
    /* If an instruction pagefault or ITLB would occur, it must appear to have
421
     * come from the jumped-to address */
422
    if(ADDR_PAGE(addr) == ADDR_PAGE(cpu_state.pc_delay)) {
423
      immu_ex_from_insn = 1;
424
      immu_translate(addr + 4);
425
      immu_ex_from_insn = 0;
426
      runtime.sim.mem_cycles = 0;
427
    }
428
    return;
429
  }
430
 
431
  if(ADDR_PAGE(addr) == ADDR_PAGE(addr + 4)) {
432
    /* If the next instruction is on another page then the immu will be checked
433
     * when the jump to the next page happens */
434
    immu_ex_from_insn = 1;
435
    immu_translate(addr + 4);
436
    immu_ex_from_insn = 0;
437
    /* If we had am immu hit then runtime.sim.mem_cycles will hold the value
438
     * config.immu.hitdelay, but this value is added to the cycle when the next
439
     * instruction is run */
440
    runtime.sim.mem_cycles = 0;
441
  }
442
  /* Only update the cycle decrementer if the mmu got enabled or disabled */
443
  if(got_en_dis == IMMU_GOT_ENABLED)
444
    /* Add the mmu hit delay to the cycle counter */
445
    upd_cycles_dec(cpu_state.curr_page->delayr - config.immu.hitdelay);
446
  else if(got_en_dis == IMMU_GOT_DISABLED) {
447
    upd_cycles_dec(cpu_state.curr_page->delayr);
448
    /* Since we updated the cycle decrementer above the immu hit delay will not
449
     * be added to the cycle counter for this instruction.  Compensate for this
450
     * by adding it now */
451
    /* FIXME: This is not correct here.  In the complex execution model the hit
452
     * delay is added to runtime.sim.mem_cycles which is only joined with the
453
     * cycle counter after analysis() and before the scheduler would run.
454
     * Therefore the scheduler will still be correct but analysis() will produce
455
     * wrong results just for this one instruction. */
456
    add_to_cycles(config.immu.hitdelay);
457
  }
458
}
459
 
460
/* Runs the scheduler.  Called from except_handler (and dirtyfy_page below) */
461
void run_sched_out_of_line(int add_normal)
462
{
463
  int brk;
464
  oraddr_t pc = get_pc();
465
 
466
  if(!cpu_state.ts_current)
467 1481 nogj
    upd_reg_from_t(pc, 0);
468 1452 nogj
 
469
  if(add_normal && do_stats) {
470
    cpu_state.iqueue.insn_addr = pc;
471
    cpu_state.iqueue.insn = eval_insn_direct(pc, &brk, 1);
472
    cpu_state.iqueue.insn_index = insn_decode(cpu_state.iqueue.insn);
473 1481 nogj
    runtime.cpu.instructions++;
474 1452 nogj
    analysis(&cpu_state.iqueue);
475
  }
476
 
477
  /* Run the scheduler */
478
  if(add_normal)
479
    sched_add_cycles();
480
 
481
  op_join_mem_cycles();
482
  upd_sim_cycles();
483
  if(scheduler.job_queue->time <= 0)
484
    do_scheduler();
485
}
486
 
487
/* Signals a page as dirty */
488
void dirtyfy_page(struct dyn_page *dp)
489
{
490
  oraddr_t check;
491
 
492
  printf("Dirtyfying page 0x%"PRIxADDR"\n", dp->or_page);
493
 
494
  dp->dirty = 1;
495
 
496
  /* If the execution is currently in the page that was touched then recompile
497
   * it now and jump back to the point of execution */
498
  check = cpu_state.delay_insn ? cpu_state.pc_delay : get_pc() + 4;
499
  if(ADDR_PAGE(check) == dp->or_page) {
500
    run_sched_out_of_line(1);
501
    recompile_page(dp);
502
 
503
    cpu_state.delay_insn = 0;
504
 
505
    /* Jump out to the next instruction */
506 1481 nogj
    do_jump(check);
507 1452 nogj
  }
508
}
509
 
510
static void ship_gprs_out_t(struct op_queue *opq, int end, unsigned int *reg_t)
511
{
512
  int i;
513
 
514 1481 nogj
  /* Before takeing the temporaries out, temporarily remove the op_do_sched
515
   * operation such that dyn_page->ts_bound shall be correct before the
516
   * scheduler runs */
517
  if(end && opq->num_ops && (opq->ops[opq->num_ops - 1] == op_do_sched_indx)) {
518
    opq->num_ops--;
519
    ship_gprs_out_t(opq, end, reg_t);
520
    gen_op_do_sched(opq, 1);
521
    return;
522
  }
523
 
524 1452 nogj
  for(i = 0; i < NUM_T_REGS; i++) {
525
    if(reg_t[i] < 32)
526
      gen_op_move_gpr_t[i][reg_t[i]](opq, end);
527
  }
528
}
529
 
530
static int find_unused_t(unsigned int *pres_t, unsigned int *reg_t)
531
{
532
  int empty = -1; /* Invalid */
533
  int i;
534
 
535
  /* Try to find a temporary that does not contain a register and is not
536
   * needed to be preserved */
537
  for(i = 0; i < NUM_T_REGS; i++) {
538
    if(!pres_t[i]) {
539
      empty = i;
540
      if(reg_t[i] > 31)
541
        return i;
542
    }
543
  }
544
  return empty;
545
}
546
 
547
/* Checks if there is enough space in dp->host_page, if not grow it */
548
void *enough_host_page(struct dyn_page *dp, void *cur, unsigned int *len,
549
                       unsigned int amount)
550
{
551
  unsigned int used = cur - dp->host_page;
552
 
553
  /* The array is long enough */
554
  if((used + amount) <= *len)
555
    return cur;
556
 
557
  /* Reallocate */
558
  *len += RECED_PAGE_ENLARGE_BY;
559
 
560
  if(!(dp->host_page = realloc(dp->host_page, *len))) {
561
    fprintf(stderr, "OOM\n");
562
    exit(1);
563
  }
564
 
565
  return dp->host_page + used;
566
}
567
 
568
/* Adds an operation to the opq */
569
void add_to_opq(struct op_queue *opq, int end, int op)
570
{
571
  if(opq->num_ops == opq->ops_len) {
572
    opq->ops_len += OPS_ENLARGE_BY;
573
    if(!(opq->ops = realloc(opq->ops, opq->ops_len * sizeof(int)))) {
574
      fprintf(stderr, "OOM\n");
575
      exit(1);
576
    }
577
  }
578
 
579
  if(end)
580
    opq->ops[opq->num_ops] = op;
581
  else {
582
    /* Shift everything over by one */
583
    memmove(opq->ops + 1, opq->ops, opq->num_ops* sizeof(int));
584
    opq->ops[0] = op;
585
  }
586
 
587
  opq->num_ops++;
588
}
589
 
590 1481 nogj
static void gen_op_mark_loc(struct op_queue *opq, int end)
591
{
592
  add_to_opq(opq, end, op_mark_loc_indx);
593
}
594
 
595 1452 nogj
/* Adds a parameter to the opq */
596
void add_to_op_params(struct op_queue *opq, int end, unsigned long param)
597
{
598
  if(opq->num_ops_param == opq->ops_param_len) {
599 1481 nogj
    opq->ops_param_len += OPS_ENLARGE_BY;
600
    if(!(opq->ops_param = realloc(opq->ops_param, opq->ops_param_len * sizeof(int)))) {
601 1452 nogj
      fprintf(stderr, "OOM\n");
602
      exit(1);
603
    }
604
  }
605
 
606
  if(end)
607
    opq->ops_param[opq->num_ops_param] = param;
608
  else {
609
    /* Shift everything over by one */
610
    memmove(opq->ops_param + 1, opq->ops_param, opq->num_ops_param);
611
    opq->ops_param[0] = param;
612
  }
613
 
614
  opq->num_ops_param++;
615
}
616
 
617
/* Function to guard against rogue ret instructions in the operations */
618
void dyn_ret_stack_prot(void)
619
{
620
  fprintf(stderr, "An operation (I have no clue which) has a ret statement in it\n");
621
  fprintf(stderr, "Good luck debugging it!\n");
622
 
623
  exit(1);
624
}
625
 
626
/* Jumps out to some Openrisc address */
627
void jump_dyn_code(oraddr_t addr)
628
{
629
  set_pc(addr);
630
  do_jump(addr);
631
}
632
 
633
/* Initialises the recompiler */
634
void init_dyn_recomp(void)
635
{
636
  struct sigaction sigact;
637
  struct op_queue *opq;
638
  unsigned int i;
639
 
640
  cpu_state.opqs = NULL;
641
 
642
  /* Allocate the operation queue list (+1 for the page chaining) */
643 1483 nogj
  for(i = 0; i < (config.immu.pagesize / 4) + 1; i++) {
644 1452 nogj
    if(!(opq = malloc(sizeof(struct op_queue)))) {
645
      fprintf(stderr, "OOM\n");
646
      exit(1);
647
    }
648
 
649
    /* initialise some fields */
650
    opq->ops_len = 0;
651
    opq->ops = NULL;
652
    opq->ops_param_len = 0;
653
    opq->ops_param = NULL;
654 1481 nogj
    opq->xref = 0;
655 1452 nogj
 
656
    if(cpu_state.opqs)
657
      cpu_state.opqs->prev = opq;
658
 
659
    opq->next = cpu_state.opqs;
660
    cpu_state.opqs = opq;
661
  }
662
 
663
  opq->prev = NULL;
664
 
665
  /* Just some value that we'll use as the base for our stack */
666
  rec_stack_base = get_sp();
667
 
668
  cpu_state.curr_page = NULL;
669
  cpu_state.dyn_pages = NULL;
670
 
671
  /* Register our segmentation fault handler */
672
  sigact.sa_sigaction = dyn_sigsegv_debug;
673
  memset(&sigact.sa_mask, 0, sizeof(sigact.sa_mask));
674
  sigact.sa_flags = SA_SIGINFO | SA_NOMASK;
675
  if(sigaction(SIGSEGV, &sigact, NULL))
676
    printf("WARN: Unable to install SIGSEGV handler! Don't expect to be able to debug the recompiler.\n");
677
 
678 1481 nogj
  /* Do architecture specific initialisation */
679 1452 nogj
  init_dyn_rec();
680
 
681
  /* FIXME: Find a better place for this */
682
    { /* Needed by execution */
683
      extern int do_stats;
684
      do_stats = config.cpu.dependstats || config.cpu.superscalar || config.cpu.dependstats
685
              || config.sim.history || config.sim.exe_log;
686
    }
687
 
688
  printf("Recompile engine up and running\n");
689
}
690
 
691 1481 nogj
/* Adds code to the opq for the instruction pointed to by addr */
692
static void recompile_insn(struct op_queue *opq, oraddr_t addr, int delay_insn)
693 1452 nogj
{
694 1481 nogj
  unsigned int insn_index;
695 1452 nogj
  unsigned int pres_t[NUM_T_REGS]; /* Which temporary to preserve */
696 1481 nogj
  orreg_t param[3];
697
  int i, j, k;
698 1452 nogj
  int param_t[3]; /* Which temporary the parameters reside in */
699
  int param_r[3]; /* is parameter a register */
700
  int param_num;
701 1481 nogj
  uint32_t insn;
702 1452 nogj
  int breakp;
703
  struct insn_op_struct *opd;
704
 
705 1481 nogj
  breakp = 0;
706
  insn = eval_insn(addr, &breakp);
707 1452 nogj
 
708 1481 nogj
  /* FIXME: If a breakpoint is set at this location, insert exception code */
709
  if(breakp) {
710
    fprintf(stderr, "FIXME: Insert breakpoint code\n");
711
  }
712 1452 nogj
 
713 1481 nogj
  insn_index = insn_decode(insn);
714 1452 nogj
 
715 1481 nogj
  /* Copy over the state of the temporaries to the next opq */
716
  memcpy(opq->reg_t_d, opq->reg_t, sizeof(opq->reg_t));
717 1452 nogj
 
718 1481 nogj
  /* Check if we have an illegal instruction */
719
  if(insn_index == -1) {
720
    gen_l_invalid(opq, NULL, NULL, delay_insn);
721
    return;
722
  }
723 1452 nogj
 
724 1481 nogj
  /* If we are recompileing an instruction that has a delay slot and is in the
725
   * delay slot, ignore it.  This is undefined behavour. */
726
  if(delay_insn && ((or32_opcodes[insn_index].func_unit == it_jump) ||
727
                    (or32_opcodes[insn_index].func_unit == it_branch)))
728
    return;
729 1452 nogj
 
730 1481 nogj
  /* figure out instruction operands */
731
  for(i = 0; i < NUM_T_REGS; i++)
732
    pres_t[i] = 0;
733 1452 nogj
 
734 1481 nogj
  param_t[0] = T_NONE;
735
  param_t[1] = T_NONE;
736
  param_t[2] = T_NONE;
737
  param_r[0] = 0;
738
  param_r[1] = 0;
739
  param_r[2] = 0;
740
  param_num = 0;
741 1452 nogj
 
742 1481 nogj
  opd = op_start[insn_index];
743
  while(1) {
744
    param[param_num] = eval_operand_val(insn, opd);
745 1452 nogj
 
746 1481 nogj
    if(opd->type & OPTYPE_REG) {
747
      /* check which temporary the register is in, if any */
748
      for(i = 0; i < NUM_T_REGS; i++) {
749
        if(opq->reg_t_d[i] == param[param_num]) {
750
          param_t[param_num] = i;
751
          pres_t[i] = 1;
752 1452 nogj
        }
753
      }
754
    }
755
 
756 1481 nogj
    param_num++;
757
    while(!(opd->type & OPTYPE_OP)) opd++;
758
    if(opd->type & OPTYPE_LAST)
759
      break;
760
    opd++;
761
  }
762 1452 nogj
 
763 1481 nogj
  /* Jump instructions are special since they have a delay slot and thus they
764
   * need to control the exact operation sequence.  Special case these, here to
765
   * avoid haveing loads of if(.func_unit != it_jump && != it_branch) below */
766
  if((or32_opcodes[insn_index].func_unit == it_jump) ||
767
     (or32_opcodes[insn_index].func_unit == it_branch)) {
768
    /* Ship the jump-to register out (if it exists).  It requires special
769
     * handleing, which is done in gen_j_reg. */
770
    for(i = 0; i < NUM_T_REGS; i++) {
771
      if(pres_t[i]) {
772
        gen_op_move_gpr_t[i][opq->reg_t_d[i]](opq->prev, 1);
773
        opq->reg_t_d[i] = 32;
774
        opq->reg_t[i] = 32;
775 1452 nogj
      }
776
    }
777
 
778
    /* FIXME: Do this in a more elegent way */
779
    if(!strncmp(or32_opcodes[insn_index].name, "l.jal", 5)) {
780
      /* In the case of a l.jal instruction, make sure that LINK_REGNO is not in
781
       * a temporary.  The problem is that the l.jal(r) instruction stores the
782
       * `return address' in LINK_REGNO.  The temporaries are shiped out only
783
       * after the delay slot instruction has executed and so it overwrittes the
784
       * `return address'. */
785
      for(k = 0; k < NUM_T_REGS; k++) {
786 1481 nogj
        if(opq->reg_t_d[k] == LINK_REGNO) {
787 1452 nogj
          gen_op_move_gpr_t[k][LINK_REGNO](opq, 1);
788 1481 nogj
          opq->reg_t_d[k] = 32;
789 1452 nogj
          break;
790
        }
791
      }
792
    }
793
 
794 1481 nogj
    /* Jump instructions don't have a disposition */
795
    or32_opcodes[insn_index].exec(opq, param_t, param, delay_insn);
796 1452 nogj
 
797 1481 nogj
    /* Analysis is done by the individual jump instructions */
798
    /* Jump instructions don't touch runtime.sim.mem_cycles */
799
    /* Jump instructions run their own scheduler */
800
    return;
801
  }
802 1452 nogj
 
803 1481 nogj
  /* Before an exception takes place, all registers must be stored. */
804
  if((or32_opcodes[insn_index].func_unit == it_exception)) {
805
    if(opq->prev) {
806
      ship_gprs_out_t(opq->prev, 1, opq->reg_t_d);
807
      for(i = 0; i < NUM_T_REGS; i++) {
808
        opq->reg_t_d[i] = 32;
809
        opq->reg_t[i] = 32;
810 1452 nogj
      }
811
    }
812 1481 nogj
  }
813 1452 nogj
 
814 1481 nogj
  opd = op_start[insn_index];
815 1452 nogj
 
816 1481 nogj
  for(j = 0; j < param_num; j++, opd++) {
817
    while(!(opd->type & OPTYPE_OP)) opd++;
818
    if(!(opd->type & OPTYPE_REG))
819
      continue;
820 1452 nogj
 
821 1481 nogj
    /* Never, ever, move r0 into a temporary */
822
    if(!param[j])
823
      continue;
824 1452 nogj
 
825 1481 nogj
    /* Check if this register has been moved into a temporary in a previous
826
     * operand */
827
    for(k = 0; k < NUM_T_REGS; k++) {
828
      if(opq->reg_t_d[k] == param[j]) {
829
        /* Yes, this register is already in a temporary */
830
        if(or32_opcodes[insn_index].func_unit != it_jump) {
831
          pres_t[k] = 1;
832
          param_t[j] = k;
833 1452 nogj
        }
834 1481 nogj
        break;
835 1452 nogj
      }
836
    }
837 1481 nogj
    if(k != NUM_T_REGS)
838
      continue;
839 1452 nogj
 
840 1481 nogj
    if(param_t[j] != T_NONE)
841
      continue;
842
 
843
    /* Search for an unused temporary */
844
    k = find_unused_t(pres_t, opq->reg_t_d);
845
    if(opq->reg_t_d[k] < 32) {
846
      /* FIXME: Only ship the temporary out if it has been used as a destination
847
       * register */
848
      gen_op_move_gpr_t[k][opq->reg_t_d[k]](opq->prev, 1);
849
      opq->reg_t[k] = 32;
850
      opq->reg_t_d[k] = 32;
851 1452 nogj
    }
852 1481 nogj
    pres_t[k] = 1;
853
    opq->reg_t_d[k] = param[j];
854
    param_t[j] = k;
855
    /* FIXME: Only generate code to move the register into a temporary if it
856
     *        is used as a source operand */
857
    gen_op_move_t_gpr[k][opq->reg_t_d[k]](opq, 0);
858
  }
859 1452 nogj
 
860 1481 nogj
  /* To get the execution log correct for instructions like l.lwz r4,0(r4) the
861
   * effective address needs to be calculated before the instruction is
862
   * simulated */
863
  if(do_stats) {
864
    /* Find any disposition in the instruction */
865
    opd = op_start[insn_index];
866
    for(j = 0; j < param_num; j++, opd++) {
867
      while(!(opd->type & OPTYPE_OP)) opd++;
868
      if(!(opd->type & OPTYPE_DIS))
869
        continue;
870
 
871
      if(!param[j + 1])
872
        gen_op_store_insn_ea(opq, 1, param[j]);
873
      else
874
        calc_insn_ea_table[param_t[j + 1]](opq, 1, param[j]);
875 1452 nogj
    }
876 1481 nogj
  }
877 1452 nogj
 
878 1481 nogj
  or32_opcodes[insn_index].exec(opq, param_t, param, delay_insn);
879
 
880
  if(or32_opcodes[insn_index].func_unit != it_exception) {
881
    if(do_stats)
882
      gen_op_analysis(opq, 1, insn_index, insn);
883
  }
884
 
885
  /* The call to join_mem_cycles() could be put into the individual operations
886
   * that emulate the load/store instructions, but then it would be added to
887
   * the cycle counter before analysis() is called, which is not how the complex
888
   * execution model does it. */
889
  if((or32_opcodes[insn_index].func_unit == it_load) ||
890
     (or32_opcodes[insn_index].func_unit == it_store))
891
    gen_op_join_mem_cycles(opq, 1);
892
 
893
  /* Delay slot instructions get a special scheduler, thus don't generate it
894
   * here */
895
  if((or32_opcodes[insn_index].func_unit != it_exception) && !delay_insn)
896 1452 nogj
    gen_op_do_sched(opq, 1);
897 1481 nogj
}
898 1452 nogj
 
899 1481 nogj
/* rec_page is a physical address */
900
void recompile_page(struct dyn_page *dyn)
901
{
902
  unsigned int j;
903
  struct op_queue *opq = cpu_state.opqs;
904
  oraddr_t rec_addr = dyn->or_page;
905
  oraddr_t rec_page = dyn->or_page;
906
  void **loc;
907 1452 nogj
 
908 1481 nogj
  /* The start of the next page */
909 1483 nogj
  rec_page += config.immu.pagesize;
910 1452 nogj
 
911 1481 nogj
  printf("Recompileing page %"PRIxADDR"\n", rec_addr);
912
  fflush(stdout);
913
 
914
  /* Mark all temporaries as not containing a register */
915
  for(j = 0; j < NUM_T_REGS; j++)
916
    opq->reg_t[j] = 32; /* Out-of-range registers */
917
 
918
  dyn->delayr = -verify_memoryarea(rec_addr)->delayr;
919
 
920
  opq->num_ops = 0;
921
  opq->num_ops_param = 0;
922
 
923
  /* Insert code to check if the first instruction is exeucted in a delay slot*/
924
  gen_op_check_delay_slot(opq, 1, 0);
925
  recompile_insn(opq, rec_addr, 1);
926
  ship_gprs_out_t(opq, 1, opq->reg_t_d);
927
  gen_op_do_sched_delay(opq, 1);
928
  gen_op_clear_delay_insn(opq, 1);
929
  gen_op_do_jump_delay(opq, 1);
930
  gen_op_mark_loc(opq, 1);
931
 
932
  for(j = 0; j < NUM_T_REGS; j++)
933
    opq->reg_t[j] = 32; /* Out-of-range registers */
934
 
935
  for(; rec_addr < rec_page; rec_addr += 4, opq = opq->next) {
936
    if(opq->prev) {
937
      opq->num_ops = 0;
938
      opq->num_ops_param = 0;
939 1452 nogj
    }
940 1481 nogj
    opq->jump_local = -1;
941
    opq->not_jump_loc = -1;
942 1452 nogj
 
943 1481 nogj
    opq->insn_addr = rec_addr;
944
 
945
    /* Check if this location is cross referenced */
946
    if(opq->xref) {
947
      /* If the current address is cross-referenced, the temporaries shall be
948
       * in an undefined state, so we must assume that no registers reside in
949
       * them */
950
      /* Ship out the current set of registers from the temporaries */
951
      if(opq->prev)
952
        ship_gprs_out_t(opq->prev, 1, opq->reg_t);
953
 
954
      for(j = 0; j < NUM_T_REGS; j++)
955
        opq->reg_t[j] = 32;
956 1452 nogj
    }
957
 
958 1481 nogj
    recompile_insn(opq, rec_addr, 0);
959
 
960
    /* Store the state of the temporaries */
961
    memcpy(opq->next->reg_t, opq->reg_t_d, sizeof(opq->reg_t));
962 1452 nogj
  }
963
 
964
  dyn->dirty = 0;
965
 
966 1481 nogj
  /* Store the state of the temporaries */
967 1483 nogj
  dyn->ts_bound[config.immu.pagesize >> 2] = dyn->ts_during[j];
968 1481 nogj
 
969 1452 nogj
  /* Ship temporaries out to the corrisponding registers */
970 1481 nogj
  ship_gprs_out_t(opq->prev, 1, opq->reg_t);
971 1452 nogj
 
972
  opq->num_ops = 0;
973
  opq->num_ops_param = 0;
974 1481 nogj
  opq->not_jump_loc = -1;
975
  opq->jump_local = -1;
976 1452 nogj
 
977
  /* Insert code to jump to the next page */
978
  gen_op_set_ts_current(opq, 1);
979 1481 nogj
  gen_op_do_jump(opq, 1);
980 1452 nogj
 
981
  /* Generate the code */
982
  gen_code(cpu_state.opqs, dyn);
983
 
984 1481 nogj
  /* Fix up the locations */
985 1483 nogj
  for(loc = dyn->locs; loc < &dyn->locs[config.immu.pagesize / 4]; loc++)
986 1481 nogj
    *loc += (unsigned int)dyn->host_page;
987 1452 nogj
 
988 1481 nogj
  cpu_state.opqs->ops_param[0] += (unsigned int)dyn->host_page;
989
 
990 1452 nogj
  /* Search for page-local jumps */
991 1483 nogj
  opq = cpu_state.opqs;
992
  for(j = 0; j < (config.immu.pagesize / 4); opq = opq->next, j++) {
993 1481 nogj
    if(opq->jump_local != -1)
994
      opq->ops_param[opq->jump_local] =
995
                              (unsigned int)dyn->locs[opq->jump_local_loc >> 2];
996 1452 nogj
 
997 1481 nogj
    if(opq->not_jump_loc != -1)
998
      opq->ops_param[opq->not_jump_loc] = (unsigned int)dyn->locs[j + 1];
999
 
1000
    /* Store the state of the temporaries into dyn->ts_bound */
1001
    dyn->ts_bound[j] = 0;
1002
    if(opq->reg_t[0] < 32)
1003
      dyn->ts_bound[j] = opq->reg_t[0];
1004
    if(opq->reg_t[1] < 32)
1005
      dyn->ts_bound[j] |= opq->reg_t[1] << 5;
1006
    if(opq->reg_t[2] < 32)
1007
      dyn->ts_bound[j] |= opq->reg_t[2] << 10;
1008
 
1009
    dyn->ts_during[j] = 0;
1010
    if(opq->reg_t_d[0] < 32)
1011
      dyn->ts_during[j] = opq->reg_t_d[0];
1012
    if(opq->reg_t_d[1] < 32)
1013
      dyn->ts_during[j] |= opq->reg_t_d[1] << 5;
1014
    if(opq->reg_t_d[2] < 32)
1015
      dyn->ts_during[j] |= opq->reg_t_d[2] << 10;
1016 1452 nogj
  }
1017
 
1018
  /* Patch the relocations */
1019
  patch_relocs(cpu_state.opqs, dyn->host_page);
1020
 
1021
  /* FIXME: Fix the issue below in a more elegent way */
1022
  /* Since eval_insn is called to get the instruction, runtime.sim.mem_cycles is
1023
   * updated but the recompiler expectes it to start a 0, so reset it */
1024
  runtime.sim.mem_cycles = 0;
1025
}
1026
 
1027
/* Returns non-zero if the jump is into this page, 0 otherwise */
1028
static int find_jump_loc(oraddr_t j_ea, struct op_queue *opq)
1029
{
1030
  int i;
1031
 
1032
  /* Mark the jump as non page local if the delay slot instruction is on the
1033
   * next page to the jump instruction.  This should not be needed */
1034
  if((ADDR_PAGE(j_ea) != ADDR_PAGE(opq->insn_addr)) ||
1035
     (ADDR_PAGE(opq->insn_addr) != ADDR_PAGE(opq->insn_addr + 4)))
1036
    /* We can't do anything as the j_ea (as passed to find_jump_loc) is a
1037
     * VIRTUAL offset and the next physical page may not be the next VIRTUAL
1038
     * page */
1039
    return 0;
1040
 
1041
  /* The jump is into the page currently undergoing dynamic recompilation */
1042
 
1043
  /* If we haven't got to the location of the jump, everything is ok */
1044 1481 nogj
  if(j_ea > opq->insn_addr) {
1045
    /* Find the corissponding opq and mark it as cross referenced */
1046
    for(i = (j_ea - opq->insn_addr) / 4; i; i--)
1047
      opq = opq->next;
1048
    opq->xref = 1;
1049 1452 nogj
    return 1;
1050 1481 nogj
  }
1051 1452 nogj
 
1052
  /* Insert temporary -> register code before the jump ea and register ->
1053
   * temporary at the x-ref address */
1054 1481 nogj
  for(i = (opq->insn_addr - j_ea) / 4; i; i--)
1055
    opq = opq->prev;
1056
 
1057 1452 nogj
  if(!opq->prev)
1058
    /* We're at the begining of a page, no need to do anything */
1059
    return 1;
1060
 
1061
  /* Found location, insert code */
1062 1481 nogj
 
1063 1452 nogj
  ship_gprs_out_t(opq->prev, 1, opq->reg_t);
1064
 
1065
  for(i = 0; i < NUM_T_REGS; i++) {
1066
    if(opq->reg_t[i] < 32) {
1067
      gen_op_move_t_gpr[i][opq->reg_t[i]](opq, 0);
1068
      opq->reg_t[i] = 32;
1069
    }
1070
  }
1071
 
1072 1481 nogj
  opq->xref = 1;
1073 1452 nogj
 
1074
  return 1;
1075
}
1076
 
1077 1481 nogj
static void gen_j_imm(struct op_queue *opq, oraddr_t off)
1078
{
1079
  int jump_local;
1080
  int i;
1081
  int reg_t[NUM_T_REGS];
1082
 
1083
  off <<= 2;
1084
 
1085
  jump_local = find_jump_loc(opq->insn_addr + off, opq);
1086
 
1087
  if(ADDR_PAGE(opq->insn_addr) != ADDR_PAGE(opq->insn_addr + 4)) {
1088
    gen_op_set_pc_delay_imm(opq, 1, off);
1089
    gen_op_do_sched(opq, 1);
1090
    return;
1091
  }
1092
 
1093
  gen_op_set_delay_insn(opq, 1);
1094
  gen_op_do_sched(opq, 1);
1095
 
1096
  /* Recompileing the delay slot instruction must see the temoraries being in
1097
   * the state after the jump/branch instruction not before */
1098
  memcpy(reg_t, opq->reg_t, sizeof(reg_t));
1099
  memcpy(opq->reg_t, opq->reg_t_d, sizeof(reg_t));
1100
 
1101
  /* Generate the delay slot instruction */
1102
  recompile_insn(opq, opq->insn_addr + 4, 1);
1103
 
1104
  memcpy(opq->reg_t, reg_t, sizeof(reg_t));
1105
 
1106
  ship_gprs_out_t(opq, 1, opq->reg_t_d);
1107
 
1108
  gen_op_add_pc(opq, 1, (orreg_t)off - 8);
1109
  gen_op_clear_delay_insn(opq, 1);
1110
  gen_op_do_sched_delay(opq, 1);
1111
 
1112
  if(jump_local) {
1113
    gen_op_jmp_imm(opq, 1, 0);
1114
    opq->jump_local = opq->num_ops_param - 1;
1115 1483 nogj
    opq->jump_local_loc = (opq->insn_addr + (orreg_t)off) & (config.immu.pagesize - 1);
1116 1481 nogj
  } else
1117
    gen_op_do_jump(opq, 1);
1118
}
1119
 
1120
static const generic_gen_op set_pc_delay_gpr[32] = {
1121
 NULL,
1122
 gen_op_move_gpr1_pc_delay,
1123
 gen_op_move_gpr2_pc_delay,
1124
 gen_op_move_gpr3_pc_delay,
1125
 gen_op_move_gpr4_pc_delay,
1126
 gen_op_move_gpr5_pc_delay,
1127
 gen_op_move_gpr6_pc_delay,
1128
 gen_op_move_gpr7_pc_delay,
1129
 gen_op_move_gpr8_pc_delay,
1130
 gen_op_move_gpr9_pc_delay,
1131
 gen_op_move_gpr10_pc_delay,
1132
 gen_op_move_gpr11_pc_delay,
1133
 gen_op_move_gpr12_pc_delay,
1134
 gen_op_move_gpr13_pc_delay,
1135
 gen_op_move_gpr14_pc_delay,
1136
 gen_op_move_gpr15_pc_delay,
1137
 gen_op_move_gpr16_pc_delay,
1138
 gen_op_move_gpr17_pc_delay,
1139
 gen_op_move_gpr18_pc_delay,
1140
 gen_op_move_gpr19_pc_delay,
1141
 gen_op_move_gpr20_pc_delay,
1142
 gen_op_move_gpr21_pc_delay,
1143
 gen_op_move_gpr22_pc_delay,
1144
 gen_op_move_gpr23_pc_delay,
1145
 gen_op_move_gpr24_pc_delay,
1146
 gen_op_move_gpr25_pc_delay,
1147
 gen_op_move_gpr26_pc_delay,
1148
 gen_op_move_gpr27_pc_delay,
1149
 gen_op_move_gpr28_pc_delay,
1150
 gen_op_move_gpr29_pc_delay,
1151
 gen_op_move_gpr30_pc_delay,
1152
 gen_op_move_gpr31_pc_delay };
1153
 
1154
static void gen_j_reg(struct op_queue *opq, unsigned int gpr, int insn_index,
1155
                      uint32_t insn)
1156
{
1157
  int i;
1158
  int reg_t[NUM_T_REGS];
1159
 
1160
  if(do_stats)
1161
    gen_op_analysis(opq, 1, insn_index, insn);
1162
 
1163
  if(!gpr)
1164
    gen_op_clear_pc_delay(opq, 1);
1165
  else
1166
    set_pc_delay_gpr[gpr](opq, 1);
1167
 
1168
  gen_op_do_sched(opq, 1);
1169
 
1170
  /* Recompileing the delay slot instruction must see the temoraries being in
1171
   * the state after the jump/branch instruction not before */
1172
  memcpy(reg_t, opq->reg_t, sizeof(reg_t));
1173
  memcpy(opq->reg_t, opq->reg_t_d, sizeof(reg_t));
1174
 
1175
  /* Generate the delay slot instruction */
1176
  gen_op_set_delay_insn(opq, 1);
1177
  recompile_insn(opq, opq->insn_addr + 4, 1);
1178
 
1179
  memcpy(opq->reg_t, reg_t, sizeof(reg_t));
1180
 
1181
  ship_gprs_out_t(opq, 1, opq->reg_t_d);
1182
 
1183
  gen_op_set_pc_pc_delay(opq, 1);
1184
  gen_op_clear_delay_insn(opq, 1);
1185
  gen_op_do_sched_delay(opq, 1);
1186
 
1187
  gen_op_do_jump_delay(opq, 1);
1188
}
1189
 
1190 1452 nogj
/*------------------------------[ Operation generation for an instruction ]---*/
1191
/* FIXME: Flag setting is not done in any instruction */
1192
/* FIXME: Since r0 is not moved into a temporary, check all arguments below! */
1193
 
1194
static const generic_gen_op clear_t[NUM_T_REGS] =
1195
 { gen_op_clear_t0, gen_op_clear_t1, gen_op_clear_t2 };
1196
 
1197
static const generic_gen_op move_t_t[NUM_T_REGS][NUM_T_REGS] = {
1198
/* param0 -> t0 */ { NULL, gen_op_move_t0_t1, gen_op_move_t0_t2 },
1199
/* param0 -> t1 */ { gen_op_move_t1_t0, NULL, gen_op_move_t1_t2 },
1200
/* param0 -> t2 */ { gen_op_move_t2_t0, gen_op_move_t2_t1, NULL } };
1201
 
1202
static const imm_gen_op mov_t_imm[NUM_T_REGS] =
1203
 { gen_op_t0_imm, gen_op_t1_imm, gen_op_t2_imm };
1204
 
1205
static const imm_gen_op l_add_imm_t_table[NUM_T_REGS][NUM_T_REGS] = {
1206
/* param0 -> t0 */ { gen_op_add_imm_t0_t0, gen_op_add_imm_t0_t1, gen_op_add_imm_t0_t2 },
1207
/* param0 -> t1 */ { gen_op_add_imm_t1_t0, gen_op_add_imm_t1_t1, gen_op_add_imm_t1_t2 },
1208
/* param0 -> t2 */ { gen_op_add_imm_t2_t0, gen_op_add_imm_t2_t1, gen_op_add_imm_t2_t2 } };
1209
 
1210
static const generic_gen_op l_add_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
1211
/* param0 -> t0 */              {
1212
/* param0 -> t0, param1 -> t0 */ { gen_op_add_t0_t0_t0, gen_op_add_t0_t0_t1, gen_op_add_t0_t0_t2 },
1213
/* param0 -> t0, param1 -> t1 */ { gen_op_add_t0_t1_t0, gen_op_add_t0_t1_t1, gen_op_add_t0_t1_t2 },
1214
/* param0 -> t0, param1 -> t2 */ { gen_op_add_t0_t2_t0, gen_op_add_t0_t2_t1, gen_op_add_t0_t2_t2 } },
1215
/* param0 -> t1 */              {
1216
/* param0 -> t1, param1 -> t0 */ { gen_op_add_t1_t0_t0, gen_op_add_t1_t0_t1, gen_op_add_t1_t0_t2 },
1217
/* param0 -> t1, param1 -> t1 */ { gen_op_add_t1_t1_t0, gen_op_add_t1_t1_t1, gen_op_add_t1_t1_t2 },
1218
/* param0 -> t1, param1 -> t2 */ { gen_op_add_t1_t2_t0, gen_op_add_t1_t2_t1, gen_op_add_t1_t2_t2 } },
1219
/* param0 -> t2 */              {
1220
/* param0 -> t2, param1 -> t0 */ { gen_op_add_t2_t0_t0, gen_op_add_t2_t0_t1, gen_op_add_t2_t0_t2 },
1221
/* param0 -> t2, param1 -> t1 */ { gen_op_add_t2_t1_t0, gen_op_add_t2_t1_t1, gen_op_add_t2_t1_t2 },
1222
/* param0 -> t2, param1 -> t2 */ { gen_op_add_t2_t2_t0, gen_op_add_t2_t2_t1, gen_op_add_t2_t2_t2 } } };
1223
 
1224
void gen_l_add(struct op_queue *opq, int param_t[3], orreg_t param[3],
1225
               int delay_slot)
1226
{
1227
  if(!param[0])
1228
    /* Screw this, the operation shall do nothing */
1229
    return;
1230
 
1231
  if(!param[1] && !param[2]) {
1232
    /* Just clear param_t[0] */
1233
    clear_t[param_t[0]](opq, 1);
1234
    return;
1235
  }
1236
 
1237
  if(!param[2]) {
1238
    if(param[0] != param[1])
1239
      /* This just moves a register */
1240
      move_t_t[param_t[0]][param_t[1]](opq, 1);
1241
    return;
1242
  }
1243
 
1244
  if(!param[1]) {
1245
    /* Check if we are moveing an immediate */
1246
    if(param_t[2] == T_NONE) {
1247
      /* Yep, an immediate */
1248
      mov_t_imm[param_t[0]](opq, 1, param[2]);
1249
      return;
1250
    }
1251
    /* Just another move */
1252
    if(param[0] != param[2])
1253
      move_t_t[param_t[0]][param_t[2]](opq, 1);
1254
    return;
1255
  }
1256
 
1257
  /* Ok, This _IS_ an add... */
1258
  if(param_t[2] == T_NONE)
1259
    /* immediate */
1260
    l_add_imm_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
1261
  else
1262
    l_add_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
1263
}
1264
 
1265
static const generic_gen_op l_addc_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
1266
/* param0 -> t0 */              {
1267
/* param0 -> t0, param1 -> t0 */ { gen_op_addc_t0_t0_t0, gen_op_addc_t0_t0_t1, gen_op_addc_t0_t0_t2 },
1268
/* param0 -> t0, param1 -> t1 */ { gen_op_addc_t0_t1_t0, gen_op_addc_t0_t1_t1, gen_op_addc_t0_t1_t2 },
1269
/* param0 -> t0, param1 -> t2 */ { gen_op_addc_t0_t2_t0, gen_op_addc_t0_t2_t1, gen_op_addc_t0_t2_t2 } },
1270
/* param0 -> t1 */              {
1271
/* param0 -> t1, param1 -> t0 */ { gen_op_addc_t1_t0_t0, gen_op_addc_t1_t0_t1, gen_op_addc_t1_t0_t2 },
1272
/* param0 -> t1, param1 -> t1 */ { gen_op_addc_t1_t1_t0, gen_op_addc_t1_t1_t1, gen_op_addc_t1_t1_t2 },
1273
/* param0 -> t1, param1 -> t2 */ { gen_op_addc_t1_t2_t0, gen_op_addc_t1_t2_t1, gen_op_addc_t1_t2_t2 } },
1274
/* param0 -> t2 */              {
1275
/* param0 -> t2, param1 -> t0 */ { gen_op_addc_t2_t0_t0, gen_op_addc_t2_t0_t1, gen_op_addc_t2_t0_t2 },
1276
/* param0 -> t2, param1 -> t1 */ { gen_op_addc_t2_t1_t0, gen_op_addc_t2_t1_t1, gen_op_addc_t2_t1_t2 },
1277
/* param0 -> t2, param1 -> t2 */ { gen_op_addc_t2_t2_t0, gen_op_addc_t2_t2_t1, gen_op_addc_t2_t2_t2 } } };
1278
 
1279
void gen_l_addc(struct op_queue *opq, int param_t[3], orreg_t param[3],
1280
                int delay_slot)
1281
{
1282
  if(!param[0])
1283
    /* Screw this, the operation shall do nothing */
1284
    return;
1285
 
1286
  /* FIXME: More optimisations !! (...and immediate...) */
1287
  l_addc_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
1288
}
1289
 
1290
static const imm_gen_op l_and_imm_t_table[NUM_T_REGS][NUM_T_REGS] = {
1291
/* param0 -> t0 */ { gen_op_and_imm_t0_t0, gen_op_and_imm_t0_t1, gen_op_and_imm_t0_t2 },
1292
/* param0 -> t1 */ { gen_op_and_imm_t1_t0, gen_op_and_imm_t1_t1, gen_op_and_imm_t1_t2 },
1293
/* param0 -> t2 */ { gen_op_and_imm_t2_t0, gen_op_and_imm_t2_t1, gen_op_and_imm_t2_t2 } };
1294
 
1295
static const generic_gen_op l_and_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
1296
/* param0 -> t0 */              {
1297
/* param0 -> t0, param1 -> t0 */ { NULL, gen_op_and_t0_t0_t1, gen_op_and_t0_t0_t2 },
1298
/* param0 -> t0, param1 -> t1 */ { gen_op_and_t0_t1_t0, gen_op_and_t0_t1_t1, gen_op_and_t0_t1_t2 },
1299
/* param0 -> t0, param1 -> t2 */ { gen_op_and_t0_t2_t0, gen_op_and_t0_t2_t1, gen_op_and_t0_t2_t2 } },
1300
/* param0 -> t1 */              {
1301
/* param0 -> t1, param1 -> t0 */ { gen_op_and_t1_t0_t0, gen_op_and_t1_t0_t1, gen_op_and_t1_t0_t2 },
1302
/* param0 -> t1, param1 -> t1 */ { gen_op_and_t1_t1_t0, NULL, gen_op_and_t1_t1_t2 },
1303
/* param0 -> t1, param1 -> t2 */ { gen_op_and_t1_t2_t0, gen_op_and_t1_t2_t1, gen_op_and_t1_t2_t2 } },
1304
/* param0 -> t2 */              {
1305
/* param0 -> t2, param1 -> t0 */ { gen_op_and_t2_t0_t0, gen_op_and_t2_t0_t1, gen_op_and_t2_t0_t2 },
1306
/* param0 -> t2, param1 -> t1 */ { gen_op_and_t2_t1_t0, gen_op_and_t2_t1_t1, gen_op_and_t2_t1_t2 },
1307
/* param0 -> t2, param1 -> t2 */ { gen_op_and_t2_t2_t0, gen_op_and_t2_t2_t1, NULL } } };
1308
 
1309
void gen_l_and(struct op_queue *opq, int param_t[3], orreg_t param[3],
1310
               int delay_slot)
1311
{
1312
  if(!param[0])
1313
    /* Screw this, the operation shall do nothing */
1314
    return;
1315
 
1316
  if(!param[1] || !param[2]) {
1317
    /* Just clear param_t[0] */
1318
    clear_t[param_t[0]](opq, 1);
1319
    return;
1320
  }
1321
 
1322
  if((param[0] == param[1] == param[2]) && (param_t[2] != T_NONE))
1323
    return;
1324
 
1325
  if(param_t[2] == T_NONE)
1326
    l_and_imm_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
1327
  else
1328
    l_and_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
1329
}
1330
 
1331
void gen_l_bf(struct op_queue *opq, int param_t[3], orreg_t param[3],
1332
              int delay_slot)
1333
{
1334 1481 nogj
  int i;
1335
  if(do_stats)
1336
    gen_op_analysis(opq, 1, 3, 0x10000000 | (param[0] & 0x03ffffff));
1337
 
1338
  /* The temporaries are expected to be shiped out after the execution of the
1339
   * branch instruction wether it branched or not */
1340
  if(opq->prev) {
1341
    ship_gprs_out_t(opq->prev, 1, opq->reg_t);
1342
    for(i = 0; i < NUM_T_REGS; i++) {
1343
      opq->reg_t[i] = 32;
1344
      opq->reg_t_d[i] = 32;
1345
    }
1346
  }
1347
 
1348
  if(ADDR_PAGE(opq->insn_addr) != ADDR_PAGE(opq->insn_addr + 4)) {
1349
    gen_op_check_flag_delay(opq, 1, param[0] << 2);
1350
    gen_op_do_sched(opq, 1);
1351
    opq->not_jump_loc = -1;
1352
    return;
1353
  }
1354
 
1355
  gen_op_check_flag(opq, 1, 0);
1356
  opq->not_jump_loc = opq->num_ops_param - 1;
1357
 
1358
  gen_j_imm(opq, param[0]);
1359 1452 nogj
}
1360
 
1361
void gen_l_bnf(struct op_queue *opq, int param_t[3], orreg_t param[3],
1362
               int delay_slot)
1363
{
1364 1481 nogj
  int i;
1365
  if(do_stats)
1366
    gen_op_analysis(opq, 1, 2, 0x0c000000 | (param[0] & 0x03ffffff));
1367
 
1368
  /* The temporaries are expected to be shiped out after the execution of the
1369
   * branch instruction wether it branched or not */
1370
  if(opq->prev) {
1371
    ship_gprs_out_t(opq->prev, 1, opq->reg_t);
1372
    for(i = 0; i < NUM_T_REGS; i++) {
1373
      opq->reg_t[i] = 32;
1374
      opq->reg_t_d[i] = 32;
1375
    }
1376
  }
1377
 
1378
  if(ADDR_PAGE(opq->insn_addr) != ADDR_PAGE(opq->insn_addr + 4)) {
1379
    gen_op_check_not_flag_delay(opq, 1, param[0] << 2);
1380
    gen_op_do_sched(opq, 1);
1381
    opq->not_jump_loc = -1;
1382
    return;
1383
  }
1384
 
1385
  gen_op_check_not_flag(opq, 1, 0);
1386
  opq->not_jump_loc = opq->num_ops_param - 1;
1387
 
1388
  gen_j_imm(opq, param[0]);
1389
 
1390
  /* The temporaries don't get shiped out if the branch is not taken */
1391
  memcpy(opq->next->reg_t, opq->reg_t, sizeof(opq->reg_t));
1392 1452 nogj
}
1393
 
1394
static const generic_gen_op l_cmov_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
1395
/* param0 -> t0 */              {
1396
/* param0 -> t0, param1 -> t0 */ { NULL, gen_op_cmov_t0_t0_t1, gen_op_cmov_t0_t0_t2 },
1397
/* param0 -> t0, param1 -> t1 */ { gen_op_cmov_t0_t1_t0, NULL, gen_op_cmov_t0_t1_t2 },
1398
/* param0 -> t0, param1 -> t2 */ { gen_op_cmov_t0_t2_t0, gen_op_cmov_t0_t2_t1, NULL } },
1399
/* param0 -> t1 */              {
1400
/* param0 -> t1, param1 -> t0 */ { NULL, gen_op_cmov_t1_t0_t1, gen_op_cmov_t1_t0_t2 },
1401
/* param0 -> t1, param1 -> t1 */ { gen_op_cmov_t1_t1_t0, NULL, gen_op_cmov_t1_t1_t2 },
1402
/* param0 -> t1, param1 -> t2 */ { gen_op_cmov_t1_t2_t0, gen_op_cmov_t1_t2_t1, NULL } },
1403
/* param0 -> t2 */              {
1404
/* param0 -> t2, param1 -> t0 */ { NULL, gen_op_cmov_t2_t0_t1, gen_op_cmov_t2_t0_t2 },
1405
/* param0 -> t2, param1 -> t1 */ { gen_op_cmov_t2_t1_t0, NULL, gen_op_cmov_t2_t1_t2 },
1406
/* param0 -> t2, param1 -> t2 */ { gen_op_cmov_t2_t2_t0, gen_op_cmov_t2_t2_t1, NULL } } };
1407
 
1408
/* FIXME: Check if either opperand 1 or 2 is r0 */
1409
void gen_l_cmov(struct op_queue *opq, int param_t[3], orreg_t param[3],
1410
                int delay_slot)
1411
{
1412
  if(!param[0])
1413
    return;
1414
 
1415
  if(!param[1] && !param[2]) {
1416
    clear_t[param_t[0]](opq, 1);
1417
    return;
1418
  }
1419
 
1420
  if(param[1] == param[2]) {
1421
    move_t_t[param_t[0]][param_t[1]](opq, 1);
1422
    return;
1423
  }
1424
 
1425
  if((param[1] == param[2]) && (param[0] == param[1]))
1426
    return;
1427
 
1428
  l_cmov_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
1429
}
1430
 
1431
void gen_l_cust1(struct op_queue *opq, int param_t[3], orreg_t param[3],
1432
                 int delay_slot)
1433
{
1434
}
1435
 
1436
void gen_l_cust2(struct op_queue *opq, int param_t[3], orreg_t param[3],
1437
                 int delay_slot)
1438
{
1439
}
1440
 
1441
void gen_l_cust3(struct op_queue *opq, int param_t[3], orreg_t param[3],
1442
                 int delay_slot)
1443
{
1444
}
1445
 
1446
void gen_l_cust4(struct op_queue *opq, int param_t[3], orreg_t param[3],
1447
                 int delay_slot)
1448
{
1449
}
1450
 
1451
void gen_l_cust5(struct op_queue *opq, int param_t[3], orreg_t param[3],
1452
                 int delay_slot)
1453
{
1454
}
1455
 
1456
void gen_l_cust6(struct op_queue *opq, int param_t[3], orreg_t param[3],
1457
                 int delay_slot)
1458
{
1459
}
1460
 
1461
void gen_l_cust7(struct op_queue *opq, int param_t[3], orreg_t param[3],
1462
                 int delay_slot)
1463
{
1464
}
1465
 
1466
void gen_l_cust8(struct op_queue *opq, int param_t[3], orreg_t param[3],
1467
                 int delay_slot)
1468
{
1469
}
1470
 
1471
/* FIXME: All registers need to be stored before the div instructions as they
1472
 * have the potenticial to cause an exception */
1473
 
1474
static const generic_gen_op check_null_excpt[NUM_T_REGS] =
1475
 { gen_op_check_null_except_t0, gen_op_check_null_except_t1, gen_op_check_null_except_t2 };
1476
 
1477
static const generic_gen_op check_null_excpt_delay[NUM_T_REGS] = {
1478
 gen_op_check_null_except_t0_delay,
1479
 gen_op_check_null_except_t1_delay,
1480
 gen_op_check_null_except_t2_delay };
1481
 
1482
static const generic_gen_op l_div_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
1483
/* param0 -> t0 */              {
1484
/* param0 -> t0, param1 -> t0 */ { gen_op_div_t0_t0_t0, gen_op_div_t0_t0_t1, gen_op_div_t0_t0_t2 },
1485
/* param0 -> t0, param1 -> t1 */ { gen_op_div_t0_t1_t0, gen_op_div_t0_t1_t1, gen_op_div_t0_t1_t2 },
1486
/* param0 -> t0, param1 -> t2 */ { gen_op_div_t0_t2_t0, gen_op_div_t0_t2_t1, gen_op_div_t0_t2_t2 } },
1487
/* param0 -> t1 */              {
1488
/* param0 -> t1, param1 -> t0 */ { gen_op_div_t1_t0_t0, gen_op_div_t1_t0_t1, gen_op_div_t1_t0_t2 },
1489
/* param0 -> t1, param1 -> t1 */ { gen_op_div_t1_t1_t0, gen_op_div_t1_t1_t1, gen_op_div_t1_t1_t2 },
1490
/* param0 -> t1, param1 -> t2 */ { gen_op_div_t1_t2_t0, gen_op_div_t1_t2_t1, gen_op_div_t1_t2_t2 } },
1491
/* param0 -> t2 */              {
1492
/* param0 -> t2, param1 -> t0 */ { gen_op_div_t2_t0_t0, gen_op_div_t2_t0_t1, gen_op_div_t2_t0_t2 },
1493
/* param0 -> t2, param1 -> t1 */ { gen_op_div_t2_t1_t0, gen_op_div_t2_t1_t1, gen_op_div_t2_t1_t2 },
1494
/* param0 -> t2, param1 -> t2 */ { gen_op_div_t2_t2_t0, gen_op_div_t2_t2_t1, gen_op_div_t2_t2_t2 } } };
1495
 
1496
void gen_l_div(struct op_queue *opq, int param_t[3], orreg_t param[3],
1497
               int delay_slot)
1498
{
1499
  if(!param[2]) {
1500
    /* There is no option.  This _will_ cause an illeagal exception */
1501
    if(!delay_slot)
1502
      gen_op_illegal(opq, 1);
1503
    else
1504
      gen_op_illegal(opq, 1);
1505
    return;
1506
  }
1507
 
1508
  if(!delay_slot)
1509
    check_null_excpt[param_t[2]](opq, 1);
1510
  else
1511
    check_null_excpt_delay[param_t[2]](opq, 1);
1512
 
1513
  if(!param[0])
1514
    return;
1515
 
1516
  if(!param[1]) {
1517
    /* Clear param_t[0] */
1518
    clear_t[param_t[0]](opq, 1);
1519
    return;
1520
  }
1521
 
1522
  l_div_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
1523
}
1524
 
1525
static const generic_gen_op l_divu_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
1526
/* param0 -> t0 */              {
1527
/* param0 -> t0, param1 -> t0 */ { gen_op_divu_t0_t0_t0, gen_op_divu_t0_t0_t1, gen_op_divu_t0_t0_t2 },
1528
/* param0 -> t0, param1 -> t1 */ { gen_op_divu_t0_t1_t0, gen_op_divu_t0_t1_t1, gen_op_divu_t0_t1_t2 },
1529
/* param0 -> t0, param1 -> t2 */ { gen_op_divu_t0_t2_t0, gen_op_divu_t0_t2_t1, gen_op_divu_t0_t2_t2 } },
1530
/* param0 -> t1 */              {
1531
/* param0 -> t1, param1 -> t0 */ { gen_op_divu_t1_t0_t0, gen_op_divu_t1_t0_t1, gen_op_divu_t1_t0_t2 },
1532
/* param0 -> t1, param1 -> t1 */ { gen_op_divu_t1_t1_t0, gen_op_divu_t1_t1_t1, gen_op_divu_t1_t1_t2 },
1533
/* param0 -> t1, param1 -> t2 */ { gen_op_divu_t1_t2_t0, gen_op_divu_t1_t2_t1, gen_op_divu_t1_t2_t2 } },
1534
/* param0 -> t2 */              {
1535
/* param0 -> t2, param1 -> t0 */ { gen_op_divu_t2_t0_t0, gen_op_divu_t2_t0_t1, gen_op_divu_t2_t0_t2 },
1536
/* param0 -> t2, param1 -> t1 */ { gen_op_divu_t2_t1_t0, gen_op_divu_t2_t1_t1, gen_op_divu_t2_t1_t2 },
1537
/* param0 -> t2, param1 -> t2 */ { gen_op_divu_t2_t2_t0, gen_op_divu_t2_t2_t1, gen_op_divu_t2_t2_t2 } } };
1538
 
1539
void gen_l_divu(struct op_queue *opq, int param_t[3], orreg_t param[3],
1540
                int delay_slot)
1541
{
1542
  if(!param[2]) {
1543
    /* There is no option.  This _will_ cause an illeagal exception */
1544
    if(!delay_slot)
1545
      gen_op_illegal(opq, 1);
1546
    else
1547
      gen_op_illegal(opq, 1);
1548
    return;
1549
  }
1550
 
1551
  if(!delay_slot)
1552
    check_null_excpt[param_t[2]](opq, 1);
1553
  else
1554
    check_null_excpt_delay[param_t[2]](opq, 1);
1555
 
1556
  if(!param[0])
1557
    return;
1558
 
1559
  if(!param[1]) {
1560
    /* Clear param_t[0] */
1561
    clear_t[param_t[0]](opq, 1);
1562
    return;
1563
  }
1564
 
1565
  l_divu_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
1566
}
1567
 
1568
static const generic_gen_op l_extbs_t_table[NUM_T_REGS][NUM_T_REGS] = {
1569
/* param0 -> t0 */ { gen_op_extbs_t0_t0, gen_op_extbs_t0_t1, gen_op_extbs_t0_t2 },
1570
/* param0 -> t1 */ { gen_op_extbs_t1_t0, gen_op_extbs_t1_t1, gen_op_extbs_t1_t2 },
1571
/* param0 -> t2 */ { gen_op_extbs_t2_t0, gen_op_extbs_t2_t1, gen_op_extbs_t2_t2 } };
1572
 
1573
void gen_l_extbs(struct op_queue *opq, int param_t[3], orreg_t param[3],
1574
                 int delay_slot)
1575
{
1576
  if(!param[0])
1577
    return;
1578
 
1579
  if(!param[1]) {
1580
    clear_t[param_t[0]](opq, 1);
1581
    return;
1582
  }
1583
 
1584
  l_extbs_t_table[param_t[0]][param_t[1]](opq, 1);
1585
}
1586
 
1587
static const generic_gen_op l_extbz_t_table[NUM_T_REGS][NUM_T_REGS] = {
1588
/* param0 -> t0 */ { gen_op_extbz_t0_t0, gen_op_extbz_t0_t1, gen_op_extbz_t0_t2 },
1589
/* param0 -> t1 */ { gen_op_extbz_t1_t0, gen_op_extbz_t1_t1, gen_op_extbz_t1_t2 },
1590
/* param0 -> t2 */ { gen_op_extbz_t2_t0, gen_op_extbz_t2_t1, gen_op_extbz_t2_t2 } };
1591
 
1592
void gen_l_extbz(struct op_queue *opq, int param_t[3], orreg_t param[3],
1593
                 int delay_slot)
1594
{
1595
  if(!param[0])
1596
    return;
1597
 
1598
  if(!param[1]) {
1599
    clear_t[param_t[0]](opq, 1);
1600
    return;
1601
  }
1602
 
1603
  l_extbz_t_table[param_t[0]][param_t[1]](opq, 1);
1604
}
1605
 
1606
static const generic_gen_op l_exths_t_table[NUM_T_REGS][NUM_T_REGS] = {
1607
/* param0 -> t0 */ { gen_op_exths_t0_t0, gen_op_exths_t0_t1, gen_op_exths_t0_t2 },
1608
/* param0 -> t1 */ { gen_op_exths_t1_t0, gen_op_exths_t1_t1, gen_op_exths_t1_t2 },
1609
/* param0 -> t2 */ { gen_op_exths_t2_t0, gen_op_exths_t2_t1, gen_op_exths_t2_t2 } };
1610
 
1611
void gen_l_exths(struct op_queue *opq, int param_t[3], orreg_t param[3],
1612
                 int delay_slot)
1613
{
1614
  if(!param[0])
1615
    return;
1616
 
1617
  if(!param[1]) {
1618
    clear_t[param_t[0]](opq, 1);
1619
    return;
1620
  }
1621
 
1622
  l_exths_t_table[param_t[0]][param_t[1]](opq, 1);
1623
}
1624
 
1625
static const generic_gen_op l_exthz_t_table[NUM_T_REGS][NUM_T_REGS] = {
1626
/* param0 -> t0 */ { gen_op_exthz_t0_t0, gen_op_exthz_t0_t1, gen_op_exthz_t0_t2 },
1627
/* param0 -> t1 */ { gen_op_exthz_t1_t0, gen_op_exthz_t1_t1, gen_op_exthz_t1_t2 },
1628
/* param0 -> t2 */ { gen_op_exthz_t2_t0, gen_op_exthz_t2_t1, gen_op_exthz_t2_t2 } };
1629
 
1630
void gen_l_exthz(struct op_queue *opq, int param_t[3], orreg_t param[3],
1631
                 int delay_slot)
1632
{
1633
  if(!param[0])
1634
    return;
1635
 
1636
  if(!param[1]) {
1637
    clear_t[param_t[0]](opq, 1);
1638
    return;
1639
  }
1640
 
1641
  l_exthz_t_table[param_t[0]][param_t[1]](opq, 1);
1642
}
1643
 
1644
void gen_l_extws(struct op_queue *opq, int param_t[3], orreg_t param[3],
1645
                 int delay_slot)
1646
{
1647
  if(!param[0])
1648
    return;
1649
 
1650
  if(!param[1]) {
1651
    clear_t[param_t[0]](opq, 1);
1652
    return;
1653
  }
1654
 
1655
  if(param[0] == param[1])
1656
    return;
1657
 
1658
  /* In the 32-bit architechture this instruction reduces to a move */
1659
  move_t_t[param_t[0]][param_t[1]](opq, 1);
1660
}
1661
 
1662
void gen_l_extwz(struct op_queue *opq, int param_t[3], orreg_t param[3],
1663
                 int delay_slot)
1664
{
1665
  if(!param[0])
1666
    return;
1667
 
1668
  if(!param[1]) {
1669
    clear_t[param_t[0]](opq, 1);
1670
    return;
1671
  }
1672
 
1673
  if(param[0] == param[1])
1674
    return;
1675
 
1676
  /* In the 32-bit architechture this instruction reduces to a move */
1677
  move_t_t[param_t[0]][param_t[1]](opq, 1);
1678
}
1679
 
1680
static const generic_gen_op l_ff1_t_table[NUM_T_REGS][NUM_T_REGS] = {
1681
/* param0 -> t0 */ { gen_op_ff1_t0_t0, gen_op_ff1_t0_t1, gen_op_ff1_t0_t2 },
1682
/* param0 -> t1 */ { gen_op_ff1_t1_t0, gen_op_ff1_t1_t1, gen_op_ff1_t1_t2 },
1683
/* param0 -> t2 */ { gen_op_ff1_t2_t0, gen_op_ff1_t2_t1, gen_op_ff1_t2_t2 } };
1684
 
1685
void gen_l_ff1(struct op_queue *opq, int param_t[3], orreg_t param[3],
1686
               int delay_slot)
1687
{
1688
  if(!param[0])
1689
    return;
1690
 
1691
  if(!param[1]) {
1692
    clear_t[param_t[0]](opq, 1);
1693
    return;
1694
  }
1695
 
1696
  l_ff1_t_table[param_t[0]][param_t[1]](opq, 1);
1697
}
1698
 
1699
void gen_l_j(struct op_queue *opq, int param_t[3], orreg_t param[3],
1700
             int delay_slot)
1701
{
1702 1481 nogj
  if(do_stats)
1703
    gen_op_analysis(opq, 1, 0, param[0] & 0x03ffffff);
1704 1452 nogj
 
1705 1481 nogj
  gen_j_imm(opq, param[0]);
1706 1452 nogj
}
1707
 
1708
void gen_l_jal(struct op_queue *opq, int param_t[3], orreg_t param[3],
1709
               int delay_slot)
1710
{
1711 1481 nogj
  /* Store the return address */
1712
  gen_op_store_link_addr_gpr(opq, 1);
1713 1452 nogj
 
1714 1481 nogj
  if(do_stats)
1715
    gen_op_analysis(opq, 1, 1, 0x04000000 | (param[0] & 0x03ffffff));
1716 1452 nogj
 
1717 1481 nogj
  gen_j_imm(opq, param[0]);
1718 1452 nogj
}
1719
 
1720
void gen_l_jr(struct op_queue *opq, int param_t[3], orreg_t param[3],
1721
              int delay_slot)
1722
{
1723 1481 nogj
  gen_j_reg(opq, param[0], 104, 0x14000000 | (param[0] << 11));
1724 1452 nogj
}
1725
 
1726
void gen_l_jalr(struct op_queue *opq, int param_t[3], orreg_t param[3],
1727
                int delay_slot)
1728
{
1729
  /* Store the return address */
1730
  gen_op_store_link_addr_gpr(opq, 1);
1731 1481 nogj
 
1732
  gen_j_reg(opq, param[0], 105, 0x18000000 | (param[0] << 11));
1733 1452 nogj
}
1734
 
1735
/* FIXME: Optimise all load instruction when the disposition == 0 */
1736
 
1737
static const imm_gen_op l_lbs_imm_t_table[NUM_T_REGS] =
1738
 { gen_op_lbs_imm_t0, gen_op_lbs_imm_t1, gen_op_lbs_imm_t2 };
1739
 
1740
static const imm_gen_op l_lbs_t_table[3][3] = {
1741
/* param0 -> t0 */ { gen_op_lbs_t0_t0, gen_op_lbs_t0_t1, gen_op_lbs_t0_t2 },
1742
/* param0 -> t1 */ { gen_op_lbs_t1_t0, gen_op_lbs_t1_t1, gen_op_lbs_t1_t2 },
1743
/* param0 -> t2 */ { gen_op_lbs_t2_t0, gen_op_lbs_t2_t1, gen_op_lbs_t2_t2 } };
1744
 
1745
void gen_l_lbs(struct op_queue *opq, int param_t[3], orreg_t param[3],
1746
               int delay_slot)
1747
{
1748
  if(!param[0]) {
1749
    /* FIXME: This will work, but the statistics need to be updated... */
1750
    return;
1751
  }
1752
 
1753
  if(!param[2]) {
1754
    /* Load the data from the immediate */
1755
    l_lbs_imm_t_table[param_t[0]](opq, 1, param[1]);
1756
    return;
1757
  }
1758
 
1759
  l_lbs_t_table[param_t[0]][param_t[2]](opq, 1, param[1]);
1760
}
1761
 
1762
static const imm_gen_op l_lbz_imm_t_table[NUM_T_REGS] =
1763
 { gen_op_lbz_imm_t0, gen_op_lbz_imm_t1, gen_op_lbz_imm_t2 };
1764
 
1765
static const imm_gen_op l_lbz_t_table[NUM_T_REGS][NUM_T_REGS] = {
1766
/* param0 -> t0 */ { gen_op_lbz_t0_t0, gen_op_lbz_t0_t1, gen_op_lbz_t0_t2 },
1767
/* param0 -> t1 */ { gen_op_lbz_t1_t0, gen_op_lbz_t1_t1, gen_op_lbz_t1_t2 },
1768
/* param0 -> t2 */ { gen_op_lbz_t2_t0, gen_op_lbz_t2_t1, gen_op_lbz_t2_t2 } };
1769
 
1770
void gen_l_lbz(struct op_queue *opq, int param_t[3], orreg_t param[3],
1771
               int delay_slot)
1772
{
1773
  if(!param[0]) {
1774
    /* FIXME: This will work, but the statistics need to be updated... */
1775
    return;
1776
  }
1777
 
1778
  if(!param[2]) {
1779
    /* Load the data from the immediate */
1780
    l_lbz_imm_t_table[param_t[0]](opq, 1, param[1]);
1781
    return;
1782
  }
1783
 
1784
  l_lbz_t_table[param_t[0]][param_t[2]](opq, 1, param[1]);
1785
}
1786
 
1787
static const imm_gen_op l_lhs_imm_t_table[NUM_T_REGS] =
1788
 { gen_op_lhs_imm_t0, gen_op_lhs_imm_t1, gen_op_lhs_imm_t2 };
1789
 
1790
static const imm_gen_op l_lhs_t_table[NUM_T_REGS][NUM_T_REGS] = {
1791
/* param0 -> t0 */ { gen_op_lhs_t0_t0, gen_op_lhs_t0_t1, gen_op_lhs_t0_t2 },
1792
/* param0 -> t1 */ { gen_op_lhs_t1_t0, gen_op_lhs_t1_t1, gen_op_lhs_t1_t2 },
1793
/* param0 -> t2 */ { gen_op_lhs_t2_t0, gen_op_lhs_t2_t1, gen_op_lhs_t2_t2 } };
1794
 
1795
void gen_l_lhs(struct op_queue *opq, int param_t[3], orreg_t param[3],
1796
               int delay_slot)
1797
{
1798
  if(!param[0]) {
1799
    /* FIXME: This will work, but the statistics need to be updated... */
1800
    return;
1801
  }
1802
 
1803
  if(!param[2]) {
1804
    /* Load the data from the immediate */
1805
    l_lhs_imm_t_table[param_t[0]](opq, 1, param[1]);
1806
    return;
1807
  }
1808
 
1809
  l_lhs_t_table[param_t[0]][param_t[2]](opq, 1, param[1]);
1810
}
1811
 
1812
static const imm_gen_op l_lhz_imm_t_table[NUM_T_REGS] =
1813
 { gen_op_lhz_imm_t0, gen_op_lhz_imm_t1, gen_op_lhz_imm_t2 };
1814
 
1815
static const imm_gen_op l_lhz_t_table[NUM_T_REGS][NUM_T_REGS] = {
1816
/* param0 -> t0 */ { gen_op_lhz_t0_t0, gen_op_lhz_t0_t1, gen_op_lhz_t0_t2 },
1817
/* param0 -> t1 */ { gen_op_lhz_t1_t0, gen_op_lhz_t1_t1, gen_op_lhz_t1_t2 },
1818
/* param0 -> t2 */ { gen_op_lhz_t2_t0, gen_op_lhz_t2_t1, gen_op_lhz_t2_t2 } };
1819
 
1820
void gen_l_lhz(struct op_queue *opq, int param_t[3], orreg_t param[3],
1821
               int delay_slot)
1822
{
1823
  if(!param[0]) {
1824
    /* FIXME: This will work, but the statistics need to be updated... */
1825
    return;
1826
  }
1827
 
1828
  if(!param[2]) {
1829
    /* Load the data from the immediate */
1830
    l_lhz_imm_t_table[param_t[0]](opq, 1, param[1]);
1831
    return;
1832
  }
1833
 
1834
  l_lhz_t_table[param_t[0]][param_t[2]](opq, 1, param[1]);
1835
}
1836
 
1837
static const imm_gen_op l_lws_imm_t_table[NUM_T_REGS] =
1838
 { gen_op_lws_imm_t0, gen_op_lws_imm_t1, gen_op_lws_imm_t2 };
1839
 
1840
static const imm_gen_op l_lws_t_table[NUM_T_REGS][NUM_T_REGS] = {
1841
/* param0 -> t0 */ { gen_op_lws_t0_t0, gen_op_lws_t0_t1, gen_op_lws_t0_t2 },
1842
/* param0 -> t1 */ { gen_op_lws_t1_t0, gen_op_lws_t1_t1, gen_op_lws_t1_t2 },
1843
/* param0 -> t2 */ { gen_op_lws_t2_t0, gen_op_lws_t2_t1, gen_op_lws_t2_t2 } };
1844
 
1845
void gen_l_lws(struct op_queue *opq, int param_t[3], orreg_t param[3],
1846
               int delay_slot)
1847
{
1848
  if(!param[0]) {
1849
    /* FIXME: This will work, but the statistics need to be updated... */
1850
    return;
1851
  }
1852
 
1853
  if(!param[2]) {
1854
    /* Load the data from the immediate */
1855
    l_lws_imm_t_table[param_t[0]](opq, 1, param[1]);
1856
    return;
1857
  }
1858
 
1859
  l_lws_t_table[param_t[0]][param_t[2]](opq, 1, param[1]);
1860
}
1861
 
1862
static const imm_gen_op l_lwz_imm_t_table[NUM_T_REGS] =
1863
 { gen_op_lwz_imm_t0, gen_op_lwz_imm_t1, gen_op_lwz_imm_t2 };
1864
 
1865
static const imm_gen_op l_lwz_t_table[NUM_T_REGS][NUM_T_REGS] = {
1866
/* param0 -> t0 */ { gen_op_lwz_t0_t0, gen_op_lwz_t0_t1, gen_op_lwz_t0_t2 },
1867
/* param0 -> t1 */ { gen_op_lwz_t1_t0, gen_op_lwz_t1_t1, gen_op_lwz_t1_t2 },
1868
/* param0 -> t2 */ { gen_op_lwz_t2_t0, gen_op_lwz_t2_t1, gen_op_lwz_t2_t2 } };
1869
 
1870
void gen_l_lwz(struct op_queue *opq, int param_t[3], orreg_t param[3],
1871
               int delay_slot)
1872
{
1873
  if(!param[0]) {
1874
    /* FIXME: This will work, but the statistics need to be updated... */
1875
    return;
1876
  }
1877
 
1878
  if(!param[2]) {
1879
    /* Load the data from the immediate */
1880
    l_lwz_imm_t_table[param_t[0]](opq, 1, param[1]);
1881
    return;
1882
  }
1883
 
1884
  l_lwz_t_table[param_t[0]][param_t[2]](opq, 1, param[1]);
1885
}
1886
 
1887
static const imm_gen_op l_mac_imm_t_table[NUM_T_REGS] =
1888
 { gen_op_mac_imm_t0, gen_op_mac_imm_t1, gen_op_mac_imm_t2 };
1889
 
1890
static const generic_gen_op l_mac_t_table[NUM_T_REGS][NUM_T_REGS] = {
1891
/* param0 -> t0 */ { gen_op_mac_t0_t0, gen_op_mac_t0_t1, gen_op_mac_t0_t2 },
1892
/* param0 -> t1 */ { gen_op_mac_t0_t1, gen_op_mac_t1_t1, gen_op_mac_t1_t2 },
1893
/* param0 -> t2 */ { gen_op_mac_t0_t2, gen_op_mac_t1_t2, gen_op_mac_t2_t2 } };
1894
 
1895
void gen_l_mac(struct op_queue *opq, int param_t[3], orreg_t param[3],
1896
               int delay_slot)
1897
{
1898
  if(!param[0] || !param[1])
1899
    return;
1900
 
1901
  if(param_t[1] == T_NONE)
1902
    l_mac_imm_t_table[param_t[0]](opq, 1, param[1]);
1903
  else
1904
    l_mac_t_table[param_t[0]][param_t[1]](opq, 1);
1905
}
1906
 
1907
static const generic_gen_op l_macrc_t_table[NUM_T_REGS] =
1908
 { gen_op_macrc_t0, gen_op_macrc_t1, gen_op_macrc_t2 };
1909
 
1910
void gen_l_macrc(struct op_queue *opq, int param_t[3], orreg_t param[3],
1911
                 int delay_slot)
1912
{
1913
  if(!param[0]) {
1914
    gen_op_macc(opq, 1);
1915
    return;
1916
  }
1917
 
1918
  l_macrc_t_table[param_t[0]](opq, 1);
1919
}
1920
 
1921
static const imm_gen_op l_mfspr_imm_t_table[NUM_T_REGS] =
1922
 { gen_op_mfspr_t0_imm, gen_op_mfspr_t1_imm, gen_op_mfspr_t2_imm };
1923
 
1924
static const imm_gen_op l_mfspr_t_table[NUM_T_REGS][NUM_T_REGS] = {
1925
/* param0 -> t0 */ { gen_op_mfspr_t0_t0, gen_op_mfspr_t0_t1, gen_op_mfspr_t0_t2 },
1926
/* param0 -> t1 */ { gen_op_mfspr_t1_t0, gen_op_mfspr_t1_t1, gen_op_mfspr_t1_t2 },
1927
/* param0 -> t2 */ { gen_op_mfspr_t2_t0, gen_op_mfspr_t2_t1, gen_op_mfspr_t2_t2 } };
1928
 
1929
void gen_l_mfspr(struct op_queue *opq, int param_t[3], orreg_t param[3],
1930
                 int delay_slot)
1931
{
1932
  if(!param[0])
1933
    return;
1934
 
1935
  if(!param[1]) {
1936
    l_mfspr_imm_t_table[param_t[0]](opq, 1, param[2]);
1937
    return;
1938
  }
1939
 
1940
  l_mfspr_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
1941
}
1942
 
1943
void gen_l_movhi(struct op_queue *opq, int param_t[3], orreg_t param[3],
1944
                 int delay_slot)
1945
{
1946
  if(!param[0])
1947
    return;
1948
 
1949
  if(!param[1]) {
1950
    clear_t[param_t[0]](opq, 1);
1951
    return;
1952
  }
1953
 
1954
  mov_t_imm[param_t[0]](opq, 1, param[1] << 16);
1955
}
1956
 
1957
static const generic_gen_op l_msb_t_table[NUM_T_REGS][NUM_T_REGS] = {
1958
/* param0 -> t0 */ { gen_op_msb_t0_t0, gen_op_msb_t0_t1, gen_op_msb_t0_t2 },
1959
/* param0 -> t1 */ { gen_op_msb_t0_t1, gen_op_msb_t1_t1, gen_op_msb_t1_t2 },
1960
/* param0 -> t2 */ { gen_op_msb_t0_t2, gen_op_msb_t1_t2, gen_op_msb_t2_t2 } };
1961
 
1962
void gen_l_msb(struct op_queue *opq, int param_t[3], orreg_t param[3],
1963
               int delay_slot)
1964
{
1965
  if(!param[0] || !param[1])
1966
    return;
1967
 
1968
  l_msb_t_table[param_t[0]][param_t[1]](opq, 1);
1969
}
1970
 
1971
static const imm_gen_op l_mtspr_clear_t_table[NUM_T_REGS] =
1972
 { gen_op_mtspr_t0_clear, gen_op_mtspr_t1_clear, gen_op_mtspr_t2_clear };
1973
 
1974
static const imm_gen_op l_mtspr_imm_t_table[NUM_T_REGS] =
1975
 { gen_op_mtspr_imm_t0, gen_op_mtspr_imm_t1, gen_op_mtspr_imm_t2 };
1976
 
1977
static const imm_gen_op l_mtspr_t_table[NUM_T_REGS][NUM_T_REGS] = {
1978
/* param0 -> t0 */ { gen_op_mtspr_t0_t0, gen_op_mtspr_t0_t1, gen_op_mtspr_t0_t2 },
1979
/* param0 -> t1 */ { gen_op_mtspr_t1_t0, gen_op_mtspr_t1_t1, gen_op_mtspr_t1_t2 },
1980
/* param0 -> t2 */ { gen_op_mtspr_t2_t0, gen_op_mtspr_t2_t1, gen_op_mtspr_t2_t2 } };
1981
 
1982
void gen_l_mtspr(struct op_queue *opq, int param_t[3], orreg_t param[3],
1983
                 int delay_slot)
1984
{
1985
  if(!param[0]) {
1986
    if(!param[1]) {
1987
      /* Clear the immediate SPR */
1988
      gen_op_mtspr_imm_clear(opq, 1, param[2]);
1989
      return;
1990
    }
1991
    l_mtspr_imm_t_table[param_t[1]](opq, 1, param[2]);
1992
    return;
1993
  }
1994
 
1995
  if(!param[1]) {
1996
    l_mtspr_clear_t_table[param_t[0]](opq, 1, param[2]);
1997
    return;
1998
  }
1999
 
2000
  l_mtspr_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
2001
}
2002
 
2003
static const imm_gen_op l_mul_imm_t_table[NUM_T_REGS][NUM_T_REGS] = {
2004
/* param0 -> t0 */ { gen_op_mul_imm_t0_t0, gen_op_mul_imm_t0_t1, gen_op_mul_imm_t0_t2 },
2005
/* param0 -> t1 */ { gen_op_mul_imm_t1_t0, gen_op_mul_imm_t1_t1, gen_op_mul_imm_t1_t2 },
2006
/* param0 -> t2 */ { gen_op_mul_imm_t2_t0, gen_op_mul_imm_t2_t1, gen_op_mul_imm_t2_t2 } };
2007
 
2008
static const generic_gen_op l_mul_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
2009
/* param0 -> t0 */              {
2010
/* param0 -> t0, param1 -> t0 */ { gen_op_mul_t0_t0_t0, gen_op_mul_t0_t0_t1, gen_op_mul_t0_t0_t2 },
2011
/* param0 -> t0, param1 -> t1 */ { gen_op_mul_t0_t1_t0, gen_op_mul_t0_t1_t1, gen_op_mul_t0_t1_t2 },
2012
/* param0 -> t0, param1 -> t2 */ { gen_op_mul_t0_t2_t0, gen_op_mul_t0_t2_t1, gen_op_mul_t0_t2_t2 } },
2013
/* param0 -> t1 */              {
2014
/* param0 -> t1, param1 -> t0 */ { gen_op_mul_t1_t0_t0, gen_op_mul_t1_t0_t1, gen_op_mul_t1_t0_t2 },
2015
/* param0 -> t1, param1 -> t1 */ { gen_op_mul_t1_t1_t0, gen_op_mul_t1_t1_t1, gen_op_mul_t1_t1_t2 },
2016
/* param0 -> t1, param1 -> t2 */ { gen_op_mul_t1_t2_t0, gen_op_mul_t1_t2_t1, gen_op_mul_t1_t2_t2 } },
2017
/* param0 -> t2 */              {
2018
/* param0 -> t2, param1 -> t0 */ { gen_op_mul_t2_t0_t0, gen_op_mul_t2_t0_t1, gen_op_mul_t2_t0_t2 },
2019
/* param0 -> t2, param1 -> t1 */ { gen_op_mul_t2_t1_t0, gen_op_mul_t2_t1_t1, gen_op_mul_t2_t1_t2 },
2020
/* param0 -> t2, param1 -> t2 */ { gen_op_mul_t2_t2_t0, gen_op_mul_t2_t2_t1, gen_op_mul_t2_t2_t2 } } };
2021
 
2022
void gen_l_mul(struct op_queue *opq, int param_t[3], orreg_t param[3],
2023
               int delay_slot)
2024
{
2025
  if(!param[0])
2026
    return;
2027
 
2028
  if(!param[1] || !param[2]) {
2029
    clear_t[param_t[0]](opq, 1);
2030
    return;
2031
  }
2032
 
2033
  if(param_t[2] == T_NONE)
2034
    l_mul_imm_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
2035
  else
2036
    l_mul_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
2037
}
2038
 
2039
static const generic_gen_op l_mulu_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
2040
/* param0 -> t0 */              {
2041
/* param0 -> t0, param1 -> t0 */ { gen_op_mulu_t0_t0_t0, gen_op_mulu_t0_t0_t1, gen_op_mulu_t0_t0_t2 },
2042
/* param0 -> t0, param1 -> t1 */ { gen_op_mulu_t0_t1_t0, gen_op_mulu_t0_t1_t1, gen_op_mulu_t0_t1_t2 },
2043
/* param0 -> t0, param1 -> t2 */ { gen_op_mulu_t0_t2_t0, gen_op_mulu_t0_t2_t1, gen_op_mulu_t0_t2_t2 } },
2044
/* param0 -> t1 */              {
2045
/* param0 -> t1, param1 -> t0 */ { gen_op_mulu_t1_t0_t0, gen_op_mulu_t1_t0_t1, gen_op_mulu_t1_t0_t2 },
2046
/* param0 -> t1, param1 -> t1 */ { gen_op_mulu_t1_t1_t0, gen_op_mulu_t1_t1_t1, gen_op_mulu_t1_t1_t2 },
2047
/* param0 -> t1, param1 -> t2 */ { gen_op_mulu_t1_t2_t0, gen_op_mulu_t1_t2_t1, gen_op_mulu_t1_t2_t2 } },
2048
/* param0 -> t2 */              {
2049
/* param0 -> t2, param1 -> t0 */ { gen_op_mulu_t2_t0_t0, gen_op_mulu_t2_t0_t1, gen_op_mulu_t2_t0_t2 },
2050
/* param0 -> t2, param1 -> t1 */ { gen_op_mulu_t2_t1_t0, gen_op_mulu_t2_t1_t1, gen_op_mulu_t2_t1_t2 },
2051
/* param0 -> t2, param1 -> t2 */ { gen_op_mulu_t2_t2_t0, gen_op_mulu_t2_t2_t1, gen_op_mulu_t2_t2_t2 } } };
2052
 
2053
void gen_l_mulu(struct op_queue *opq, int param_t[3], orreg_t param[3],
2054
                int delay_slot)
2055
{
2056
  if(!param[0])
2057
    return;
2058
 
2059
  if(!param[1] || !param[2]) {
2060
    clear_t[param_t[0]](opq, 1);
2061
    return;
2062
  }
2063
 
2064
  l_mulu_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
2065
}
2066
 
2067
void gen_l_nop(struct op_queue *opq, int param_t[3], orreg_t param[3],
2068
               int delay_slot)
2069
{
2070
  /* Do parameter switch now */
2071
  switch (param[0]) {
2072
  case NOP_NOP:
2073
    break;
2074
  case NOP_EXIT:
2075
    gen_op_nop_exit(opq, 1);
2076
    break;
2077
  case NOP_CNT_RESET:
2078
    /* FIXME: Since op_nop_reset calls handle_except, this instruction wont show
2079
     * up in the execution log, nor will the scheduler run */
2080
    gen_op_nop_reset(opq, 1);
2081
    break;
2082
  case NOP_PRINTF:
2083
    gen_op_nop_printf(opq, 1);
2084
    break;
2085
  case NOP_REPORT:
2086
    gen_op_nop_report(opq, 1);
2087
    break;
2088
  default:
2089
    if((param[0] >= NOP_REPORT_FIRST) && (param[0] <= NOP_REPORT_LAST))
2090
      gen_op_nop_report_imm(opq, 1, param[0] - NOP_REPORT_FIRST);
2091
    break;
2092
  }
2093
}
2094
 
2095
static const imm_gen_op l_or_imm_t_table[NUM_T_REGS][NUM_T_REGS] = {
2096
/* param0 -> t0 */ { gen_op_or_imm_t0_t0, gen_op_or_imm_t0_t1, gen_op_or_imm_t0_t2 },
2097
/* param0 -> t1 */ { gen_op_or_imm_t1_t0, gen_op_or_imm_t1_t1, gen_op_or_imm_t1_t2 },
2098
/* param0 -> t2 */ { gen_op_or_imm_t2_t0, gen_op_or_imm_t2_t1, gen_op_or_imm_t2_t2 } };
2099
 
2100
static const generic_gen_op l_or_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
2101
/* param0 -> t0 */              {
2102
/* param0 -> t0, param1 -> t0 */ { NULL, gen_op_or_t0_t0_t1, gen_op_or_t0_t0_t2 },
2103
/* param0 -> t0, param1 -> t1 */ { gen_op_or_t0_t1_t0, gen_op_or_t0_t1_t1, gen_op_or_t0_t1_t2 },
2104
/* param0 -> t0, param1 -> t2 */ { gen_op_or_t0_t2_t0, gen_op_or_t0_t2_t1, gen_op_or_t0_t2_t2 } },
2105
/* param0 -> t1 */              {
2106
/* param0 -> t1, param1 -> t0 */ { gen_op_or_t1_t0_t0, gen_op_or_t1_t0_t1, gen_op_or_t1_t0_t2 },
2107
/* param0 -> t1, param1 -> t1 */ { gen_op_or_t1_t1_t0, NULL, gen_op_or_t1_t1_t2 },
2108
/* param0 -> t1, param1 -> t2 */ { gen_op_or_t1_t2_t0, gen_op_or_t1_t2_t1, gen_op_or_t1_t2_t2 } },
2109
/* param0 -> t2 */              {
2110
/* param0 -> t2, param1 -> t0 */ { gen_op_or_t2_t0_t0, gen_op_or_t2_t0_t1, gen_op_or_t2_t0_t2 },
2111
/* param0 -> t2, param1 -> t1 */ { gen_op_or_t2_t1_t0, gen_op_or_t2_t1_t1, gen_op_or_t2_t1_t2 },
2112
/* param0 -> t2, param1 -> t2 */ { gen_op_or_t2_t2_t0, gen_op_or_t2_t2_t1, NULL } } };
2113
 
2114
void gen_l_or(struct op_queue *opq, int param_t[3], orreg_t param[3],
2115
              int delay_slot)
2116
{
2117
  if(!param[0])
2118
    return;
2119
 
2120
  if((param[0] == param[1] == param[2]) && (param_t[2] != T_NONE))
2121
    return;
2122
 
2123
  if(!param[1] && !param[2]) {
2124
    clear_t[param_t[0]](opq, 1);
2125
    return;
2126
  }
2127
 
2128
  if(!param[2]) {
2129
    if((param_t[2] == T_NONE) && (param[0] == param[1]))
2130
      return;
2131
    move_t_t[param_t[0]][param_t[1]](opq, 1);
2132
    return;
2133
  }
2134
 
2135
  if(!param[1]) {
2136
    /* Check if we are moveing an immediate */
2137
    if(param_t[2] == T_NONE) {
2138
      /* Yep, an immediate */
2139
      mov_t_imm[param_t[0]](opq, 1, param[2]);
2140
      return;
2141
    }
2142
    /* Just another move */
2143
    move_t_t[param_t[0]][param_t[2]](opq, 1);
2144
    return;
2145
  }
2146
 
2147
  if(param_t[2] == T_NONE)
2148
    l_or_imm_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
2149
  else
2150
    l_or_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
2151
}
2152
 
2153
void gen_l_rfe(struct op_queue *opq, int param_t[3], orreg_t param[3],
2154
               int delay_slot)
2155
{
2156 1481 nogj
  if(do_stats)
2157
    gen_op_analysis(opq, 1, 12, 0x24000000);
2158
 
2159 1452 nogj
  gen_op_prep_rfe(opq, 1);
2160 1481 nogj
  gen_op_do_sched(opq, 1);
2161
  gen_op_do_jump(opq, 1);
2162 1452 nogj
}
2163
 
2164
/* FIXME: All store instructions should be optimised when the disposition = 0 */
2165
 
2166
static const imm_gen_op l_sb_clear_table[NUM_T_REGS] =
2167
 { gen_op_sb_clear_t0, gen_op_sb_clear_t1, gen_op_sb_clear_t2 };
2168
 
2169
static const imm_gen_op l_sb_imm_t_table[NUM_T_REGS] =
2170
 { gen_op_sb_imm_t0, gen_op_sb_imm_t1, gen_op_sb_imm_t2 };
2171
 
2172
static const imm_gen_op l_sb_t_table[NUM_T_REGS][NUM_T_REGS] = {
2173
/* param0 -> t0 */ { gen_op_sb_t0_t0, gen_op_sb_t0_t1, gen_op_sb_t0_t2 },
2174
/* param0 -> t1 */ { gen_op_sb_t1_t0, gen_op_sb_t1_t1, gen_op_sb_t1_t2 },
2175
/* param0 -> t2 */ { gen_op_sb_t2_t0, gen_op_sb_t2_t1, gen_op_sb_t2_t2 } };
2176
 
2177
void gen_l_sb(struct op_queue *opq, int param_t[3], orreg_t param[3],
2178
              int delay_slot)
2179
{
2180
  if(!param[2]) {
2181
    if(!param[1]) {
2182
      gen_op_sb_clear_imm(opq, 1, param[0]);
2183
      return;
2184
    }
2185
    l_sb_clear_table[param_t[1]](opq, 1, param[0]);
2186
    return;
2187
  }
2188
 
2189
  if(!param[1]) {
2190
    /* Store the data to the immediate */
2191
    l_sb_imm_t_table[param_t[2]](opq, 1, param[0]);
2192
    return;
2193
  }
2194
 
2195
  l_sb_t_table[param_t[1]][param_t[2]](opq, 1, param[0]);
2196
}
2197
 
2198
static const imm_gen_op l_sh_clear_table[NUM_T_REGS] =
2199
 { gen_op_sh_clear_t0, gen_op_sh_clear_t1, gen_op_sh_clear_t2 };
2200
 
2201
static const imm_gen_op l_sh_imm_t_table[NUM_T_REGS] =
2202
 { gen_op_sh_imm_t0, gen_op_sh_imm_t1, gen_op_sh_imm_t2 };
2203
 
2204
static const imm_gen_op l_sh_t_table[NUM_T_REGS][NUM_T_REGS] = {
2205
/* param0 -> t0 */ { gen_op_sh_t0_t0, gen_op_sh_t0_t1, gen_op_sh_t0_t2 },
2206
/* param0 -> t1 */ { gen_op_sh_t1_t0, gen_op_sh_t1_t1, gen_op_sh_t1_t2 },
2207
/* param0 -> t2 */ { gen_op_sh_t2_t0, gen_op_sh_t2_t1, gen_op_sh_t2_t2 } };
2208
 
2209
void gen_l_sh(struct op_queue *opq, int param_t[3], orreg_t param[3],
2210
              int delay_slot)
2211
{
2212
  if(!param[2]) {
2213
    if(!param[1]) {
2214
      gen_op_sh_clear_imm(opq, 1, param[0]);
2215
      return;
2216
    }
2217
    l_sh_clear_table[param_t[1]](opq, 1, param[0]);
2218
    return;
2219
  }
2220
 
2221
  if(!param[1]) {
2222
    /* Store the data to the immediate */
2223
    l_sh_imm_t_table[param_t[2]](opq, 1, param[0]);
2224
    return;
2225
  }
2226
 
2227
  l_sh_t_table[param_t[1]][param_t[2]](opq, 1, param[0]);
2228
}
2229
 
2230
static const imm_gen_op l_sw_clear_table[NUM_T_REGS] =
2231
 { gen_op_sw_clear_t0, gen_op_sw_clear_t1, gen_op_sw_clear_t2 };
2232
 
2233
static const imm_gen_op l_sw_imm_t_table[NUM_T_REGS] =
2234
 { gen_op_sw_imm_t0, gen_op_sw_imm_t1, gen_op_sw_imm_t2 };
2235
 
2236
static const imm_gen_op l_sw_t_table[NUM_T_REGS][NUM_T_REGS] = {
2237
/* param0 -> t0 */ { gen_op_sw_t0_t0, gen_op_sw_t0_t1, gen_op_sw_t0_t2 },
2238
/* param0 -> t1 */ { gen_op_sw_t1_t0, gen_op_sw_t1_t1, gen_op_sw_t1_t2 },
2239
/* param0 -> t2 */ { gen_op_sw_t2_t0, gen_op_sw_t2_t1, gen_op_sw_t2_t2 } };
2240
 
2241
void gen_l_sw(struct op_queue *opq, int param_t[3], orreg_t param[3],
2242
              int delay_slot)
2243
{
2244
  if(!param[2]) {
2245
    if(!param[1]) {
2246
      gen_op_sw_clear_imm(opq, 1, param[0]);
2247
      return;
2248
    }
2249
    l_sw_clear_table[param_t[1]](opq, 1, param[0]);
2250
    return;
2251
  }
2252
 
2253
  if(!param[1]) {
2254
    /* Store the data to the immediate */
2255
    l_sw_imm_t_table[param_t[2]](opq, 1, param[0]);
2256
    return;
2257
  }
2258
 
2259
  l_sw_t_table[param_t[1]][param_t[2]](opq, 1, param[0]);
2260
}
2261
 
2262
static const generic_gen_op l_sfeq_null_t_table[NUM_T_REGS] =
2263
 { gen_op_sfeq_null_t0, gen_op_sfeq_null_t1, gen_op_sfeq_null_t2 };
2264
 
2265
static const imm_gen_op l_sfeq_imm_t_table[NUM_T_REGS] =
2266
 { gen_op_sfeq_imm_t0, gen_op_sfeq_imm_t1, gen_op_sfeq_imm_t2 };
2267
 
2268
static const generic_gen_op l_sfeq_t_table[NUM_T_REGS][NUM_T_REGS] = {
2269
/* param0 -> t0 */ { gen_op_sfeq_t0_t0, gen_op_sfeq_t0_t1, gen_op_sfeq_t0_t2 },
2270
/* param0 -> t1 */ { gen_op_sfeq_t1_t0, gen_op_sfeq_t1_t1, gen_op_sfeq_t1_t2 },
2271
/* param0 -> t2 */ { gen_op_sfeq_t2_t0, gen_op_sfeq_t2_t1, gen_op_sfeq_t2_t2 } };
2272
 
2273
void gen_l_sfeq(struct op_queue *opq, int param_t[3], orreg_t param[3],
2274
                int delay_slot)
2275
{
2276
  if(!param[0] && !param[1]) {
2277
    gen_op_set_flag(opq, 1);
2278
    return;
2279
  }
2280
 
2281
  if(!param[0]) {
2282
    if(param_t[1] == T_NONE) {
2283
      if(!param[1])
2284
        gen_op_set_flag(opq, 1);
2285
      else
2286
        gen_op_clear_flag(opq, 1);
2287
    } else
2288
      l_sfeq_null_t_table[param_t[1]](opq, 1);
2289
    return;
2290
  }
2291
 
2292
  if(!param[1]) {
2293
    l_sfeq_null_t_table[param_t[0]](opq, 1);
2294
    return;
2295
  }
2296
 
2297
  if(param_t[1] == T_NONE)
2298
    l_sfeq_imm_t_table[param_t[0]](opq, 1, param[1]);
2299
  else
2300
    l_sfeq_t_table[param_t[0]][param_t[1]](opq, 1);
2301
}
2302
 
2303
static const generic_gen_op l_sfges_null_t_table[NUM_T_REGS] =
2304
 { gen_op_sfges_null_t0, gen_op_sfges_null_t1, gen_op_sfges_null_t2 };
2305
 
2306
static const generic_gen_op l_sfles_null_t_table[NUM_T_REGS] =
2307
 { gen_op_sfles_null_t0, gen_op_sfles_null_t1, gen_op_sfles_null_t2 };
2308
 
2309
static const imm_gen_op l_sfges_imm_t_table[NUM_T_REGS] =
2310
 { gen_op_sfges_imm_t0, gen_op_sfges_imm_t1, gen_op_sfges_imm_t2 };
2311
 
2312
static const generic_gen_op l_sfges_t_table[NUM_T_REGS][NUM_T_REGS] = {
2313
/* param0 -> t0 */ { gen_op_sfges_t0_t0, gen_op_sfges_t0_t1, gen_op_sfges_t0_t2 },
2314
/* param0 -> t1 */ { gen_op_sfges_t1_t0, gen_op_sfges_t1_t1, gen_op_sfges_t1_t2 },
2315
/* param0 -> t2 */ { gen_op_sfges_t2_t0, gen_op_sfges_t2_t1, gen_op_sfges_t2_t2 } };
2316
 
2317
void gen_l_sfges(struct op_queue *opq, int param_t[3], orreg_t param[3],
2318
                 int delay_slot)
2319
{
2320
  if(!param[0] && !param[1]) {
2321
    gen_op_set_flag(opq, 1);
2322
    return;
2323
  }
2324
 
2325
  if(!param[0]) {
2326
    /* sfles IS correct */
2327
    if(param_t[1] == T_NONE) {
2328
      if(0 >= (orreg_t)param[1])
2329
        gen_op_set_flag(opq, 1);
2330
      else
2331
        gen_op_clear_flag(opq, 1);
2332
    } else
2333
      l_sfles_null_t_table[param_t[1]](opq, 1);
2334
    return;
2335
  }
2336
 
2337
  if(!param[1]) {
2338
    l_sfges_null_t_table[param_t[0]](opq, 1);
2339
    return;
2340
  }
2341
 
2342
  if(param_t[1] == T_NONE)
2343
    l_sfges_imm_t_table[param_t[0]](opq, 1, param[1]);
2344
  else
2345
    l_sfges_t_table[param_t[0]][param_t[1]](opq, 1);
2346
}
2347
 
2348
static const generic_gen_op l_sfgeu_null_t_table[NUM_T_REGS] =
2349
 { gen_op_sfgeu_null_t0, gen_op_sfgeu_null_t1, gen_op_sfgeu_null_t2 };
2350
 
2351
static const generic_gen_op l_sfleu_null_t_table[NUM_T_REGS] =
2352
 { gen_op_sfleu_null_t0, gen_op_sfleu_null_t1, gen_op_sfleu_null_t2 };
2353
 
2354
static const imm_gen_op l_sfgeu_imm_t_table[NUM_T_REGS] =
2355
 { gen_op_sfgeu_imm_t0, gen_op_sfgeu_imm_t1, gen_op_sfgeu_imm_t2 };
2356
 
2357
static const generic_gen_op l_sfgeu_t_table[NUM_T_REGS][NUM_T_REGS] = {
2358
/* param0 -> t0 */ { gen_op_sfgeu_t0_t0, gen_op_sfgeu_t0_t1, gen_op_sfgeu_t0_t2 },
2359
/* param0 -> t1 */ { gen_op_sfgeu_t1_t0, gen_op_sfgeu_t1_t1, gen_op_sfgeu_t1_t2 },
2360
/* param0 -> t2 */ { gen_op_sfgeu_t2_t0, gen_op_sfgeu_t2_t1, gen_op_sfgeu_t2_t2 } };
2361
 
2362
void gen_l_sfgeu(struct op_queue *opq, int param_t[3], orreg_t param[3],
2363
                 int delay_slot)
2364
{
2365
  if(!param[0] && !param[1]) {
2366
    gen_op_set_flag(opq, 1);
2367
    return;
2368
  }
2369
 
2370
  if(!param[0]) {
2371
    /* sfleu IS correct */
2372
    if(param_t[1] == T_NONE) {
2373
      if(0 >= param[1])
2374
        gen_op_set_flag(opq, 1);
2375
      else
2376
        gen_op_clear_flag(opq, 1);
2377
    } else
2378
      l_sfleu_null_t_table[param_t[1]](opq, 1);
2379
    return;
2380
  }
2381
 
2382
  if(!param[1]) {
2383
    l_sfgeu_null_t_table[param_t[0]](opq, 1);
2384
    return;
2385
  }
2386
  if(param_t[1] == T_NONE)
2387
    l_sfgeu_imm_t_table[param_t[0]](opq, 1, param[1]);
2388
  else
2389
    l_sfgeu_t_table[param_t[0]][param_t[1]](opq, 1);
2390
}
2391
 
2392
static const generic_gen_op l_sfgts_null_t_table[NUM_T_REGS] =
2393
 { gen_op_sfgts_null_t0, gen_op_sfgts_null_t1, gen_op_sfgts_null_t2 };
2394
 
2395
static const generic_gen_op l_sflts_null_t_table[NUM_T_REGS] =
2396
 { gen_op_sflts_null_t0, gen_op_sflts_null_t1, gen_op_sflts_null_t2 };
2397
 
2398
static const imm_gen_op l_sfgts_imm_t_table[NUM_T_REGS] =
2399
 { gen_op_sfgts_imm_t0, gen_op_sfgts_imm_t1, gen_op_sfgts_imm_t2 };
2400
 
2401
static const generic_gen_op l_sfgts_t_table[NUM_T_REGS][NUM_T_REGS] = {
2402
/* param0 -> t0 */ { gen_op_sfgts_t0_t0, gen_op_sfgts_t0_t1, gen_op_sfgts_t0_t2 },
2403
/* param0 -> t1 */ { gen_op_sfgts_t1_t0, gen_op_sfgts_t1_t1, gen_op_sfgts_t1_t2 },
2404
/* param0 -> t2 */ { gen_op_sfgts_t2_t0, gen_op_sfgts_t2_t1, gen_op_sfgts_t2_t2 } };
2405
 
2406
void gen_l_sfgts(struct op_queue *opq, int param_t[3], orreg_t param[3],
2407
                 int delay_slot)
2408
{
2409
  if(!param[0] && !param[1]) {
2410
    gen_op_clear_flag(opq, 1);
2411
    return;
2412
  }
2413
 
2414
  if(!param[0]) {
2415
    /* sflts IS correct */
2416
    if(param_t[1] == T_NONE) {
2417
      if(0 > (orreg_t)param[1])
2418
        gen_op_set_flag(opq, 1);
2419
      else
2420
        gen_op_clear_flag(opq, 1);
2421
    } else
2422
      l_sflts_null_t_table[param_t[1]](opq, 1);
2423
    return;
2424
  }
2425
 
2426
  if(!param[1]) {
2427
    l_sfgts_null_t_table[param_t[0]](opq, 1);
2428
    return;
2429
  }
2430
 
2431
  if(param_t[1] == T_NONE)
2432
    l_sfgts_imm_t_table[param_t[0]](opq, 1, param[1]);
2433
  else
2434
    l_sfgts_t_table[param_t[0]][param_t[1]](opq, 1);
2435
}
2436
 
2437
static const generic_gen_op l_sfgtu_null_t_table[NUM_T_REGS] =
2438
 { gen_op_sfgtu_null_t0, gen_op_sfgtu_null_t1, gen_op_sfgtu_null_t2 };
2439
 
2440
static const generic_gen_op l_sfltu_null_t_table[NUM_T_REGS] =
2441
 { gen_op_sfltu_null_t0, gen_op_sfltu_null_t1, gen_op_sfltu_null_t2 };
2442
 
2443
static const imm_gen_op l_sfgtu_imm_t_table[NUM_T_REGS] =
2444
 { gen_op_sfgtu_imm_t0, gen_op_sfgtu_imm_t1, gen_op_sfgtu_imm_t2 };
2445
 
2446
static const generic_gen_op l_sfgtu_t_table[NUM_T_REGS][NUM_T_REGS] = {
2447
/* param0 -> t0 */ { gen_op_sfgtu_t0_t0, gen_op_sfgtu_t0_t1, gen_op_sfgtu_t0_t2 },
2448
/* param0 -> t1 */ { gen_op_sfgtu_t1_t0, gen_op_sfgtu_t1_t1, gen_op_sfgtu_t1_t2 },
2449
/* param0 -> t2 */ { gen_op_sfgtu_t2_t0, gen_op_sfgtu_t2_t1, gen_op_sfgtu_t2_t2 } };
2450
 
2451
void gen_l_sfgtu(struct op_queue *opq, int param_t[3], orreg_t param[3],
2452
                 int delay_slot)
2453
{
2454
  if(!param[0] && !param[1]) {
2455
    gen_op_clear_flag(opq, 1);
2456
    return;
2457
  }
2458
 
2459
  if(!param[0]) {
2460
    /* sfltu IS correct */
2461
    if(param_t[1] == T_NONE) {
2462
      if(0 > param[1])
2463
        gen_op_set_flag(opq, 1);
2464
      else
2465
        gen_op_clear_flag(opq, 1);
2466
    } else
2467
      l_sfltu_null_t_table[param_t[1]](opq, 1);
2468
    return;
2469
  }
2470
 
2471
  if(!param[1]) {
2472
    l_sfgtu_null_t_table[param_t[0]](opq, 1);
2473
    return;
2474
  }
2475
 
2476
  if(param_t[1] == T_NONE)
2477
    l_sfgtu_imm_t_table[param_t[0]](opq, 1, param[1]);
2478
  else
2479
    l_sfgtu_t_table[param_t[0]][param_t[1]](opq, 1);
2480
}
2481
 
2482
static const imm_gen_op l_sfles_imm_t_table[NUM_T_REGS] =
2483
 { gen_op_sfles_imm_t0, gen_op_sfles_imm_t1, gen_op_sfles_imm_t2 };
2484
 
2485
static const generic_gen_op l_sfles_t_table[NUM_T_REGS][NUM_T_REGS] = {
2486
/* param0 -> t0 */ { gen_op_sfles_t0_t0, gen_op_sfles_t0_t1, gen_op_sfles_t0_t2 },
2487
/* param0 -> t1 */ { gen_op_sfles_t1_t0, gen_op_sfles_t1_t1, gen_op_sfles_t1_t2 },
2488
/* param0 -> t2 */ { gen_op_sfles_t2_t0, gen_op_sfles_t2_t1, gen_op_sfles_t2_t2 } };
2489
 
2490
void gen_l_sfles(struct op_queue *opq, int param_t[3], orreg_t param[3],
2491
                 int delay_slot)
2492
{
2493
  if(!param[0] && !param[1]) {
2494
    gen_op_set_flag(opq, 1);
2495
    return;
2496
  }
2497
 
2498
  if(!param[0]) {
2499
    /* sfges IS correct */
2500
    if(param_t[1] == T_NONE) {
2501
      if(0 <= (orreg_t)param[1])
2502
        gen_op_set_flag(opq, 1);
2503
      else
2504
        gen_op_clear_flag(opq, 1);
2505
    } else
2506
      l_sfges_null_t_table[param_t[1]](opq, 1);
2507
    return;
2508
  }
2509
 
2510
  if(!param[1]) {
2511
    l_sfles_null_t_table[param_t[0]](opq, 1);
2512
    return;
2513
  }
2514
 
2515
  if(param_t[1] == T_NONE)
2516
    l_sfles_imm_t_table[param_t[0]](opq, 1, param[1]);
2517
  else
2518
    l_sfles_t_table[param_t[0]][param_t[1]](opq, 1);
2519
}
2520
 
2521
static const imm_gen_op l_sfleu_imm_t_table[NUM_T_REGS] =
2522
 { gen_op_sfleu_imm_t0, gen_op_sfleu_imm_t1, gen_op_sfleu_imm_t2 };
2523
 
2524
static const generic_gen_op l_sfleu_t_table[NUM_T_REGS][NUM_T_REGS] = {
2525
/* param0 -> t0 */ { gen_op_sfleu_t0_t0, gen_op_sfleu_t0_t1, gen_op_sfleu_t0_t2 },
2526
/* param0 -> t1 */ { gen_op_sfleu_t1_t0, gen_op_sfleu_t1_t1, gen_op_sfleu_t1_t2 },
2527
/* param0 -> t2 */ { gen_op_sfleu_t2_t0, gen_op_sfleu_t2_t1, gen_op_sfleu_t2_t2 } };
2528
 
2529
void gen_l_sfleu(struct op_queue *opq, int param_t[3], orreg_t param[3],
2530
                 int delay_slot)
2531
{
2532
  if(!param[0] && !param[1]) {
2533
    gen_op_set_flag(opq, 1);
2534
    return;
2535
  }
2536
 
2537
  if(!param[0]) {
2538
    /* sfleu IS correct */
2539
    if(param_t[1] == T_NONE) {
2540
      if(0 <= param[1])
2541
        gen_op_set_flag(opq, 1);
2542
      else
2543
        gen_op_clear_flag(opq, 1);
2544
    } else
2545
      l_sfgeu_null_t_table[param_t[1]](opq, 1);
2546
    return;
2547
  }
2548
 
2549
  if(!param[1]) {
2550
    l_sfleu_null_t_table[param_t[0]](opq, 1);
2551
    return;
2552
  }
2553
 
2554
  if(param_t[1] == T_NONE)
2555
    l_sfleu_imm_t_table[param_t[0]](opq, 1, param[1]);
2556
  else
2557
    l_sfleu_t_table[param_t[0]][param_t[1]](opq, 1);
2558
}
2559
 
2560
static const imm_gen_op l_sflts_imm_t_table[NUM_T_REGS] =
2561
 { gen_op_sflts_imm_t0, gen_op_sflts_imm_t1, gen_op_sflts_imm_t2 };
2562
 
2563
static const generic_gen_op l_sflts_t_table[NUM_T_REGS][NUM_T_REGS] = {
2564
/* param0 -> t0 */ { gen_op_sflts_t0_t0, gen_op_sflts_t0_t1, gen_op_sflts_t0_t2 },
2565
/* param0 -> t1 */ { gen_op_sflts_t1_t0, gen_op_sflts_t1_t1, gen_op_sflts_t1_t2 },
2566
/* param0 -> t2 */ { gen_op_sflts_t2_t0, gen_op_sflts_t2_t1, gen_op_sflts_t2_t2 } };
2567
 
2568
void gen_l_sflts(struct op_queue *opq, int param_t[3], orreg_t param[3],
2569
                 int delay_slot)
2570
{
2571
  if(!param[0] && !param[1]) {
2572
    gen_op_clear_flag(opq, 1);
2573
    return;
2574
  }
2575
 
2576
  if(!param[0]) {
2577
    /* sfgts IS correct */
2578
    if(param_t[1] == T_NONE) {
2579
      if(0 < (orreg_t)param[1])
2580
        gen_op_set_flag(opq, 1);
2581
      else
2582
        gen_op_clear_flag(opq, 1);
2583
    } else
2584
      l_sfgts_null_t_table[param_t[1]](opq, 1);
2585
    return;
2586
  }
2587
 
2588
  if(!param[1]) {
2589
    l_sflts_null_t_table[param_t[0]](opq, 1);
2590
    return;
2591
  }
2592
 
2593
  if(param_t[1] == T_NONE)
2594
    l_sflts_imm_t_table[param_t[0]](opq, 1, param[1]);
2595
  else
2596
    l_sflts_t_table[param_t[0]][param_t[1]](opq, 1);
2597
}
2598
 
2599
static const imm_gen_op l_sfltu_imm_t_table[NUM_T_REGS] =
2600
 { gen_op_sfltu_imm_t0, gen_op_sfltu_imm_t1, gen_op_sfltu_imm_t2 };
2601
 
2602
static const generic_gen_op l_sfltu_t_table[NUM_T_REGS][NUM_T_REGS] = {
2603
/* param0 -> t0 */ { gen_op_sfltu_t0_t0, gen_op_sfltu_t0_t1, gen_op_sfltu_t0_t2 },
2604
/* param0 -> t1 */ { gen_op_sfltu_t1_t0, gen_op_sfltu_t1_t1, gen_op_sfltu_t1_t2 },
2605
/* param0 -> t2 */ { gen_op_sfltu_t2_t0, gen_op_sfltu_t2_t1, gen_op_sfltu_t2_t2 } };
2606
 
2607
void gen_l_sfltu(struct op_queue *opq, int param_t[3], orreg_t param[3],
2608
                 int delay_slot)
2609
{
2610
  if(!param[0] && !param[1]) {
2611
    gen_op_clear_flag(opq, 1);
2612
    return;
2613
  }
2614
 
2615
  if(!param[0]) {
2616
    /* sfgtu IS correct */
2617
    if(param_t[1] == T_NONE) {
2618
      if(0 < param[1])
2619
        gen_op_set_flag(opq, 1);
2620
      else
2621
        gen_op_clear_flag(opq, 1);
2622
    } else
2623
      l_sfgtu_null_t_table[param_t[1]](opq, 1);
2624
    return;
2625
  }
2626
 
2627
  if(!param[1]) {
2628
    l_sfltu_null_t_table[param_t[0]](opq, 1);
2629
    return;
2630
  }
2631
 
2632
  if(param_t[1] == T_NONE)
2633
    l_sfltu_imm_t_table[param_t[0]](opq, 1, param[1]);
2634
  else
2635
    l_sfltu_t_table[param_t[0]][param_t[1]](opq, 1);
2636
}
2637
 
2638
static const generic_gen_op l_sfne_null_t_table[NUM_T_REGS] =
2639
 { gen_op_sfne_null_t0, gen_op_sfne_null_t1, gen_op_sfne_null_t2 };
2640
 
2641
static const imm_gen_op l_sfne_imm_t_table[NUM_T_REGS] =
2642
 { gen_op_sfne_imm_t0, gen_op_sfne_imm_t1, gen_op_sfne_imm_t2 };
2643
 
2644
static const generic_gen_op l_sfne_t_table[NUM_T_REGS][NUM_T_REGS] = {
2645
/* param0 -> t0 */ { gen_op_sfne_t0_t0, gen_op_sfne_t0_t1, gen_op_sfne_t0_t2 },
2646
/* param0 -> t1 */ { gen_op_sfne_t1_t0, gen_op_sfne_t1_t1, gen_op_sfne_t1_t2 },
2647
/* param0 -> t2 */ { gen_op_sfne_t2_t0, gen_op_sfne_t2_t1, gen_op_sfne_t2_t2 } };
2648
 
2649
void gen_l_sfne(struct op_queue *opq, int param_t[3], orreg_t param[3],
2650
                int delay_slot)
2651
{
2652
  if(!param[0] && !param[1]) {
2653
    gen_op_set_flag(opq, 1);
2654
    return;
2655
  }
2656
 
2657
  if(!param[0]) {
2658
    if(param_t[1] == T_NONE)
2659
      if(param[1])
2660
        gen_op_set_flag(opq, 1);
2661
      else
2662
        gen_op_clear_flag(opq, 1);
2663
    else
2664
      l_sfne_null_t_table[param_t[1]](opq, 1);
2665
    return;
2666
  }
2667
 
2668
  if(!param[1]) {
2669
    l_sfne_null_t_table[param_t[0]](opq, 1);
2670
    return;
2671
  }
2672
 
2673
  if(param_t[1] == T_NONE)
2674
    l_sfne_imm_t_table[param_t[0]](opq, 1, param[1]);
2675
  else
2676
    l_sfne_t_table[param_t[0]][param_t[1]](opq, 1);
2677
}
2678
 
2679
static const imm_gen_op l_sll_imm_t_table[NUM_T_REGS][NUM_T_REGS] = {
2680
/* param0 -> t0 */ { gen_op_sll_imm_t0_t0, gen_op_sll_imm_t0_t1, gen_op_sll_imm_t0_t2 },
2681
/* param0 -> t1 */ { gen_op_sll_imm_t1_t0, gen_op_sll_imm_t1_t1, gen_op_sll_imm_t1_t2 },
2682
/* param0 -> t2 */ { gen_op_sll_imm_t2_t0, gen_op_sll_imm_t2_t1, gen_op_sll_imm_t2_t2 } };
2683
 
2684
static const generic_gen_op l_sll_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
2685
/* param0 -> t0 */              {
2686
/* param0 -> t0, param1 -> t0 */ { gen_op_sll_t0_t0_t0, gen_op_sll_t0_t0_t1, gen_op_sll_t0_t0_t2 },
2687
/* param0 -> t0, param1 -> t1 */ { gen_op_sll_t0_t1_t0, gen_op_sll_t0_t1_t1, gen_op_sll_t0_t1_t2 },
2688
/* param0 -> t0, param1 -> t2 */ { gen_op_sll_t0_t2_t0, gen_op_sll_t0_t2_t1, gen_op_sll_t0_t2_t2 } },
2689
/* param0 -> t1 */              {
2690
/* param0 -> t1, param1 -> t0 */ { gen_op_sll_t1_t0_t0, gen_op_sll_t1_t0_t1, gen_op_sll_t1_t0_t2 },
2691
/* param0 -> t1, param1 -> t1 */ { gen_op_sll_t1_t1_t0, gen_op_sll_t1_t1_t1, gen_op_sll_t1_t1_t2 },
2692
/* param0 -> t1, param1 -> t2 */ { gen_op_sll_t1_t2_t0, gen_op_sll_t1_t2_t1, gen_op_sll_t1_t2_t2 } },
2693
/* param0 -> t2 */              {
2694
/* param0 -> t2, param1 -> t0 */ { gen_op_sll_t2_t0_t0, gen_op_sll_t2_t0_t1, gen_op_sll_t2_t0_t2 },
2695
/* param0 -> t2, param1 -> t1 */ { gen_op_sll_t2_t1_t0, gen_op_sll_t2_t1_t1, gen_op_sll_t2_t1_t2 },
2696
/* param0 -> t2, param1 -> t2 */ { gen_op_sll_t2_t2_t0, gen_op_sll_t2_t2_t1, gen_op_sll_t2_t2_t2 } } };
2697
 
2698
void gen_l_sll(struct op_queue *opq, int param_t[3], orreg_t param[3],
2699
               int delay_slot)
2700
{
2701
  if(!param[0])
2702
    return;
2703
 
2704
  if(!param[1]) {
2705
    clear_t[param_t[0]](opq, 1);
2706
    return;
2707
  }
2708
 
2709
  if(!param[2]) {
2710
    move_t_t[param_t[0]][param_t[1]](opq, 1);
2711
    return;
2712
  }
2713
 
2714
  if(param_t[2] == T_NONE)
2715
    l_sll_imm_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
2716
  else
2717
    l_sll_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
2718
}
2719
 
2720
static const imm_gen_op l_sra_imm_t_table[NUM_T_REGS][NUM_T_REGS] = {
2721
/* param0 -> t0 */ { gen_op_sra_imm_t0_t0, gen_op_sra_imm_t0_t1, gen_op_sra_imm_t0_t2 },
2722
/* param0 -> t1 */ { gen_op_sra_imm_t1_t0, gen_op_sra_imm_t1_t1, gen_op_sra_imm_t1_t2 },
2723
/* param0 -> t2 */ { gen_op_sra_imm_t2_t0, gen_op_sra_imm_t2_t1, gen_op_sra_imm_t2_t2 } };
2724
 
2725
static const generic_gen_op l_sra_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
2726
/* param0 -> t0 */              {
2727
/* param0 -> t0, param1 -> t0 */ { gen_op_sra_t0_t0_t0, gen_op_sra_t0_t0_t1, gen_op_sra_t0_t0_t2 },
2728
/* param0 -> t0, param1 -> t1 */ { gen_op_sra_t0_t1_t0, gen_op_sra_t0_t1_t1, gen_op_sra_t0_t1_t2 },
2729
/* param0 -> t0, param1 -> t2 */ { gen_op_sra_t0_t2_t0, gen_op_sra_t0_t2_t1, gen_op_sra_t0_t2_t2 } },
2730
/* param0 -> t1 */              {
2731
/* param0 -> t1, param1 -> t0 */ { gen_op_sra_t1_t0_t0, gen_op_sra_t1_t0_t1, gen_op_sra_t1_t0_t2 },
2732
/* param0 -> t1, param1 -> t1 */ { gen_op_sra_t1_t1_t0, gen_op_sra_t1_t1_t1, gen_op_sra_t1_t1_t2 },
2733
/* param0 -> t1, param1 -> t2 */ { gen_op_sra_t1_t2_t0, gen_op_sra_t1_t2_t1, gen_op_sra_t1_t2_t2 } },
2734
/* param0 -> t2 */              {
2735
/* param0 -> t2, param1 -> t0 */ { gen_op_sra_t2_t0_t0, gen_op_sra_t2_t0_t1, gen_op_sra_t2_t0_t2 },
2736
/* param0 -> t2, param1 -> t1 */ { gen_op_sra_t2_t1_t0, gen_op_sra_t2_t1_t1, gen_op_sra_t2_t1_t2 },
2737
/* param0 -> t2, param1 -> t2 */ { gen_op_sra_t2_t2_t0, gen_op_sra_t2_t2_t1, gen_op_sra_t2_t2_t2 } } };
2738
 
2739
void gen_l_sra(struct op_queue *opq, int param_t[3], orreg_t param[3],
2740
               int delay_slot)
2741
{
2742
  if(!param[0])
2743
    return;
2744
 
2745
  if(!param[1]) {
2746
    clear_t[param_t[0]](opq, 1);
2747
    return;
2748
  }
2749
 
2750
  if(!param[2]) {
2751
    move_t_t[param_t[0]][param_t[1]](opq, 1);
2752
    return;
2753
  }
2754
 
2755
  if(param_t[2] == T_NONE)
2756
    l_sra_imm_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
2757
  else
2758
    l_sra_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
2759
}
2760
 
2761
static const imm_gen_op l_srl_imm_t_table[NUM_T_REGS][NUM_T_REGS] = {
2762
/* param0 -> t0 */ { gen_op_srl_imm_t0_t0, gen_op_srl_imm_t0_t1, gen_op_srl_imm_t0_t2 },
2763
/* param0 -> t1 */ { gen_op_srl_imm_t1_t0, gen_op_srl_imm_t1_t1, gen_op_srl_imm_t1_t2 },
2764
/* param0 -> t2 */ { gen_op_srl_imm_t2_t0, gen_op_srl_imm_t2_t1, gen_op_srl_imm_t2_t2 } };
2765
 
2766
static const generic_gen_op l_srl_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
2767
/* param0 -> t0 */              {
2768
/* param0 -> t0, param1 -> t0 */ { gen_op_srl_t0_t0_t0, gen_op_srl_t0_t0_t1, gen_op_srl_t0_t0_t2 },
2769
/* param0 -> t0, param1 -> t1 */ { gen_op_srl_t0_t1_t0, gen_op_srl_t0_t1_t1, gen_op_srl_t0_t1_t2 },
2770
/* param0 -> t0, param1 -> t2 */ { gen_op_srl_t0_t2_t0, gen_op_srl_t0_t2_t1, gen_op_srl_t0_t2_t2 } },
2771
/* param0 -> t1 */              {
2772
/* param0 -> t1, param1 -> t0 */ { gen_op_srl_t1_t0_t0, gen_op_srl_t1_t0_t1, gen_op_srl_t1_t0_t2 },
2773
/* param0 -> t1, param1 -> t1 */ { gen_op_srl_t1_t1_t0, gen_op_srl_t1_t1_t1, gen_op_srl_t1_t1_t2 },
2774
/* param0 -> t1, param1 -> t2 */ { gen_op_srl_t1_t2_t0, gen_op_srl_t1_t2_t1, gen_op_srl_t1_t2_t2 } },
2775
/* param0 -> t2 */              {
2776
/* param0 -> t2, param1 -> t0 */ { gen_op_srl_t2_t0_t0, gen_op_srl_t2_t0_t1, gen_op_srl_t2_t0_t2 },
2777
/* param0 -> t2, param1 -> t1 */ { gen_op_srl_t2_t1_t0, gen_op_srl_t2_t1_t1, gen_op_srl_t2_t1_t2 },
2778
/* param0 -> t2, param1 -> t2 */ { gen_op_srl_t2_t2_t0, gen_op_srl_t2_t2_t1, gen_op_srl_t2_t2_t2 } } };
2779
 
2780
void gen_l_srl(struct op_queue *opq, int param_t[3], orreg_t param[3],
2781
               int delay_slot)
2782
{
2783
  if(!param[0])
2784
    return;
2785
 
2786
  if(!param[1]) {
2787
    clear_t[param_t[0]](opq, 1);
2788
    return;
2789
  }
2790
 
2791
  if(!param[2]) {
2792
    move_t_t[param_t[0]][param_t[1]](opq, 1);
2793
    return;
2794
  }
2795
 
2796
  if(param_t[2] == T_NONE)
2797
    l_srl_imm_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
2798
  else
2799
    l_srl_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
2800
}
2801
 
2802
static const generic_gen_op l_neg_t_table[NUM_T_REGS][NUM_T_REGS] = {
2803
/* param0 -> t0 */ { gen_op_neg_t0_t0, gen_op_neg_t0_t1, gen_op_neg_t0_t2 },
2804
/* param0 -> t1 */ { gen_op_neg_t1_t0, gen_op_neg_t1_t1, gen_op_neg_t1_t2 },
2805
/* param0 -> t2 */ { gen_op_neg_t2_t0, gen_op_neg_t2_t1, gen_op_neg_t2_t2 } };
2806
 
2807
static const generic_gen_op l_sub_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
2808
/* param0 -> t0 */              {
2809
/* param0 -> t0, param1 -> t0 */ { gen_op_sub_t0_t0_t0, gen_op_sub_t0_t0_t1, gen_op_sub_t0_t0_t2 },
2810
/* param0 -> t0, param1 -> t1 */ { gen_op_sub_t0_t1_t0, gen_op_sub_t0_t1_t1, gen_op_sub_t0_t1_t2 },
2811
/* param0 -> t0, param1 -> t2 */ { gen_op_sub_t0_t2_t0, gen_op_sub_t0_t2_t1, gen_op_sub_t0_t2_t2 } },
2812
/* param0 -> t1 */              {
2813
/* param0 -> t1, param1 -> t0 */ { gen_op_sub_t1_t0_t0, gen_op_sub_t1_t0_t1, gen_op_sub_t1_t0_t2 },
2814
/* param0 -> t1, param1 -> t1 */ { gen_op_sub_t1_t1_t0, gen_op_sub_t1_t1_t1, gen_op_sub_t1_t1_t2 },
2815
/* param0 -> t1, param1 -> t2 */ { gen_op_sub_t1_t2_t0, gen_op_sub_t1_t2_t1, gen_op_sub_t1_t2_t2 } },
2816
/* param0 -> t2 */              {
2817
/* param0 -> t2, param1 -> t0 */ { gen_op_sub_t2_t0_t0, gen_op_sub_t2_t0_t1, gen_op_sub_t2_t0_t2 },
2818
/* param0 -> t2, param1 -> t1 */ { gen_op_sub_t2_t1_t0, gen_op_sub_t2_t1_t1, gen_op_sub_t2_t1_t2 },
2819
/* param0 -> t2, param1 -> t2 */ { gen_op_sub_t2_t2_t0, gen_op_sub_t2_t2_t1, gen_op_sub_t2_t2_t2 } } };
2820
 
2821
void gen_l_sub(struct op_queue *opq, int param_t[3], orreg_t param[3],
2822
               int delay_slot)
2823
{
2824
  if(!param[0])
2825
    return;
2826
 
2827
  if((param_t[2] != T_NONE) && (param[1] == param[2])) {
2828
    clear_t[param_t[0]](opq, 1);
2829
    return;
2830
  }
2831
 
2832
  if(!param[1] && !param[2]) {
2833
    clear_t[param_t[0]](opq, 1);
2834
    return;
2835
  }
2836
 
2837
  if(!param[1]) {
2838
    if(param_t[2] == T_NONE)
2839
      mov_t_imm[param_t[0]](opq, 1, -param[2]);
2840
    else
2841
      l_neg_t_table[param_t[0]][param_t[2]](opq, 1);
2842
    return;
2843
  }
2844
 
2845
  if(!param[2]) {
2846
    move_t_t[param_t[0]][param_t[1]](opq, 1);
2847
    return;
2848
  }
2849
 
2850
  l_sub_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
2851
}
2852
 
2853
/* FIXME: This will not work if the l.sys is in a delay slot */
2854
void gen_l_sys(struct op_queue *opq, int param_t[3], orreg_t param[3],
2855
               int delay_slot)
2856
{
2857 1481 nogj
  if(do_stats)
2858
    gen_op_analysis(opq, 1, 7, 0x20000000 | param[0]);
2859 1452 nogj
 
2860
  if(!delay_slot)
2861
    gen_op_prep_sys(opq, 1);
2862
  else
2863
    gen_op_prep_sys_delay(opq, 1);
2864 1481 nogj
 
2865
  gen_op_do_sched(opq, 1);
2866
  gen_op_do_jump(opq, 1);
2867 1452 nogj
}
2868
 
2869
/* FIXME: This will not work if the l.trap is in a delay slot */
2870
void gen_l_trap(struct op_queue *opq, int param_t[3], orreg_t param[3],
2871
                int delay_slot)
2872
{
2873 1481 nogj
  if(do_stats)
2874
    gen_op_analysis(opq, 1, 8, 0x22000000);
2875 1452 nogj
 
2876
  if(!delay_slot)
2877
    gen_op_prep_trap(opq, 1);
2878
  else
2879
    gen_op_prep_trap_delay(opq, 1);
2880
}
2881
 
2882
static const imm_gen_op l_xor_imm_t_table[NUM_T_REGS][NUM_T_REGS] = {
2883
/* param0 -> t0 */ { gen_op_xor_imm_t0_t0, gen_op_xor_imm_t0_t1, gen_op_xor_imm_t0_t2 },
2884
/* param0 -> t1 */ { gen_op_xor_imm_t1_t0, gen_op_xor_imm_t1_t1, gen_op_xor_imm_t1_t2 },
2885
/* param0 -> t2 */ { gen_op_xor_imm_t2_t0, gen_op_xor_imm_t2_t1, gen_op_xor_imm_t2_t2 } };
2886
 
2887
static const generic_gen_op l_xor_t_table[NUM_T_REGS][NUM_T_REGS][NUM_T_REGS] = {
2888
/* param0 -> t0 */              {
2889
/* param0 -> t0, param1 -> t0 */ { gen_op_xor_t0_t0_t0, gen_op_xor_t0_t0_t1, gen_op_xor_t0_t0_t2 },
2890
/* param0 -> t0, param1 -> t1 */ { gen_op_xor_t0_t1_t0, gen_op_xor_t0_t1_t1, gen_op_xor_t0_t1_t2 },
2891
/* param0 -> t0, param1 -> t2 */ { gen_op_xor_t0_t2_t0, gen_op_xor_t0_t2_t1, gen_op_xor_t0_t2_t2 } },
2892
/* param0 -> t1 */              {
2893
/* param0 -> t1, param1 -> t0 */ { gen_op_xor_t1_t0_t0, gen_op_xor_t1_t0_t1, gen_op_xor_t1_t0_t2 },
2894
/* param0 -> t1, param1 -> t1 */ { gen_op_xor_t1_t1_t0, gen_op_xor_t1_t1_t1, gen_op_xor_t1_t1_t2 },
2895
/* param0 -> t1, param1 -> t2 */ { gen_op_xor_t1_t2_t0, gen_op_xor_t1_t2_t1, gen_op_xor_t1_t2_t2 } },
2896
/* param0 -> t2 */              {
2897
/* param0 -> t2, param1 -> t0 */ { gen_op_xor_t2_t0_t0, gen_op_xor_t2_t0_t1, gen_op_xor_t2_t0_t2 },
2898
/* param0 -> t2, param1 -> t1 */ { gen_op_xor_t2_t1_t0, gen_op_xor_t2_t1_t1, gen_op_xor_t2_t1_t2 },
2899
/* param0 -> t2, param1 -> t2 */ { gen_op_xor_t2_t2_t0, gen_op_xor_t2_t2_t1, gen_op_xor_t2_t2_t2 } } };
2900
 
2901
void gen_l_xor(struct op_queue *opq, int param_t[3], orreg_t param[3],
2902
               int delay_slot)
2903
{
2904
  if(!param[0])
2905
    return;
2906
 
2907
  if((param_t[2] != T_NONE) && (param[1] == param[2])) {
2908
    clear_t[param_t[0]](opq, 1);
2909
    return;
2910
  }
2911
 
2912
  if(!param[2]) {
2913
    if((param_t[2] == T_NONE) && (param[0] == param[1]))
2914
      return;
2915
    move_t_t[param_t[0]][param_t[1]](opq, 1);
2916
    return;
2917
  }
2918
 
2919
  if(!param[1]) {
2920
    if(param_t[2] == T_NONE) {
2921
      mov_t_imm[param_t[0]](opq, 1, param[2]);
2922
      return;
2923
    }
2924
    move_t_t[param_t[0]][param_t[2]](opq, 1);
2925
    return;
2926
  }
2927
 
2928
  if(param_t[2] == T_NONE)
2929
    l_xor_imm_t_table[param_t[0]][param_t[1]](opq, 1, param[2]);
2930
  else
2931
    l_xor_t_table[param_t[0]][param_t[1]][param_t[2]](opq, 1);
2932
}
2933
 
2934
void gen_l_invalid(struct op_queue *opq, int param_t[3], orreg_t param[3],
2935
                   int delay_slot)
2936
{
2937
  if(!delay_slot)
2938
    gen_op_illegal(opq, 1);
2939
  else
2940
    gen_op_illegal_delay(opq, 1);
2941
}
2942
 
2943
/*----------------------------------[ Floating point instructions (stubs) ]---*/
2944
void gen_lf_add_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
2945
                  int delay_slot)
2946
{
2947
  gen_l_invalid(opq, param_t, param, delay_slot);
2948
}
2949
 
2950
void gen_lf_div_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
2951
                  int delay_slot)
2952
{
2953
  gen_l_invalid(opq, param_t, param, delay_slot);
2954
}
2955
 
2956
void gen_lf_ftoi_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
2957
                   int delay_slot)
2958
{
2959
  gen_l_invalid(opq, param_t, param, delay_slot);
2960
}
2961
 
2962
void gen_lf_itof_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
2963
                   int delay_slot)
2964
{
2965
  gen_l_invalid(opq, param_t, param, delay_slot);
2966
}
2967
 
2968
void gen_lf_madd_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
2969
                   int delay_slot)
2970
{
2971
  gen_l_invalid(opq, param_t, param, delay_slot);
2972
}
2973
 
2974
void gen_lf_mul_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
2975
                  int delay_slot)
2976
{
2977
  gen_l_invalid(opq, param_t, param, delay_slot);
2978
}
2979
 
2980
void gen_lf_rem_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
2981
                  int delay_slot)
2982
{
2983
  gen_l_invalid(opq, param_t, param, delay_slot);
2984
}
2985
 
2986
void gen_lf_sfeq_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
2987
                   int delay_slot)
2988
{
2989
  gen_l_invalid(opq, param_t, param, delay_slot);
2990
}
2991
 
2992
void gen_lf_sfge_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
2993
                   int delay_slot)
2994
{
2995
  gen_l_invalid(opq, param_t, param, delay_slot);
2996
}
2997
 
2998
void gen_lf_sfgt_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
2999
                   int delay_slot)
3000
{
3001
  gen_l_invalid(opq, param_t, param, delay_slot);
3002
}
3003
 
3004
void gen_lf_sfle_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
3005
                   int delay_slot)
3006
{
3007
  gen_l_invalid(opq, param_t, param, delay_slot);
3008
}
3009
 
3010
void gen_lf_sflt_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
3011
                   int delay_slot)
3012
{
3013
  gen_l_invalid(opq, param_t, param, delay_slot);
3014
}
3015
 
3016
void gen_lf_sfne_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
3017
                   int delay_slot)
3018
{
3019
  gen_l_invalid(opq, param_t, param, delay_slot);
3020
}
3021
 
3022
void gen_lf_sub_s(struct op_queue *opq, int param_t[3], orreg_t param[3],
3023
                  int delay_slot)
3024
{
3025
  gen_l_invalid(opq, param_t, param, delay_slot);
3026
}
3027
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.