25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: bintrans_alpha.c,v 1.119 2005/06/22 10:12:25 debug Exp $ |
* $Id: bintrans_alpha.c,v 1.125 2005/07/31 08:47:56 debug Exp $ |
29 |
* |
* |
30 |
* Alpha specific code for dynamic binary translation. |
* Alpha specific code for dynamic binary translation. |
31 |
* |
* |
60 |
* t7 a0 (mips register 4) (64-bit) |
* t7 a0 (mips register 4) (64-bit) |
61 |
* t8 a1 (mips register 5) (64-bit) |
* t8 a1 (mips register 5) (64-bit) |
62 |
* t9 s0 (mips register 16) (64-bit) |
* t9 s0 (mips register 16) (64-bit) |
63 |
* t10 table0 cached (for load/store) |
* t10 load table base cached |
64 |
* t11 v0 (mips register 2) (64-bit) |
* t11 v0 (mips register 2) (64-bit) |
65 |
* s0 delay_slot (32-bit int) |
* s0 delay_slot (32-bit int) |
66 |
* s1 delay_jmpaddr (64-bit) |
* s1 delay_jmpaddr (64-bit) |
68 |
* s3 ra (mips register 31) (64-bit) |
* s3 ra (mips register 31) (64-bit) |
69 |
* s4 t0 (mips register 8) (64-bit) |
* s4 t0 (mips register 8) (64-bit) |
70 |
* s5 t1 (mips register 9) (64-bit) |
* s5 t1 (mips register 9) (64-bit) |
71 |
* s6 t2 (mips register 10) (64-bit) |
* s6 store table base cached |
72 |
*/ |
*/ |
73 |
|
|
74 |
#define MIPSREG_PC -3 |
#define MIPSREG_PC -3 |
105 |
static int map_MIPS_to_Alpha[32] = { |
static int map_MIPS_to_Alpha[32] = { |
106 |
ALPHA_ZERO, -1, ALPHA_T11, -1, /* 0 .. 3 */ |
ALPHA_ZERO, -1, ALPHA_T11, -1, /* 0 .. 3 */ |
107 |
ALPHA_T7, ALPHA_T8, -1, -1, /* 4 .. 7 */ |
ALPHA_T7, ALPHA_T8, -1, -1, /* 4 .. 7 */ |
108 |
ALPHA_S4, ALPHA_S5, ALPHA_S6, -1, /* 8 .. 11 */ |
ALPHA_S4, ALPHA_S5, -1, -1, /* 8 .. 11 */ |
109 |
-1, -1, -1, -1, /* 12 .. 15 */ |
-1, -1, -1, -1, /* 12 .. 15 */ |
110 |
ALPHA_T9, -1, -1, -1, /* 16 .. 19 */ |
ALPHA_T9, -1, -1, -1, /* 16 .. 19 */ |
111 |
-1, -1, -1, -1, /* 20 .. 23 */ |
-1, -1, -1, -1, /* 20 .. 23 */ |
150 |
} |
} |
151 |
|
|
152 |
|
|
|
/* |
|
|
* lda sp,-128(sp) some margin |
|
|
* stq ra,0(sp) |
|
|
* stq s0,8(sp) |
|
|
* stq s1,16(sp) |
|
|
* stq s2,24(sp) |
|
|
* stq s3,32(sp) |
|
|
* stq s4,40(sp) |
|
|
* stq s5,48(sp) |
|
|
* stq s6,56(sp) |
|
|
* |
|
|
* jsr ra,(a1),<back> |
|
|
* back: |
|
|
* |
|
|
* ldq ra,0(sp) |
|
|
* ldq s0,8(sp) |
|
|
* ldq s1,16(sp) |
|
|
* ldq s2,24(sp) |
|
|
* ldq s3,32(sp) |
|
|
* ldq s4,40(sp) |
|
|
* ldq s5,48(sp) |
|
|
* ldq s6,56(sp) |
|
|
* lda sp,128(sp) |
|
|
* ret |
|
|
*/ |
|
153 |
/* note: offsetof (in stdarg.h) could possibly be used, but I'm not sure |
/* note: offsetof (in stdarg.h) could possibly be used, but I'm not sure |
154 |
if it will take care of the compiler problems... */ |
if it will take care of the compiler problems... */ |
155 |
#define ofs_pc (((size_t)&dummy_cpu.pc) - ((size_t)&dummy_cpu)) |
#define ofs_pc (((size_t)&dummy_cpu.pc) - ((size_t)&dummy_cpu)) |
170 |
#define ofs_c0 ((size_t)&dummy_vth32_table.bintrans_chunks[0] - (size_t)&dummy_vth32_table) |
#define ofs_c0 ((size_t)&dummy_vth32_table.bintrans_chunks[0] - (size_t)&dummy_vth32_table) |
171 |
#define ofs_cb (((size_t)&dummy_cpu.cd.mips.chunk_base_address) - (size_t)&dummy_cpu) |
#define ofs_cb (((size_t)&dummy_cpu.cd.mips.chunk_base_address) - (size_t)&dummy_cpu) |
172 |
|
|
173 |
|
#define ofs_h_l (((size_t)&dummy_cpu.cd.mips.host_load) - ((size_t)&dummy_cpu)) |
174 |
|
#define ofs_h_s (((size_t)&dummy_cpu.cd.mips.host_store) - ((size_t)&dummy_cpu)) |
175 |
|
|
|
static uint32_t bintrans_alpha_load_32bit[18] = { |
|
|
/* |
|
|
* t1 = 1023; |
|
|
* t2 = ((a1 >> 22) & t1) * sizeof(void *); |
|
|
* t3 = ((a1 >> 12) & t1) * sizeof(void *); |
|
|
* t1 = a1 & 4095; |
|
|
* |
|
|
* f8 1f 5f 20 lda t1,1023 * 8 |
|
|
* 83 76 22 4a srl a1,19,t2 |
|
|
* 84 36 21 4a srl a1, 9,t3 |
|
|
* 03 00 62 44 and t2,t1,t2 |
|
|
*/ |
|
|
0x205f1ff8, |
|
|
0x4a227683, |
|
|
0x4a213684, |
|
|
0x44620003, |
|
|
|
|
|
/* |
|
|
* t10 is vaddr_to_hostaddr_table0 |
|
|
* |
|
|
* a3 = tbl0[t2] (load entry from tbl0) |
|
|
* 12 04 03 43 addq t10,t2,a2 |
|
|
*/ |
|
|
0x43030412, |
|
|
|
|
|
/* 04 00 82 44 and t3,t1,t3 */ |
|
|
0x44820004, |
|
|
|
|
|
/* 00 00 72 a6 ldq a3,0(a2) */ |
|
|
0xa6720000, |
|
|
|
|
|
/* 24 37 80 48 sll t3,0x1,t3 */ |
|
|
0x48803724, |
|
|
|
|
|
/* ff 0f 5f 20 lda t1,4095 */ |
|
|
0x205f0fff, |
|
176 |
|
|
177 |
/* |
static uint32_t bintrans_alpha_load_32bit[18] = { |
178 |
* a3 = tbl1[t3] (load entry from tbl1 (which is a3)) |
0x4a21f622, /* zapnot a1,0xf,t1 */ |
179 |
* 13 04 64 42 addq a3,t3,a3 |
0x209f0fff, /* lda t3,4095 */ |
180 |
*/ |
0x48419682, /* srl t1,0xc,t1 t1 = addr >> 12 */ |
181 |
0x42640413, |
0x46240004, /* and a1,t3,t3 t3 = addr & 4095 */ |
182 |
|
0x40580642, /* s8addq t1,t10,t1 &host_load[t1] */ |
183 |
/* 02 00 22 46 and a1,t1,t1 */ |
0xa6620000, /* ldq a3,0(t1) a3 = host_load[t1] */ |
|
0x46220002, |
|
|
|
|
|
/* 00 00 73 a6 ldq a3,0(a3) */ |
|
|
0xa6730000, |
|
184 |
|
|
185 |
/* NULL? Then return failure at once. */ |
/* NULL? Then return failure at once. */ |
186 |
/* beq a3, return */ |
0xe6600002, /* beq a3, return */ |
|
0xe6600002, |
|
187 |
|
|
188 |
/* The rest of the load/store code was written with t3 as the address. */ |
/* The rest of the load/store code was written with t3 as the address. */ |
|
|
|
189 |
/* Add the offset within the page: */ |
/* Add the offset within the page: */ |
190 |
/* 04 04 62 42 addq a3,t1,t3 */ |
0x42640404, /* addq a3,t3,t3 */ |
191 |
0x42620404, |
0x6be58000, /* ret (t4) */ |
|
|
|
|
0x6be50000, /* jmp (t4) */ |
|
192 |
|
|
193 |
/* return: */ |
/* return: */ |
194 |
0x243f0000 | (BINTRANS_DONT_RUN_NEXT >> 16), /* ldah t0,256 */ |
0x243f0000 | (BINTRANS_DONT_RUN_NEXT >> 16), /* ldah t0,256 */ |
195 |
0x44270407, /* or t0,t6,t6 */ |
0x44270407, /* or t0,t6,t6 */ |
196 |
0x6bfa8001 /* ret */ |
0x6bfa8000 /* ret */ |
197 |
}; |
}; |
198 |
|
|
199 |
static uint32_t bintrans_alpha_store_32bit[18] = { |
static uint32_t bintrans_alpha_store_32bit[18] = { |
200 |
/* |
0x4a21f622, /* zapnot a1,0xf,t1 */ |
201 |
* t1 = 1023; |
0x209f0fff, /* lda t3,4095 */ |
202 |
* t2 = ((a1 >> 22) & t1) * sizeof(void *); |
0x48419682, /* srl t1,0xc,t1 t1 = addr >> 12 */ |
203 |
* t3 = ((a1 >> 12) & t1) * sizeof(void *); |
0x46240004, /* and a1,t3,t3 t3 = addr & 4095 */ |
204 |
* t1 = a1 & 4095; |
0x404f0642, /* s8addq t1,s6,t1 &host_store[t1] */ |
205 |
* |
0xa6620000, /* ldq a3,0(t1) a3 = host_store[t1] */ |
|
* f8 1f 5f 20 lda t1,1023 * 8 |
|
|
* 83 76 22 4a srl a1,19,t2 |
|
|
* 84 36 21 4a srl a1, 9,t3 |
|
|
* 03 00 62 44 and t2,t1,t2 |
|
|
*/ |
|
|
0x205f1ff8, |
|
|
0x4a227683, |
|
|
0x4a213684, |
|
|
0x44620003, |
|
|
|
|
|
/* |
|
|
* t10 is vaddr_to_hostaddr_table0 |
|
|
* |
|
|
* a3 = tbl0[t2] (load entry from tbl0) |
|
|
* 12 04 03 43 addq t10,t2,a2 |
|
|
*/ |
|
|
0x43030412, |
|
|
|
|
|
/* 04 00 82 44 and t3,t1,t3 */ |
|
|
0x44820004, |
|
|
|
|
|
/* 00 00 72 a6 ldq a3,0(a2) */ |
|
|
0xa6720000, |
|
|
|
|
|
/* 24 37 80 48 sll t3,0x1,t3 */ |
|
|
0x48803724, |
|
|
|
|
|
/* ff 0f 5f 20 lda t1,4095 */ |
|
|
0x205f0fff, |
|
|
|
|
|
/* |
|
|
* a3 = tbl1[t3] (load entry from tbl1 (which is a3)) |
|
|
* 13 04 64 42 addq a3,t3,a3 |
|
|
*/ |
|
|
0x42640413, |
|
|
|
|
|
/* 02 00 22 46 and a1,t1,t1 */ |
|
|
0x46220002, |
|
|
|
|
|
/* 00 00 73 a6 ldq a3,8(a3) */ |
|
|
0xa6730008, |
|
206 |
|
|
207 |
/* NULL? Then return failure at once. */ |
/* NULL? Then return failure at once. */ |
208 |
/* beq a3, return */ |
/* beq a3, return */ |
209 |
0xe6600002, |
0xe6600002, |
210 |
|
|
211 |
/* The rest of the load/store code was written with t3 as the address. */ |
/* The rest of the load/store code was written with t3 as the address. */ |
212 |
|
0x42640404, /* addq a3,t3,t3 */ |
213 |
/* Add the offset within the page: */ |
0x6be58000, /* ret (t4) */ |
|
/* 04 04 62 42 addq a3,t1,t3 */ |
|
|
0x42620404, |
|
|
|
|
|
0x6be50000, /* jmp (t4) */ |
|
214 |
|
|
215 |
/* return: */ |
/* return: */ |
216 |
0x243f0000 | (BINTRANS_DONT_RUN_NEXT >> 16), /* ldah t0,256 */ |
0x243f0000 | (BINTRANS_DONT_RUN_NEXT >> 16), /* ldah t0,256 */ |
217 |
0x44270407, /* or t0,t6,t6 */ |
0x44270407, /* or t0,t6,t6 */ |
218 |
0x6bfa8001 /* ret */ |
0x6bfa8000 /* ret */ |
219 |
}; |
}; |
220 |
|
|
221 |
static void (*bintrans_runchunk)(struct cpu *, unsigned char *); |
static void (*bintrans_runchunk)(struct cpu *, unsigned char *); |
257 |
static void bintrans_write_chunkreturn(unsigned char **addrp) |
static void bintrans_write_chunkreturn(unsigned char **addrp) |
258 |
{ |
{ |
259 |
uint32_t *a = (uint32_t *) *addrp; |
uint32_t *a = (uint32_t *) *addrp; |
260 |
*a++ = 0x6bfa8001; /* ret */ |
*a++ = 0x6bfa8000; /* ret */ |
261 |
*addrp = (unsigned char *) a; |
*addrp = (unsigned char *) a; |
262 |
} |
} |
263 |
|
|
272 |
/* 07 04 27 44 or t0,t6,t6 */ |
/* 07 04 27 44 or t0,t6,t6 */ |
273 |
*a++ = 0x243f0000 | (BINTRANS_DONT_RUN_NEXT >> 16); |
*a++ = 0x243f0000 | (BINTRANS_DONT_RUN_NEXT >> 16); |
274 |
*a++ = 0x44270407; |
*a++ = 0x44270407; |
275 |
*a++ = 0x6bfa8001; /* ret */ |
*a++ = 0x6bfa8000; /* ret */ |
276 |
*addrp = (unsigned char *) a; |
*addrp = (unsigned char *) a; |
277 |
} |
} |
278 |
|
|
371 |
/* |
/* |
372 |
* bintrans_write_instruction__addiu_etc(): |
* bintrans_write_instruction__addiu_etc(): |
373 |
*/ |
*/ |
374 |
static int bintrans_write_instruction__addiu_etc(unsigned char **addrp, |
static int bintrans_write_instruction__addiu_etc( |
375 |
|
struct memory *mem, unsigned char **addrp, |
376 |
int rt, int rs, int imm, int instruction_type) |
int rt, int rs, int imm, int instruction_type) |
377 |
{ |
{ |
378 |
uint32_t *a; |
uint32_t *a; |
530 |
/* |
/* |
531 |
* bintrans_write_instruction__addu_etc(): |
* bintrans_write_instruction__addu_etc(): |
532 |
*/ |
*/ |
533 |
static int bintrans_write_instruction__addu_etc(unsigned char **addrp, |
static int bintrans_write_instruction__addu_etc( |
534 |
|
struct memory *mem, unsigned char **addrp, |
535 |
int rd, int rs, int rt, int sa, int instruction_type) |
int rd, int rs, int rt, int sa, int instruction_type) |
536 |
{ |
{ |
537 |
unsigned char *a, *unmodified = NULL; |
unsigned char *a, *unmodified = NULL; |
1000 |
* Perform the jump by setting cpu->delay_slot = 0 |
* Perform the jump by setting cpu->delay_slot = 0 |
1001 |
* and pc = cpu->delay_jmpaddr. |
* and pc = cpu->delay_jmpaddr. |
1002 |
*/ |
*/ |
1003 |
|
bintrans_move_MIPS_reg_into_Alpha_reg(&a, MIPSREG_PC, ALPHA_T3); |
1004 |
|
bintrans_move_MIPS_reg_into_Alpha_reg(&a, MIPSREG_DELAY_JMPADDR, ALPHA_T5); |
1005 |
|
|
1006 |
/* 00 00 3f 21 lda s0,0 */ |
/* 00 00 3f 21 lda s0,0 */ |
1007 |
*a++ = 0; *a++ = 0; *a++ = 0x3f; *a++ = 0x21; |
*a++ = 0; *a++ = 0; *a++ = 0x3f; *a++ = 0x21; |
1008 |
|
|
|
bintrans_move_MIPS_reg_into_Alpha_reg(&a, MIPSREG_DELAY_JMPADDR, ALPHA_T0); |
|
|
bintrans_move_MIPS_reg_into_Alpha_reg(&a, MIPSREG_PC, ALPHA_T3); |
|
|
bintrans_move_Alpha_reg_into_MIPS_reg(&a, ALPHA_T0, MIPSREG_PC); |
|
1009 |
} |
} |
1010 |
|
|
1011 |
if (potential_chunk_p == NULL) { |
if (potential_chunk_p == NULL) { |
1062 |
* 04 00 82 44 and t3,t1,t3 |
* 04 00 82 44 and t3,t1,t3 |
1063 |
* a3 05 24 40 cmpeq t0,t3,t2 |
* a3 05 24 40 cmpeq t0,t3,t2 |
1064 |
* 01 00 60 f4 bne t2,7c <ok2> |
* 01 00 60 f4 bne t2,7c <ok2> |
1065 |
* 01 80 fa 6b ret |
* 00 80 fa 6b ret |
1066 |
*/ |
*/ |
1067 |
*a++ = 0x00; *a++ = 0xf0; *a++ = 0x5f; *a++ = 0x20; /* lda */ |
*a++ = 0x00; *a++ = 0xf0; *a++ = 0x5f; *a++ = 0x20; /* lda */ |
1068 |
*a++ = 0x01; *a++ = 0x00; *a++ = 0x22; *a++ = 0x44; /* and */ |
*a++ = 0x01; *a++ = 0x00; *a++ = 0x22; *a++ = 0x44; /* and */ |
1069 |
*a++ = 0x04; *a++ = 0x00; *a++ = 0x82; *a++ = 0x44; /* and */ |
*a++ = 0x04; *a++ = 0x00; *a++ = 0x82; *a++ = 0x44; /* and */ |
1070 |
*a++ = 0xa3; *a++ = 0x05; *a++ = 0x24; *a++ = 0x40; /* cmpeq */ |
*a++ = 0xa3; *a++ = 0x05; *a++ = 0x24; *a++ = 0x40; /* cmpeq */ |
1071 |
*a++ = 0x01; *a++ = 0x00; *a++ = 0x60; *a++ = 0xf4; /* bne */ |
*a++ = 0x01; *a++ = 0x00; *a++ = 0x60; *a++ = 0xf4; /* bne */ |
1072 |
*a++ = 0x01; *a++ = 0x80; *a++ = 0xfa; *a++ = 0x6b; /* ret */ |
*a++ = 0x00; *a++ = 0x80; *a++ = 0xfa; *a++ = 0x6b; /* ret */ |
1073 |
|
|
1074 |
/* Don't execute too many instructions. (see comment below) */ |
/* Don't execute too many instructions. (see comment below) */ |
1075 |
*a++ = (N_SAFE_BINTRANS_LIMIT-1)&255; *a++ = ((N_SAFE_BINTRANS_LIMIT-1) >> 8)&255; |
*a++ = (N_SAFE_BINTRANS_LIMIT-1)&255; *a++ = ((N_SAFE_BINTRANS_LIMIT-1) >> 8)&255; |
1076 |
*a++ = 0x5f; *a++ = 0x20; /* lda t1,0x1fff */ |
*a++ = 0x5f; *a++ = 0x20; /* lda t1,0x1fff */ |
1077 |
*a++ = 0xa1; *a++ = 0x0d; *a++ = 0xe2; *a++ = 0x40; /* cmple t6,t1,t0 */ |
*a++ = 0xa1; *a++ = 0x0d; *a++ = 0xe2; *a++ = 0x40; /* cmple t6,t1,t0 */ |
1078 |
*a++ = 0x01; *a++ = 0x00; *a++ = 0x20; *a++ = 0xf4; /* bne */ |
*a++ = 0x01; *a++ = 0x00; *a++ = 0x20; *a++ = 0xf4; /* bne */ |
1079 |
*a++ = 0x01; *a++ = 0x80; *a++ = 0xfa; *a++ = 0x6b; /* ret */ |
*a++ = 0x00; *a++ = 0x80; *a++ = 0xfa; *a++ = 0x6b; /* ret */ |
1080 |
|
|
1081 |
/* 15 bits at a time, which means max 60 bits, but |
/* 15 bits at a time, which means max 60 bits, but |
1082 |
that should be enough. the top 4 bits are probably |
that should be enough. the top 4 bits are probably |
1143 |
*a++ = 0x00; *a++ = 0x00; *a++ = 0xe1; *a++ = 0x6b; /* jmp (t0) */ |
*a++ = 0x00; *a++ = 0x00; *a++ = 0xe1; *a++ = 0x6b; /* jmp (t0) */ |
1144 |
|
|
1145 |
/* Failure, then return to the main loop. */ |
/* Failure, then return to the main loop. */ |
1146 |
*a++ = 0x01; *a++ = 0x80; *a++ = 0xfa; *a++ = 0x6b; /* ret */ |
*a++ = 0x00; *a++ = 0x80; *a++ = 0xfa; *a++ = 0x6b; /* ret */ |
1147 |
} |
} |
1148 |
} else { |
} else { |
1149 |
/* |
/* |
1165 |
*a++ = 0x5f; *a++ = 0x20; /* lda t1,0x1fff */ |
*a++ = 0x5f; *a++ = 0x20; /* lda t1,0x1fff */ |
1166 |
*a++ = 0xa1; *a++ = 0x0d; *a++ = 0xe2; *a++ = 0x40; /* cmple t6,t1,t0 */ |
*a++ = 0xa1; *a++ = 0x0d; *a++ = 0xe2; *a++ = 0x40; /* cmple t6,t1,t0 */ |
1167 |
*a++ = 0x01; *a++ = 0x00; *a++ = 0x20; *a++ = 0xf4; /* bne */ |
*a++ = 0x01; *a++ = 0x00; *a++ = 0x20; *a++ = 0xf4; /* bne */ |
1168 |
*a++ = 0x01; *a++ = 0x80; *a++ = 0xfa; *a++ = 0x6b; /* ret */ |
*a++ = 0x00; *a++ = 0x80; *a++ = 0xfa; *a++ = 0x6b; /* ret */ |
1169 |
} |
} |
1170 |
|
|
1171 |
/* |
/* |
1247 |
*a++ = 0x00; *a++ = 0x00; *a++ = 0xe1; *a++ = 0x6b; /* jmp (t0) */ |
*a++ = 0x00; *a++ = 0x00; *a++ = 0xe1; *a++ = 0x6b; /* jmp (t0) */ |
1248 |
|
|
1249 |
/* "Failure", then let's return to the main loop. */ |
/* "Failure", then let's return to the main loop. */ |
1250 |
*a++ = 0x01; *a++ = 0x80; *a++ = 0xfa; *a++ = 0x6b; /* ret */ |
*a++ = 0x00; *a++ = 0x80; *a++ = 0xfa; *a++ = 0x6b; /* ret */ |
1251 |
} |
} |
1252 |
} |
} |
1253 |
|
|
1267 |
*/ |
*/ |
1268 |
static int bintrans_write_instruction__loadstore( |
static int bintrans_write_instruction__loadstore( |
1269 |
struct memory *mem, unsigned char **addrp, |
struct memory *mem, unsigned char **addrp, |
1270 |
int rt, int imm, int rs, int instruction_type, int bigendian) |
int rt, int imm, int rs, int instruction_type, int bigendian, |
1271 |
|
int do_alignment_check) |
1272 |
{ |
{ |
1273 |
unsigned char *a, *fail, *generic64bit = NULL, *generic64bitA = NULL; |
unsigned char *a, *fail, *generic64bit = NULL, *generic64bitA = NULL; |
1274 |
unsigned char *doloadstore = NULL, |
unsigned char *doloadstore = NULL, |
1275 |
*ok_unaligned_load3, *ok_unaligned_load2, *ok_unaligned_load1; |
*ok_unaligned_load3, *ok_unaligned_load2, *ok_unaligned_load1; |
1276 |
uint32_t *b; |
uint32_t *b; |
1277 |
|
int need_imm_lda = 0; |
1278 |
int ofs, alignment, load = 0, alpha_rs, alpha_rt, unaligned = 0; |
int ofs, alignment, load = 0, alpha_rs, alpha_rt, unaligned = 0; |
1279 |
|
|
1280 |
/* TODO: Not yet: */ |
/* TODO: Not yet: */ |
1317 |
/* |
/* |
1318 |
* a1 = gpr[rs] + imm; |
* a1 = gpr[rs] + imm; |
1319 |
* |
* |
1320 |
* 88 08 30 a4 ldq t0,2184(a0) |
* rs_ofs 30 a4 ldq a1,rs(a0) |
1321 |
* 34 12 21 22 lda a1,4660(t0) |
* imm 21 22 lda a1,imm(a1) |
1322 |
*/ |
*/ |
1323 |
|
|
1324 |
alpha_rs = map_MIPS_to_Alpha[rs]; |
alpha_rs = map_MIPS_to_Alpha[rs]; |
1325 |
if (alpha_rs < 0) { |
if (alpha_rs < 0) { |
1326 |
bintrans_move_MIPS_reg_into_Alpha_reg(&a, rs, ALPHA_T0); |
bintrans_move_MIPS_reg_into_Alpha_reg(&a, rs, ALPHA_A1); |
1327 |
alpha_rs = ALPHA_T0; |
alpha_rs = ALPHA_A1; |
1328 |
|
} else |
1329 |
|
need_imm_lda = 1; |
1330 |
|
|
1331 |
|
if (imm != 0 || need_imm_lda) { |
1332 |
|
*a++ = imm; *a++ = (imm >> 8); |
1333 |
|
*a++ = 0x20 + alpha_rs; *a++ = 0x22; |
1334 |
} |
} |
|
*a++ = imm; *a++ = (imm >> 8); *a++ = 0x20 + alpha_rs; *a++ = 0x22; |
|
1335 |
|
|
1336 |
alignment = 0; |
alignment = 0; |
1337 |
switch (instruction_type) { |
switch (instruction_type) { |
1374 |
*/ |
*/ |
1375 |
*a++ = 0x02; *a++ = 0x10 + alignment * 0x20; *a++ = 0x20 + (alignment >> 3); *a++ = 0x46; |
*a++ = 0x02; *a++ = 0x10 + alignment * 0x20; *a++ = 0x20 + (alignment >> 3); *a++ = 0x46; |
1376 |
*a++ = 0x31; *a++ = 0x05; *a++ = 0x22; *a++ = 0x42; |
*a++ = 0x31; *a++ = 0x05; *a++ = 0x22; *a++ = 0x42; |
1377 |
} else if (alignment > 0) { |
} else if (alignment > 0 && do_alignment_check) { |
1378 |
/* |
/* |
1379 |
* Check alignment: |
* Check alignment: |
1380 |
* |
* |
1383 |
* 02 f0 20 46 and a1,0x7,t1 |
* 02 f0 20 46 and a1,0x7,t1 |
1384 |
* 02 f0 21 46 and a1,0xf,t1 |
* 02 f0 21 46 and a1,0xf,t1 |
1385 |
* 01 00 40 e4 beq t1,<okalign> |
* 01 00 40 e4 beq t1,<okalign> |
1386 |
* 01 80 fa 6b ret |
* 00 80 fa 6b ret |
1387 |
*/ |
*/ |
1388 |
*a++ = 0x02; *a++ = 0x10 + alignment * 0x20; *a++ = 0x20 + (alignment >> 3); *a++ = 0x46; |
*a++ = 0x02; *a++ = 0x10 + alignment * 0x20; *a++ = 0x20 + (alignment >> 3); *a++ = 0x46; |
1389 |
fail = a; |
fail = a; |
2504 |
case CALL_ERET: |
case CALL_ERET: |
2505 |
case CALL_BREAK: |
case CALL_BREAK: |
2506 |
case CALL_SYSCALL: |
case CALL_SYSCALL: |
2507 |
|
/* Increase the nr of instructions: */ |
2508 |
|
a = (uint32_t *) *addrp; |
2509 |
|
*a++ = 0x20e70001; /* lda t6,1(t6) */ |
2510 |
|
*addrp = (unsigned char *) a; |
2511 |
break; |
break; |
2512 |
default: |
default: |
2513 |
bintrans_write_pc_inc(addrp); |
bintrans_write_pc_inc(addrp); |
2568 |
*p++ = 0xa5900000 | ofs_ra; /* ldq s3,"gpr[ra]"(a0) */ |
*p++ = 0xa5900000 | ofs_ra; /* ldq s3,"gpr[ra]"(a0) */ |
2569 |
*p++ = 0xa5b00000 | ofs_t0; /* ldq s4,"gpr[t0]"(a0) */ |
*p++ = 0xa5b00000 | ofs_t0; /* ldq s4,"gpr[t0]"(a0) */ |
2570 |
*p++ = 0xa5d00000 | ofs_t1; /* ldq s5,"gpr[t1]"(a0) */ |
*p++ = 0xa5d00000 | ofs_t1; /* ldq s5,"gpr[t1]"(a0) */ |
2571 |
*p++ = 0xa5f00000 | ofs_t2; /* ldq s6,"gpr[t2]"(a0) */ |
*p++ = 0xa5f00000 | ofs_h_s; /* ldq s6,host_store(a0) */ |
2572 |
*p++ = 0xa7100000 | ofs_tbl0; /* ldq t10,table0(a0) */ |
*p++ = 0xa7100000 | ofs_h_l; /* ldq t10,host_load(a0) */ |
2573 |
*p++ = 0xa7300000 | ofs_v0; /* ldq t11,"gpr[v0]"(a0) */ |
*p++ = 0xa7300000 | ofs_v0; /* ldq t11,"gpr[v0]"(a0) */ |
2574 |
|
|
2575 |
*p++ = 0x6b514000; /* jsr ra,(a1),<back> */ |
*p++ = 0x6b514000; /* jsr ra,(a1),<back> */ |
2585 |
*p++ = 0xb5900000 | ofs_ra; /* stq s3,"gpr[ra]"(a0) */ |
*p++ = 0xb5900000 | ofs_ra; /* stq s3,"gpr[ra]"(a0) */ |
2586 |
*p++ = 0xb5b00000 | ofs_t0; /* stq s4,"gpr[t0]"(a0) */ |
*p++ = 0xb5b00000 | ofs_t0; /* stq s4,"gpr[t0]"(a0) */ |
2587 |
*p++ = 0xb5d00000 | ofs_t1; /* stq s5,"gpr[t1]"(a0) */ |
*p++ = 0xb5d00000 | ofs_t1; /* stq s5,"gpr[t1]"(a0) */ |
|
*p++ = 0xb5f00000 | ofs_t2; /* stq s6,"gpr[t2]"(a0) */ |
|
2588 |
*p++ = 0xb7300000 | ofs_v0; /* stq t11,"gpr[v0]"(a0) */ |
*p++ = 0xb7300000 | ofs_v0; /* stq t11,"gpr[v0]"(a0) */ |
2589 |
|
|
2590 |
*p++ = 0xa75e0000; /* ldq ra,0(sp) */ |
*p++ = 0xa75e0000; /* ldq ra,0(sp) */ |
2597 |
*p++ = 0xa5fe0038; /* ldq s6,56(sp) */ |
*p++ = 0xa5fe0038; /* ldq s6,56(sp) */ |
2598 |
*p++ = 0xa7be0058; /* ldq gp,0x58(sp) */ |
*p++ = 0xa7be0058; /* ldq gp,0x58(sp) */ |
2599 |
*p++ = 0x23de0060; /* lda sp,0x60(sp) */ |
*p++ = 0x23de0060; /* lda sp,0x60(sp) */ |
2600 |
*p++ = 0x6bfa8001; /* ret */ |
*p++ = 0x6bfa8000; /* ret */ |
2601 |
|
|
2602 |
|
|
2603 |
/* "jump to 32bit pc": */ |
/* "jump to 32bit pc": */ |
2623 |
q = p; /* *q is updated later */ |
q = p; /* *q is updated later */ |
2624 |
*p++ = 0xe4200001; /* beq ret (far below) */ |
*p++ = 0xe4200001; /* beq ret (far below) */ |
2625 |
|
|
|
*p++ = 0x40c01411; /* addq t5,0,a1 */ |
|
|
|
|
2626 |
/* |
/* |
2627 |
* Special case for 32-bit addressing: |
* Special case for 32-bit addressing: |
2628 |
* |
* |
2629 |
* t1 = 1023; |
* t1 = 1023; |
2630 |
* t2 = ((a1 >> 22) & t1) * sizeof(void *); |
* t2 = ((pc >> 22) & t1) * sizeof(void *); |
2631 |
* t3 = ((a1 >> 12) & t1) * sizeof(void *); |
* t3 = ((pc >> 12) & t1) * sizeof(void *); |
2632 |
* t1 = a1 & 4095; |
* t1 = pc & 4095; |
2633 |
*/ |
*/ |
2634 |
*p++ = 0x205f1ff8; /* lda t1,1023 * 8 */ |
*p++ = 0x205f1ff8; /* lda t1,1023 * 8 */ |
2635 |
*p++ = 0x4a227683; /* srl a1,19,t2 */ |
*p++ = 0x48c27683; /* srl t5,19,t2 */ |
2636 |
*p++ = 0x4a213684; /* srl a1, 9,t3 */ |
*p++ = 0x48c13684; /* srl t5, 9,t3 */ |
2637 |
|
|
2638 |
*p++ = 0x44620003; /* and t2,t1,t2 */ |
*p++ = 0x44620003; /* and t2,t1,t2 */ |
2639 |
|
|
2640 |
/* |
/* ldq a2, vaddr_to_hostaddr_table0(a0) */ |
2641 |
* t10 is vaddr_to_hostaddr_table0 |
*p++ = 0xa6500000 | ofs_tbl0; |
2642 |
* |
|
2643 |
* a3 = tbl0[t2] (load entry from tbl0) |
/* a3 = tbl0[t2] (load entry from tbl0) */ |
2644 |
*/ |
*p++ = 0x40720412; /* addq t2,a2,a2 */ |
|
*p++ = 0x43030412; /* addq t10,t2,a2 */ |
|
2645 |
*p++ = 0x44820004; /* and t3,t1,t3 */ |
*p++ = 0x44820004; /* and t3,t1,t3 */ |
2646 |
*p++ = 0xa6720000; /* ldq a3,0(a2) */ |
*p++ = 0xa6720000; /* ldq a3,0(a2) */ |
2647 |
*p++ = 0x205f0ffc; /* lda t1,0xffc */ |
*p++ = 0x205f0ffc; /* lda t1,0xffc */ |
2650 |
* a3 = tbl1[t3] (load entry from tbl1 (which is a3)) |
* a3 = tbl1[t3] (load entry from tbl1 (which is a3)) |
2651 |
*/ |
*/ |
2652 |
*p++ = 0x42640413; /* addq a3,t3,a3 */ |
*p++ = 0x42640413; /* addq a3,t3,a3 */ |
|
*p++ = 0x46220002; /* and a1,t1,t1 */ |
|
2653 |
|
|
2654 |
*p++ = 0xa6730000 | ofs_c0; /* ldq a3,chunks[0](a3) */ |
*p++ = 0xa6730000 | ofs_c0; /* ldq a3,chunks[0](a3) */ |
2655 |
|
|
2656 |
|
*p++ = 0x44c20002; /* and t5,t1,t1 */ |
2657 |
|
|
2658 |
/* |
/* |
2659 |
* NULL? Then just return. |
* NULL? Then just return. |
2660 |
*/ |
*/ |
2664 |
*p++ = 0x40530402; /* addq t1,a3,t1 */ |
*p++ = 0x40530402; /* addq t1,a3,t1 */ |
2665 |
*p++ = 0xa0220000; /* ldl t0,0(t1) */ |
*p++ = 0xa0220000; /* ldl t0,0(t1) */ |
2666 |
|
|
|
/* No translation? Then return. */ |
|
|
*p++ = 0xe4200003; /* beq t0,<skip> */ |
|
|
|
|
2667 |
*p++ = 0xa4700000 | ofs_cb; /* ldq t2,chunk_base_address(a0) */ |
*p++ = 0xa4700000 | ofs_cb; /* ldq t2,chunk_base_address(a0) */ |
2668 |
|
|
2669 |
|
/* No translation? Then return. */ |
2670 |
|
*p++ = 0xe4200002; /* beq t0,<skip> */ |
2671 |
|
|
2672 |
*p++ = 0x40230401; /* addq t0,t2,t0 */ |
*p++ = 0x40230401; /* addq t0,t2,t0 */ |
2673 |
*p++ = 0x6be10000; /* jmp (t0) */ |
*p++ = 0x6be10000; /* jmp (t0) */ |
2674 |
|
|