1 |
/* |
/* |
2 |
* Copyright (C) 2005-2006 Anders Gavare. All rights reserved. |
* Copyright (C) 2005-2007 Anders Gavare. All rights reserved. |
3 |
* |
* |
4 |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
5 |
* modification, are permitted provided that the following conditions are met: |
* modification, are permitted provided that the following conditions are met: |
25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_alpha_instr.c,v 1.7 2006/02/09 22:40:27 debug Exp $ |
* $Id: cpu_alpha_instr.c,v 1.16 2007/06/05 03:15:01 debug Exp $ |
29 |
* |
* |
30 |
* Alpha instructions. |
* Alpha instructions. |
31 |
* |
* |
65 |
alpha_palcode(cpu, ic->arg[0]); |
alpha_palcode(cpu, ic->arg[0]); |
66 |
|
|
67 |
if (!cpu->running) { |
if (!cpu->running) { |
|
cpu->running_translated = 0; |
|
68 |
cpu->n_translated_instrs --; |
cpu->n_translated_instrs --; |
69 |
cpu->cd.alpha.next_ic = ¬hing_call; |
cpu->cd.alpha.next_ic = ¬hing_call; |
70 |
} else if (cpu->pc != old_pc) { |
} else if (cpu->pc != old_pc) { |
597 |
|
|
598 |
|
|
599 |
/* |
/* |
600 |
|
* implver: Return CPU implver value. |
601 |
|
* |
602 |
|
* arg[0] = pointer to destination uint64_t |
603 |
|
*/ |
604 |
|
X(implver) |
605 |
|
{ |
606 |
|
reg(ic->arg[0]) = cpu->cd.alpha.cpu_type.implver; |
607 |
|
} |
608 |
|
|
609 |
|
|
610 |
|
/* |
611 |
* mull: Signed Multiply 32x32 => 32. |
* mull: Signed Multiply 32x32 => 32. |
612 |
* |
* |
613 |
* arg[0] = pointer to destination uint64_t |
* arg[0] = pointer to destination uint64_t |
759 |
{ |
{ |
760 |
uint64_t addr, low_pc; |
uint64_t addr, low_pc; |
761 |
uint32_t iword; |
uint32_t iword; |
|
struct alpha_vph_page *vph_p; |
|
762 |
unsigned char *page; |
unsigned char *page; |
763 |
unsigned char ib[4]; |
unsigned char ib[4]; |
764 |
void (*samepage_function)(struct cpu *, struct alpha_instr_call *); |
void (*samepage_function)(struct cpu *, struct alpha_instr_call *); |
765 |
int opcode, ra, rb, func, rc, imm, load, loadstore_type, fp, llsc; |
int opcode, ra, rb, func, rc, imm, load, loadstore_type, fp, llsc; |
|
#ifdef DYNTRANS_BACKEND |
|
|
int simple = 0; |
|
|
#endif |
|
766 |
|
|
767 |
/* Figure out the (virtual) address of the instruction: */ |
/* Figure out the (virtual) address of the instruction: */ |
768 |
low_pc = ((size_t)ic - (size_t)cpu->cd.alpha.cur_ic_page) |
low_pc = ((size_t)ic - (size_t)cpu->cd.alpha.cur_ic_page) |
774 |
cpu->pc = addr; |
cpu->pc = addr; |
775 |
|
|
776 |
/* Read the instruction word from memory: */ |
/* Read the instruction word from memory: */ |
777 |
if ((addr >> ALPHA_TOPSHIFT) == 0) { |
{ |
778 |
vph_p = cpu->cd.alpha.vph_table0[(addr >> |
const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1; |
779 |
ALPHA_LEVEL0_SHIFT) & 8191]; |
const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1; |
780 |
page = vph_p->host_load[(addr >> ALPHA_LEVEL1_SHIFT) & 8191]; |
const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1; |
781 |
} else if ((addr >> ALPHA_TOPSHIFT) == ALPHA_TOP_KERNEL) { |
uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1; |
782 |
vph_p = cpu->cd.alpha.vph_table0_kernel[(addr >> |
uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2; |
783 |
ALPHA_LEVEL0_SHIFT) & 8191]; |
uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N- |
784 |
page = vph_p->host_load[(addr >> ALPHA_LEVEL1_SHIFT) & 8191]; |
DYNTRANS_L3N)) & mask3; |
785 |
} else |
struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.alpha.l1_64[x1]; |
786 |
page = NULL; |
struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2]; |
787 |
|
page = l3->host_load[x3]; |
788 |
|
} |
789 |
|
|
790 |
if (page != NULL) { |
if (page != NULL) { |
791 |
/* fatal("TRANSLATION HIT!\n"); */ |
/* fatal("TRANSLATION HIT!\n"); */ |
799 |
} |
} |
800 |
} |
} |
801 |
|
|
802 |
#ifdef HOST_LITTLE_ENDIAN |
/* Alpha instruction words are always little-endian. Convert |
803 |
iword = *((uint32_t *)&ib[0]); |
to host order: */ |
804 |
#else |
iword = LE32_TO_HOST( *((uint32_t *)&ib[0]) ); |
|
iword = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24); |
|
|
#endif |
|
|
|
|
|
/* fatal("{ Alpha: translating pc=0x%016llx iword=0x%08x }\n", |
|
|
(long long)addr, (int)iword); */ |
|
805 |
|
|
806 |
|
|
807 |
#define DYNTRANS_TO_BE_TRANSLATED_HEAD |
#define DYNTRANS_TO_BE_TRANSLATED_HEAD |
889 |
} |
} |
890 |
ic->f = alpha_loadstore[ |
ic->f = alpha_loadstore[ |
891 |
loadstore_type + (imm==0? 4 : 0) + 8 * load |
loadstore_type + (imm==0? 4 : 0) + 8 * load |
892 |
+ (cpu->machine->dyntrans_alignment_check? 16:0) |
+ 16 * llsc]; |
|
+ 32 * llsc]; |
|
893 |
/* Load to the zero register is treated as a prefetch |
/* Load to the zero register is treated as a prefetch |
894 |
hint. It is ignored here. */ |
hint. It is ignored here. */ |
895 |
if (load && ra == ALPHA_ZERO) { |
if (load && ra == ALPHA_ZERO) { |
919 |
case 0x02: ic->f = instr(s4addl); break; |
case 0x02: ic->f = instr(s4addl); break; |
920 |
case 0x09: ic->f = instr(subl); break; |
case 0x09: ic->f = instr(subl); break; |
921 |
case 0x0b: ic->f = instr(s4subl); break; |
case 0x0b: ic->f = instr(s4subl); break; |
922 |
|
case 0x0f: ic->f = instr(cmpbge); break; |
923 |
case 0x12: ic->f = instr(s8addl); break; |
case 0x12: ic->f = instr(s8addl); break; |
924 |
case 0x1b: ic->f = instr(s8subl); break; |
case 0x1b: ic->f = instr(s8subl); break; |
925 |
case 0x1d: ic->f = instr(cmpult); break; |
case 0x1d: ic->f = instr(cmpult); break; |
938 |
case 0x82: ic->f = instr(s4addl_imm); break; |
case 0x82: ic->f = instr(s4addl_imm); break; |
939 |
case 0x89: ic->f = instr(subl_imm); break; |
case 0x89: ic->f = instr(subl_imm); break; |
940 |
case 0x8b: ic->f = instr(s4subl_imm); break; |
case 0x8b: ic->f = instr(s4subl_imm); break; |
941 |
|
case 0x8f: ic->f = instr(cmpbge_imm); break; |
942 |
case 0x92: ic->f = instr(s8addl_imm); break; |
case 0x92: ic->f = instr(s8addl_imm); break; |
943 |
case 0x9b: ic->f = instr(s8subl_imm); break; |
case 0x9b: ic->f = instr(s8subl_imm); break; |
944 |
case 0x9d: ic->f = instr(cmpult_imm); break; |
case 0x9d: ic->f = instr(cmpult_imm); break; |
953 |
case 0xcd: ic->f = instr(cmplt_imm); break; |
case 0xcd: ic->f = instr(cmplt_imm); break; |
954 |
case 0xed: ic->f = instr(cmple_imm); break; |
case 0xed: ic->f = instr(cmple_imm); break; |
955 |
|
|
956 |
default:fatal("[ Alpha: unimplemented function 0x%03x for" |
default:if (!cpu->translation_readahead) |
957 |
" opcode 0x%02x ]\n", func, opcode); |
fatal("[ Alpha: unimplemented function 0x%03x " |
958 |
|
"for opcode 0x%02x ]\n", func, opcode); |
959 |
goto bad; |
goto bad; |
960 |
} |
} |
961 |
break; |
break; |
1005 |
case 0xc8: ic->f = instr(xornot_imm); break; |
case 0xc8: ic->f = instr(xornot_imm); break; |
1006 |
case 0xe4: ic->f = instr(cmovle_imm); break; |
case 0xe4: ic->f = instr(cmovle_imm); break; |
1007 |
case 0xe6: ic->f = instr(cmovgt_imm); break; |
case 0xe6: ic->f = instr(cmovgt_imm); break; |
1008 |
default:fatal("[ Alpha: unimplemented function 0x%03x for" |
case 0xec: ic->f = instr(implver); break; |
1009 |
" opcode 0x%02x ]\n", func, opcode); |
default:if (!cpu->translation_readahead) |
1010 |
|
fatal("[ Alpha: unimplemented function 0x%03x " |
1011 |
|
"for opcode 0x%02x ]\n", func, opcode); |
1012 |
goto bad; |
goto bad; |
1013 |
} |
} |
1014 |
break; |
break; |
1076 |
case 0xf2: ic->f = instr(mskqh_imm); break; |
case 0xf2: ic->f = instr(mskqh_imm); break; |
1077 |
case 0xf7: ic->f = instr(insqh_imm); break; |
case 0xf7: ic->f = instr(insqh_imm); break; |
1078 |
case 0xfa: ic->f = instr(extqh_imm); break; |
case 0xfa: ic->f = instr(extqh_imm); break; |
1079 |
default:fatal("[ Alpha: unimplemented function 0x%03x for" |
default:if (!cpu->translation_readahead) |
1080 |
" opcode 0x%02x ]\n", func, opcode); |
fatal("[ Alpha: unimplemented function 0x%03x " |
1081 |
|
"for opcode 0x%02x ]\n", func, opcode); |
1082 |
goto bad; |
goto bad; |
1083 |
} |
} |
1084 |
break; |
break; |
1097 |
case 0x00: ic->f = instr(mull); break; |
case 0x00: ic->f = instr(mull); break; |
1098 |
case 0x20: ic->f = instr(mulq); break; |
case 0x20: ic->f = instr(mulq); break; |
1099 |
case 0x30: ic->f = instr(umulh); break; |
case 0x30: ic->f = instr(umulh); break; |
1100 |
default:fatal("[ Alpha: unimplemented function 0x%03x for" |
default:if (!cpu->translation_readahead) |
1101 |
" opcode 0x%02x ]\n", func, opcode); |
fatal("[ Alpha: unimplemented function 0x%03x " |
1102 |
|
"for opcode 0x%02x ]\n", func, opcode); |
1103 |
goto bad; |
goto bad; |
1104 |
} |
} |
1105 |
break; |
break; |
1121 |
case 0x0a6: ic->f = instr(cmptlt); break; |
case 0x0a6: ic->f = instr(cmptlt); break; |
1122 |
case 0x0a7: ic->f = instr(cmptle); break; |
case 0x0a7: ic->f = instr(cmptle); break; |
1123 |
case 0x0be: ic->f = instr(cvtqt); break; |
case 0x0be: ic->f = instr(cvtqt); break; |
1124 |
default:fatal("[ Alpha: unimplemented function 0x%03x for" |
default:if (!cpu->translation_readahead) |
1125 |
" opcode 0x%02x ]\n", func, opcode); |
fatal("[ Alpha: unimplemented function 0x%03x " |
1126 |
|
"for opcode 0x%02x ]\n", func, opcode); |
1127 |
goto bad; |
goto bad; |
1128 |
} |
} |
1129 |
break; |
break; |
1146 |
case 0x021: |
case 0x021: |
1147 |
ic->f = instr(fneg); |
ic->f = instr(fneg); |
1148 |
break; |
break; |
1149 |
default:fatal("[ Alpha: unimplemented function 0x%03x for" |
default:if (!cpu->translation_readahead) |
1150 |
" opcode 0x%02x ]\n", func, opcode); |
fatal("[ Alpha: unimplemented function 0x%03x " |
1151 |
|
"for opcode 0x%02x ]\n", func, opcode); |
1152 |
goto bad; |
goto bad; |
1153 |
} |
} |
1154 |
break; |
break; |
1166 |
ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra]; |
ic->arg[0] = (size_t) &cpu->cd.alpha.r[ra]; |
1167 |
ic->f = instr(rdcc); |
ic->f = instr(rdcc); |
1168 |
break; |
break; |
1169 |
default:fatal("[ Alpha: unimplemented function 0x%03x for" |
default:if (!cpu->translation_readahead) |
1170 |
" opcode 0x%02x ]\n", func, opcode); |
fatal("[ Alpha: unimplemented function 0x%03x " |
1171 |
|
"for opcode 0x%02x ]\n", func, opcode); |
1172 |
goto bad; |
goto bad; |
1173 |
} |
} |
1174 |
break; |
break; |
1192 |
ic->f = instr(jsr); |
ic->f = instr(jsr); |
1193 |
} |
} |
1194 |
break; |
break; |
1195 |
default:fatal("[ Alpha: unimpl JSR type %i, ra=%i rb=%i ]\n", |
default:if (!cpu->translation_readahead) |
1196 |
((iword >> 14) & 3), ra, rb); |
fatal("[ Alpha: unimpl JSR type %i, ra=%i " |
1197 |
|
"rb=%i ]\n", ((iword >> 14) & 3), ra, rb); |
1198 |
goto bad; |
goto bad; |
1199 |
} |
} |
1200 |
break; |
break; |
1285 |
} |
} |
1286 |
} |
} |
1287 |
break; |
break; |
1288 |
default:fatal("[ UNIMPLEMENTED Alpha opcode 0x%x ]\n", opcode); |
default:if (!cpu->translation_readahead) |
1289 |
|
fatal("[ UNIMPLEMENTED Alpha opcode 0x%x ]\n", opcode); |
1290 |
goto bad; |
goto bad; |
1291 |
} |
} |
1292 |
|
|