1 |
/* |
/* |
2 |
* Cisco 7200 (Predator) simulation platform. |
* Cisco router simulation platform. |
3 |
* Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) |
* Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr) |
4 |
* |
* |
5 |
* MIPS64 Step-by-step execution. |
* MIPS64 Step-by-step execution. |
16 |
#include <sys/mman.h> |
#include <sys/mman.h> |
17 |
#include <fcntl.h> |
#include <fcntl.h> |
18 |
|
|
|
#include "rbtree.h" |
|
|
#include "mips64.h" |
|
|
#include "dynamips.h" |
|
|
#include "vm.h" |
|
|
#include "memory.h" |
|
19 |
#include "cpu.h" |
#include "cpu.h" |
20 |
#include "cp0.h" |
#include "vm.h" |
21 |
#include "mips64_exec.h" |
#include "mips64_exec.h" |
22 |
|
#include "memory.h" |
23 |
#include "insn_lookup.h" |
#include "insn_lookup.h" |
24 |
|
#include "dynamips.h" |
25 |
|
|
26 |
/* Forward declaration of instruction array */ |
/* Forward declaration of instruction array */ |
27 |
static struct insn_exec_tag mips64_exec_tags[]; |
static struct mips64_insn_exec_tag mips64_exec_tags[]; |
28 |
static insn_lookup_t *ilt = NULL; |
static insn_lookup_t *ilt = NULL; |
29 |
|
|
30 |
/* ILT */ |
/* ILT */ |
33 |
return(&mips64_exec_tags[index]); |
return(&mips64_exec_tags[index]); |
34 |
} |
} |
35 |
|
|
36 |
static int mips64_exec_chk_lo(struct insn_exec_tag *tag,int value) |
static int mips64_exec_chk_lo(struct mips64_insn_exec_tag *tag,int value) |
37 |
{ |
{ |
38 |
return((value & tag->mask) == (tag->value & 0xFFFF)); |
return((value & tag->mask) == (tag->value & 0xFFFF)); |
39 |
} |
} |
40 |
|
|
41 |
static int mips64_exec_chk_hi(struct insn_exec_tag *tag,int value) |
static int mips64_exec_chk_hi(struct mips64_insn_exec_tag *tag,int value) |
42 |
{ |
{ |
43 |
return((value & (tag->mask >> 16)) == (tag->value >> 16)); |
return((value & (tag->mask >> 16)) == (tag->value >> 16)); |
44 |
} |
} |
51 |
for(i=0,count=0;mips64_exec_tags[i].exec;i++) |
for(i=0,count=0;mips64_exec_tags[i].exec;i++) |
52 |
count++; |
count++; |
53 |
|
|
54 |
ilt = ilt_create(count, |
ilt = ilt_create("mips64e",count, |
55 |
(ilt_get_insn_cbk_t)mips64_exec_get_insn, |
(ilt_get_insn_cbk_t)mips64_exec_get_insn, |
56 |
(ilt_check_cbk_t)mips64_exec_chk_lo, |
(ilt_check_cbk_t)mips64_exec_chk_lo, |
57 |
(ilt_check_cbk_t)mips64_exec_chk_hi); |
(ilt_check_cbk_t)mips64_exec_chk_hi); |
81 |
{ |
{ |
82 |
char insn_name[64],insn_format[32],*name; |
char insn_name[64],insn_format[32],*name; |
83 |
int base,rs,rd,rt,sa,offset,imm; |
int base,rs,rd,rt,sa,offset,imm; |
84 |
struct insn_exec_tag *tag; |
struct mips64_insn_exec_tag *tag; |
85 |
m_uint64_t new_pc; |
m_uint64_t new_pc; |
86 |
int index; |
int index; |
87 |
|
|
279 |
} |
} |
280 |
|
|
281 |
/* Execute a memory operation */ |
/* Execute a memory operation */ |
282 |
static forced_inline int mips64_exec_memop(cpu_mips_t *cpu,int memop, |
static forced_inline void mips64_exec_memop(cpu_mips_t *cpu,int memop, |
283 |
m_uint64_t vaddr,u_int dst_reg, |
m_uint64_t vaddr,u_int dst_reg, |
284 |
int keep_ll_bit) |
int keep_ll_bit) |
285 |
{ |
{ |
286 |
fastcall mips_memop_fn fn; |
fastcall mips_memop_fn fn; |
287 |
|
|
288 |
if (!keep_ll_bit) cpu->ll_bit = 0; |
if (!keep_ll_bit) cpu->ll_bit = 0; |
289 |
fn = cpu->mem_op_fn[memop]; |
fn = cpu->mem_op_fn[memop]; |
290 |
return(fn(cpu,vaddr,dst_reg)); |
fn(cpu,vaddr,dst_reg); |
291 |
} |
} |
292 |
|
|
293 |
/* Execute a memory operation (2) */ |
/* Execute a memory operation (2) */ |
294 |
static forced_inline int mips64_exec_memop2(cpu_mips_t *cpu,int memop, |
static forced_inline void mips64_exec_memop2(cpu_mips_t *cpu,int memop, |
295 |
m_uint64_t base,int offset, |
m_uint64_t base,int offset, |
296 |
u_int dst_reg,int keep_ll_bit) |
u_int dst_reg,int keep_ll_bit) |
297 |
{ |
{ |
298 |
m_uint64_t vaddr = cpu->gpr[base] + sign_extend(offset,16); |
m_uint64_t vaddr = cpu->gpr[base] + sign_extend(offset,16); |
299 |
fastcall mips_memop_fn fn; |
fastcall mips_memop_fn fn; |
300 |
|
|
301 |
if (!keep_ll_bit) cpu->ll_bit = 0; |
if (!keep_ll_bit) cpu->ll_bit = 0; |
302 |
fn = cpu->mem_op_fn[memop]; |
fn = cpu->mem_op_fn[memop]; |
303 |
return(fn(cpu,vaddr,dst_reg)); |
fn(cpu,vaddr,dst_reg); |
304 |
} |
} |
305 |
|
|
306 |
/* Fetch an instruction */ |
/* Fetch an instruction */ |
322 |
return(0); |
return(0); |
323 |
} |
} |
324 |
|
|
325 |
|
/* Unknown opcode */ |
326 |
|
static fastcall int mips64_exec_unknown(cpu_mips_t *cpu,mips_insn_t insn) |
327 |
|
{ |
328 |
|
printf("MIPS64: unknown opcode 0x%8.8x at pc = 0x%llx\n",insn,cpu->pc); |
329 |
|
mips64_dump_regs(cpu->gen); |
330 |
|
return(0); |
331 |
|
} |
332 |
|
|
333 |
/* Execute a single instruction */ |
/* Execute a single instruction */ |
334 |
static forced_inline int |
static forced_inline int |
335 |
mips64_exec_single_instruction(cpu_mips_t *cpu,mips_insn_t instruction) |
mips64_exec_single_instruction(cpu_mips_t *cpu,mips_insn_t instruction) |
336 |
{ |
{ |
337 |
register fastcall int (*exec)(cpu_mips_t *,mips_insn_t) = NULL; |
register fastcall int (*exec)(cpu_mips_t *,mips_insn_t) = NULL; |
338 |
struct insn_exec_tag *tag; |
struct mips64_insn_exec_tag *tag; |
339 |
int index; |
int index; |
340 |
|
|
341 |
#if DEBUG_PERF_COUNTER |
#if DEBUG_INSN_PERF_CNT |
342 |
cpu->perf_counter++; |
cpu->perf_counter++; |
343 |
#endif |
#endif |
344 |
|
|
350 |
tag = mips64_exec_get_insn(index); |
tag = mips64_exec_get_insn(index); |
351 |
exec = tag->exec; |
exec = tag->exec; |
352 |
|
|
|
if (likely(exec != NULL)) { |
|
353 |
#if NJM_STATS_ENABLE |
#if NJM_STATS_ENABLE |
354 |
cpu->insn_exec_count++; |
cpu->insn_exec_count++; |
355 |
mips64_exec_tags[index].count++; |
mips64_exec_tags[index].count++; |
356 |
#endif |
#endif |
357 |
#if 0 |
#if 0 |
358 |
{ |
{ |
359 |
char buffer[80]; |
char buffer[80]; |
360 |
|
|
361 |
if (mips64_dump_insn(buffer,sizeof(buffer),0,cpu->pc,instruction)!=-1) |
if (mips64_dump_insn(buffer,sizeof(buffer),0,cpu->pc,instruction)!=-1) |
362 |
fprintf(log_file,"0x%llx: %s\n",cpu->pc,buffer); |
cpu_log(cpu->gen,"EXEC","0x%llx: %s\n",cpu->pc,buffer); |
363 |
} |
} |
364 |
#endif |
#endif |
365 |
|
return(exec(cpu,instruction)); |
|
return(exec(cpu,instruction)); |
|
|
} |
|
|
|
|
|
printf("MIPS64: unknown opcode 0x%8.8x at pc = 0x%llx\n", |
|
|
instruction,cpu->pc); |
|
|
mips64_dump_regs(cpu); |
|
|
return(0); |
|
366 |
} |
} |
367 |
|
|
368 |
/* Single-step execution */ |
/* Single-step execution */ |
369 |
void mips64_exec_single_step(cpu_mips_t *cpu,mips_insn_t instruction) |
fastcall void mips64_exec_single_step(cpu_mips_t *cpu,mips_insn_t instruction) |
370 |
{ |
{ |
371 |
int res; |
int res; |
372 |
|
|
377 |
} |
} |
378 |
|
|
379 |
/* Run MIPS code in step-by-step mode */ |
/* Run MIPS code in step-by-step mode */ |
380 |
void *mips64_exec_run_cpu(cpu_mips_t *cpu) |
void *mips64_exec_run_cpu(cpu_gen_t *gen) |
381 |
{ |
{ |
382 |
|
cpu_mips_t *cpu = CPU_MIPS64(gen); |
383 |
pthread_t timer_irq_thread; |
pthread_t timer_irq_thread; |
|
mips_insn_t insn; |
|
384 |
int timer_irq_check = 0; |
int timer_irq_check = 0; |
385 |
|
mips_insn_t insn; |
386 |
int res; |
int res; |
387 |
|
|
388 |
if (pthread_create(&timer_irq_thread,NULL, |
if (pthread_create(&timer_irq_thread,NULL, |
389 |
(void *)mips64_timer_irq_run,cpu)) |
(void *)mips64_timer_irq_run,cpu)) |
390 |
{ |
{ |
391 |
fprintf(stderr,"VM '%s': unable to create Timer IRQ thread for CPU%u.\n", |
fprintf(stderr,"VM '%s': unable to create Timer IRQ thread for CPU%u.\n", |
392 |
cpu->vm->name,cpu->id); |
cpu->vm->name,gen->id); |
393 |
cpu_stop(cpu); |
cpu_stop(gen); |
394 |
return NULL; |
return NULL; |
395 |
} |
} |
396 |
|
|
397 |
cpu->cpu_thread_running = TRUE; |
gen->cpu_thread_running = TRUE; |
398 |
|
cpu_exec_loop_set(gen); |
399 |
|
|
400 |
start_cpu: |
start_cpu: |
401 |
cpu->idle_count = 0; |
gen->idle_count = 0; |
402 |
|
|
403 |
for(;;) { |
for(;;) { |
404 |
if (unlikely(cpu->state != MIPS_CPU_RUNNING)) |
if (unlikely(gen->state != CPU_STATE_RUNNING)) |
405 |
break; |
break; |
406 |
|
|
407 |
/* Handle virtual idle loop */ |
/* Handle virtual idle loop */ |
408 |
if (unlikely(cpu->pc == cpu->idle_pc)) { |
if (unlikely(cpu->pc == cpu->idle_pc)) { |
409 |
if (++cpu->idle_count == cpu->idle_max) { |
if (++gen->idle_count == gen->idle_max) { |
410 |
mips64_idle_loop(cpu); |
cpu_idle_loop(gen); |
411 |
cpu->idle_count = 0; |
gen->idle_count = 0; |
412 |
} |
} |
413 |
} |
} |
414 |
|
|
437 |
res = mips64_exec_single_instruction(cpu,insn); |
res = mips64_exec_single_instruction(cpu,insn); |
438 |
|
|
439 |
/* Normal flow ? */ |
/* Normal flow ? */ |
440 |
if (likely(!res)) cpu->pc += 4; |
if (likely(!res)) cpu->pc += sizeof(mips_insn_t); |
441 |
} |
} |
442 |
|
|
443 |
if (!cpu->pc) { |
if (!cpu->pc) { |
444 |
cpu_stop(cpu); |
cpu_stop(gen); |
445 |
cpu_log(cpu,"SLOW_EXEC","PC=0, halting CPU.\n"); |
cpu_log(gen,"SLOW_EXEC","PC=0, halting CPU.\n"); |
446 |
} |
} |
447 |
|
|
448 |
/* Check regularly if the CPU has been restarted */ |
/* Check regularly if the CPU has been restarted */ |
449 |
while(cpu->cpu_thread_running) { |
while(gen->cpu_thread_running) { |
450 |
cpu->seq_state++; |
gen->seq_state++; |
451 |
|
|
452 |
switch(cpu->state) { |
switch(gen->state) { |
453 |
case MIPS_CPU_RUNNING: |
case CPU_STATE_RUNNING: |
454 |
cpu->state = MIPS_CPU_RUNNING; |
gen->state = CPU_STATE_RUNNING; |
455 |
goto start_cpu; |
goto start_cpu; |
456 |
|
|
457 |
case MIPS_CPU_HALTED: |
case CPU_STATE_HALTED: |
458 |
cpu->cpu_thread_running = FALSE; |
gen->cpu_thread_running = FALSE; |
459 |
pthread_join(timer_irq_thread,NULL); |
pthread_join(timer_irq_thread,NULL); |
460 |
break; |
break; |
461 |
} |
} |
1076 |
int op = bits(insn,16,20); |
int op = bits(insn,16,20); |
1077 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1078 |
|
|
1079 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_CACHE,base,offset,op,FALSE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_CACHE,base,offset,op,FALSE); |
1080 |
|
return(0); |
1081 |
} |
} |
1082 |
|
|
1083 |
/* CFC0 */ |
/* CFC0 */ |
1086 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1087 |
int rd = bits(insn,11,15); |
int rd = bits(insn,11,15); |
1088 |
|
|
1089 |
cp0_exec_cfc0(cpu,rt,rd); |
mips64_cp0_exec_cfc0(cpu,rt,rd); |
1090 |
return(0); |
return(0); |
1091 |
} |
} |
1092 |
|
|
1096 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1097 |
int rd = bits(insn,11,15); |
int rd = bits(insn,11,15); |
1098 |
|
|
1099 |
cp0_exec_ctc0(cpu,rt,rd); |
mips64_cp0_exec_ctc0(cpu,rt,rd); |
1100 |
return(0); |
return(0); |
1101 |
} |
} |
1102 |
|
|
1160 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1161 |
int rd = bits(insn,11,15); |
int rd = bits(insn,11,15); |
1162 |
|
|
1163 |
cp0_exec_dmfc0(cpu,rt,rd); |
mips64_cp0_exec_dmfc0(cpu,rt,rd); |
1164 |
return(0); |
return(0); |
1165 |
} |
} |
1166 |
|
|
1180 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1181 |
int rd = bits(insn,11,15); |
int rd = bits(insn,11,15); |
1182 |
|
|
1183 |
cp0_exec_dmtc0(cpu,rt,rd); |
mips64_cp0_exec_dmtc0(cpu,rt,rd); |
1184 |
return(0); |
return(0); |
1185 |
} |
} |
1186 |
|
|
1395 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1396 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1397 |
|
|
1398 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_LB,base,offset,rt,TRUE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_LB,base,offset,rt,TRUE); |
1399 |
|
return(0); |
1400 |
} |
} |
1401 |
|
|
1402 |
/* LBU (Load Byte Unsigned) */ |
/* LBU (Load Byte Unsigned) */ |
1406 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1407 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1408 |
|
|
1409 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_LBU,base,offset,rt,TRUE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_LBU,base,offset,rt,TRUE); |
1410 |
|
return(0); |
1411 |
} |
} |
1412 |
|
|
1413 |
/* LD (Load Double-Word) */ |
/* LD (Load Double-Word) */ |
1417 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1418 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1419 |
|
|
1420 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_LD,base,offset,rt,TRUE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_LD,base,offset,rt,TRUE); |
1421 |
|
return(0); |
1422 |
} |
} |
1423 |
|
|
1424 |
/* LDC1 (Load Double-Word to Coprocessor 1) */ |
/* LDC1 (Load Double-Word to Coprocessor 1) */ |
1428 |
int ft = bits(insn,16,20); |
int ft = bits(insn,16,20); |
1429 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1430 |
|
|
1431 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_LDC1,base,offset,ft,TRUE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_LDC1,base,offset,ft,TRUE); |
1432 |
|
return(0); |
1433 |
} |
} |
1434 |
|
|
1435 |
/* LDL (Load Double-Word Left) */ |
/* LDL (Load Double-Word Left) */ |
1439 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1440 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1441 |
|
|
1442 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_LDL,base,offset,rt,TRUE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_LDL,base,offset,rt,TRUE); |
1443 |
|
return(0); |
1444 |
} |
} |
1445 |
|
|
1446 |
/* LDR (Load Double-Word Right) */ |
/* LDR (Load Double-Word Right) */ |
1450 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1451 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1452 |
|
|
1453 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_LDR,base,offset,rt,TRUE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_LDR,base,offset,rt,TRUE); |
1454 |
|
return(0); |
1455 |
} |
} |
1456 |
|
|
1457 |
/* LH (Load Half-Word) */ |
/* LH (Load Half-Word) */ |
1461 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1462 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1463 |
|
|
1464 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_LH,base,offset,rt,TRUE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_LH,base,offset,rt,TRUE); |
1465 |
|
return(0); |
1466 |
} |
} |
1467 |
|
|
1468 |
/* LHU (Load Half-Word Unsigned) */ |
/* LHU (Load Half-Word Unsigned) */ |
1472 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1473 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1474 |
|
|
1475 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_LHU,base,offset,rt,TRUE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_LHU,base,offset,rt,TRUE); |
1476 |
|
return(0); |
1477 |
} |
} |
1478 |
|
|
1479 |
/* LI (virtual) */ |
/* LI (virtual) */ |
1493 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1494 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1495 |
|
|
1496 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_LL,base,offset,rt,TRUE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_LL,base,offset,rt,TRUE); |
1497 |
|
return(0); |
1498 |
} |
} |
1499 |
|
|
1500 |
/* LUI */ |
/* LUI */ |
1514 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1515 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1516 |
|
|
1517 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_LW,base,offset,rt,TRUE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_LW,base,offset,rt,TRUE); |
1518 |
|
return(0); |
1519 |
} |
} |
1520 |
|
|
1521 |
/* LWL (Load Word Left) */ |
/* LWL (Load Word Left) */ |
1525 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1526 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1527 |
|
|
1528 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_LWL,base,offset,rt,TRUE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_LWL,base,offset,rt,TRUE); |
1529 |
|
return(0); |
1530 |
} |
} |
1531 |
|
|
1532 |
/* LWR (Load Word Right) */ |
/* LWR (Load Word Right) */ |
1536 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1537 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1538 |
|
|
1539 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_LWR,base,offset,rt,TRUE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_LWR,base,offset,rt,TRUE); |
1540 |
|
return(0); |
1541 |
} |
} |
1542 |
|
|
1543 |
/* LWU (Load Word Unsigned) */ |
/* LWU (Load Word Unsigned) */ |
1547 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1548 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1549 |
|
|
1550 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_LWU,base,offset,rt,TRUE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_LWU,base,offset,rt,TRUE); |
1551 |
|
return(0); |
1552 |
} |
} |
1553 |
|
|
1554 |
/* MFC0 */ |
/* MFC0 */ |
1557 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1558 |
int rd = bits(insn,11,15); |
int rd = bits(insn,11,15); |
1559 |
|
|
1560 |
cp0_exec_mfc0(cpu,rt,rd); |
mips64_cp0_exec_mfc0(cpu,rt,rd); |
1561 |
return(0); |
return(0); |
1562 |
} |
} |
1563 |
|
|
1605 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1606 |
int rd = bits(insn,11,15); |
int rd = bits(insn,11,15); |
1607 |
|
|
1608 |
cp0_exec_mtc0(cpu,rt,rd); |
mips64_cp0_exec_mtc0(cpu,rt,rd); |
1609 |
return(0); |
return(0); |
1610 |
} |
} |
1611 |
|
|
1738 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1739 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1740 |
|
|
1741 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_SB,base,offset,rt,FALSE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_SB,base,offset,rt,FALSE); |
1742 |
|
return(0); |
1743 |
} |
} |
1744 |
|
|
1745 |
/* SC (Store Conditional) */ |
/* SC (Store Conditional) */ |
1749 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1750 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1751 |
|
|
1752 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_SC,base,offset,rt,TRUE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_SC,base,offset,rt,TRUE); |
1753 |
|
return(0); |
1754 |
} |
} |
1755 |
|
|
1756 |
/* SD (Store Double-Word) */ |
/* SD (Store Double-Word) */ |
1760 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1761 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1762 |
|
|
1763 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_SD,base,offset,rt,FALSE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_SD,base,offset,rt,FALSE); |
1764 |
|
return(0); |
1765 |
} |
} |
1766 |
|
|
1767 |
/* SDL (Store Double-Word Left) */ |
/* SDL (Store Double-Word Left) */ |
1771 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1772 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1773 |
|
|
1774 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_SDL,base,offset,rt,FALSE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_SDL,base,offset,rt,FALSE); |
1775 |
|
return(0); |
1776 |
} |
} |
1777 |
|
|
1778 |
/* SDR (Store Double-Word Right) */ |
/* SDR (Store Double-Word Right) */ |
1782 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1783 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1784 |
|
|
1785 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_SDR,base,offset,rt,FALSE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_SDR,base,offset,rt,FALSE); |
1786 |
|
return(0); |
1787 |
} |
} |
1788 |
|
|
1789 |
/* SDC1 (Store Double-Word from Coprocessor 1) */ |
/* SDC1 (Store Double-Word from Coprocessor 1) */ |
1793 |
int ft = bits(insn,16,20); |
int ft = bits(insn,16,20); |
1794 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1795 |
|
|
1796 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_SDC1,base,offset,ft,FALSE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_SDC1,base,offset,ft,FALSE); |
1797 |
|
return(0); |
1798 |
} |
} |
1799 |
|
|
1800 |
/* SH (Store Half-Word) */ |
/* SH (Store Half-Word) */ |
1804 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1805 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1806 |
|
|
1807 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_SH,base,offset,rt,FALSE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_SH,base,offset,rt,FALSE); |
1808 |
|
return(0); |
1809 |
} |
} |
1810 |
|
|
1811 |
/* SLL */ |
/* SLL */ |
1982 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1983 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1984 |
|
|
1985 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_SW,base,offset,rt,FALSE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_SW,base,offset,rt,FALSE); |
1986 |
|
return(0); |
1987 |
} |
} |
1988 |
|
|
1989 |
/* SWL (Store Word Left) */ |
/* SWL (Store Word Left) */ |
1993 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
1994 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
1995 |
|
|
1996 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_SWL,base,offset,rt,FALSE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_SWL,base,offset,rt,FALSE); |
1997 |
|
return(0); |
1998 |
} |
} |
1999 |
|
|
2000 |
/* SWR (Store Word Right) */ |
/* SWR (Store Word Right) */ |
2004 |
int rt = bits(insn,16,20); |
int rt = bits(insn,16,20); |
2005 |
int offset = bits(insn,0,15); |
int offset = bits(insn,0,15); |
2006 |
|
|
2007 |
return(mips64_exec_memop2(cpu,MIPS_MEMOP_SWR,base,offset,rt,FALSE)); |
mips64_exec_memop2(cpu,MIPS_MEMOP_SWR,base,offset,rt,FALSE); |
2008 |
|
return(0); |
2009 |
} |
} |
2010 |
|
|
2011 |
/* SYNC */ |
/* SYNC */ |
2053 |
/* TLBP */ |
/* TLBP */ |
2054 |
static fastcall int mips64_exec_TLBP(cpu_mips_t *cpu,mips_insn_t insn) |
static fastcall int mips64_exec_TLBP(cpu_mips_t *cpu,mips_insn_t insn) |
2055 |
{ |
{ |
2056 |
cp0_exec_tlbp(cpu); |
mips64_cp0_exec_tlbp(cpu); |
2057 |
return(0); |
return(0); |
2058 |
} |
} |
2059 |
|
|
2060 |
/* TLBR */ |
/* TLBR */ |
2061 |
static fastcall int mips64_exec_TLBR(cpu_mips_t *cpu,mips_insn_t insn) |
static fastcall int mips64_exec_TLBR(cpu_mips_t *cpu,mips_insn_t insn) |
2062 |
{ |
{ |
2063 |
cp0_exec_tlbr(cpu); |
mips64_cp0_exec_tlbr(cpu); |
2064 |
return(0); |
return(0); |
2065 |
} |
} |
2066 |
|
|
2067 |
/* TLBWI */ |
/* TLBWI */ |
2068 |
static fastcall int mips64_exec_TLBWI(cpu_mips_t *cpu,mips_insn_t insn) |
static fastcall int mips64_exec_TLBWI(cpu_mips_t *cpu,mips_insn_t insn) |
2069 |
{ |
{ |
2070 |
cp0_exec_tlbwi(cpu); |
mips64_cp0_exec_tlbwi(cpu); |
2071 |
return(0); |
return(0); |
2072 |
} |
} |
2073 |
|
|
2074 |
/* TLBWR */ |
/* TLBWR */ |
2075 |
static fastcall int mips64_exec_TLBWR(cpu_mips_t *cpu,mips_insn_t insn) |
static fastcall int mips64_exec_TLBWR(cpu_mips_t *cpu,mips_insn_t insn) |
2076 |
{ |
{ |
2077 |
cp0_exec_tlbwr(cpu); |
mips64_cp0_exec_tlbwr(cpu); |
2078 |
return(0); |
return(0); |
2079 |
} |
} |
2080 |
|
|
2101 |
} |
} |
2102 |
|
|
2103 |
/* MIPS instruction array */ |
/* MIPS instruction array */ |
2104 |
static struct insn_exec_tag mips64_exec_tags[] = { |
static struct mips64_insn_exec_tag mips64_exec_tags[] = { |
2105 |
{ "li" , mips64_exec_LI , 0xffe00000 , 0x24000000, 1, 16 }, |
{ "li" , mips64_exec_LI , 0xffe00000 , 0x24000000, 1, 16 }, |
2106 |
{ "move" , mips64_exec_MOVE , 0xfc1f07ff , 0x00000021, 1, 15 }, |
{ "move" , mips64_exec_MOVE , 0xfc1f07ff , 0x00000021, 1, 15 }, |
2107 |
{ "b" , mips64_exec_B , 0xffff0000 , 0x10000000, 0, 10 }, |
{ "b" , mips64_exec_B , 0xffff0000 , 0x10000000, 0, 10 }, |
2221 |
{ "tlbwr" , mips64_exec_TLBWR , 0xffffffff , 0x42000006, 1, 1 }, |
{ "tlbwr" , mips64_exec_TLBWR , 0xffffffff , 0x42000006, 1, 1 }, |
2222 |
{ "xor" , mips64_exec_XOR , 0xfc0007ff , 0x00000026, 1, 3 }, |
{ "xor" , mips64_exec_XOR , 0xfc0007ff , 0x00000026, 1, 3 }, |
2223 |
{ "xori" , mips64_exec_XORI , 0xfc000000 , 0x38000000, 1, 5 }, |
{ "xori" , mips64_exec_XORI , 0xfc000000 , 0x38000000, 1, 5 }, |
2224 |
|
{ "unknown", mips64_exec_unknown , 0x00000000 , 0x00000000, 1, 0 }, |
2225 |
{ NULL , NULL , 0x00000000 , 0x00000000, 1, 0 }, |
{ NULL , NULL , 0x00000000 , 0x00000000, 1, 0 }, |
2226 |
}; |
}; |
2227 |
|
|