ppc: Convert CRF moves to TCG

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>

git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5158 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
aurel32 2008-09-04 17:06:47 +00:00
parent ec1ac72d9c
commit 47e4661cc4
4 changed files with 34 additions and 121 deletions

View File

@ -551,7 +551,7 @@ struct CPUPPCState {
/* CTR */ /* CTR */
target_ulong ctr; target_ulong ctr;
/* condition register */ /* condition register */
uint8_t crf[8]; uint32_t crf[8];
/* XER */ /* XER */
/* XXX: We use only 5 fields, but we want to keep the structure aligned */ /* XXX: We use only 5 fields, but we want to keep the structure aligned */
uint8_t xer[8]; uint8_t xer[8];

View File

@ -26,30 +26,6 @@
#include "helper_regs.h" #include "helper_regs.h"
#include "op_helper.h" #include "op_helper.h"
#define REG 0
#include "op_template.h"
#define REG 1
#include "op_template.h"
#define REG 2
#include "op_template.h"
#define REG 3
#include "op_template.h"
#define REG 4
#include "op_template.h"
#define REG 5
#include "op_template.h"
#define REG 6
#include "op_template.h"
#define REG 7
#include "op_template.h"
void OPPROTO op_print_mem_EA (void) void OPPROTO op_print_mem_EA (void)
{ {
do_print_mem_EA(T0); do_print_mem_EA(T0);
@ -102,18 +78,6 @@ void OPPROTO op_store_cr (void)
RETURN(); RETURN();
} }
void OPPROTO op_load_cro (void)
{
T0 = env->crf[PARAM1];
RETURN();
}
void OPPROTO op_store_cro (void)
{
env->crf[PARAM1] = T0;
RETURN();
}
void OPPROTO op_load_xer_cr (void) void OPPROTO op_load_xer_cr (void)
{ {
T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1); T0 = (xer_so << 3) | (xer_ov << 2) | (xer_ca << 1);

View File

@ -1,40 +0,0 @@
/*
* PowerPC emulation micro-operations for qemu.
*
* Copyright (c) 2003-2007 Jocelyn Mayer
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/* Condition register moves */
void OPPROTO glue(op_load_crf_T0_crf, REG) (void)
{
T0 = env->crf[REG];
RETURN();
}
void OPPROTO glue(op_load_crf_T1_crf, REG) (void)
{
T1 = env->crf[REG];
RETURN();
}
void OPPROTO glue(op_store_T0_crf_crf, REG) (void)
{
env->crf[REG] = T0;
RETURN();
}
#undef REG

View File

@ -51,13 +51,15 @@ static char cpu_reg_names[10*3 + 22*4 /* GPR */
+ 10*4 + 22*5 /* SPE GPRh */ + 10*4 + 22*5 /* SPE GPRh */
#endif #endif
+ 10*4 + 22*5 /* FPR */ + 10*4 + 22*5 /* FPR */
+ 2*(10*6 + 22*7) /* AVRh, AVRl */]; + 2*(10*6 + 22*7) /* AVRh, AVRl */
+ 8*5 /* CRF */];
static TCGv cpu_gpr[32]; static TCGv cpu_gpr[32];
#if !defined(TARGET_PPC64) #if !defined(TARGET_PPC64)
static TCGv cpu_gprh[32]; static TCGv cpu_gprh[32];
#endif #endif
static TCGv cpu_fpr[32]; static TCGv cpu_fpr[32];
static TCGv cpu_avrh[32], cpu_avrl[32]; static TCGv cpu_avrh[32], cpu_avrl[32];
static TCGv cpu_crf[8];
/* dyngen register indexes */ /* dyngen register indexes */
static TCGv cpu_T[3]; static TCGv cpu_T[3];
@ -126,6 +128,14 @@ void ppc_translate_init(void)
offsetof(CPUState, avr2.u64[1]), "AVR2L"); offsetof(CPUState, avr2.u64[1]), "AVR2L");
p = cpu_reg_names; p = cpu_reg_names;
for (i = 0; i < 8; i++) {
sprintf(p, "crf%d", i);
cpu_crf[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
offsetof(CPUState, crf[i]), p);
p += 5;
}
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
sprintf(p, "r%d", i); sprintf(p, "r%d", i);
cpu_gpr[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0, cpu_gpr[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
@ -167,16 +177,6 @@ static uint16_t *gen_fprf_buf[OPC_BUF_SIZE];
static uint16_t **gen_fprf_ptr; static uint16_t **gen_fprf_ptr;
#endif #endif
#define GEN8(func, NAME) \
static GenOpFunc *NAME ## _table [8] = { \
NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
}; \
static always_inline void func (int n) \
{ \
NAME ## _table[n](); \
}
#define GEN16(func, NAME) \ #define GEN16(func, NAME) \
static GenOpFunc *NAME ## _table [16] = { \ static GenOpFunc *NAME ## _table [16] = { \
NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \ NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
@ -205,14 +205,6 @@ static always_inline void func (int n) \
NAME ## _table[n](); \ NAME ## _table[n](); \
} }
/* Condition register moves */
GEN8(gen_op_load_crf_T0, gen_op_load_crf_T0_crf);
GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf);
GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf);
#if 0 // Unused
GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf);
#endif
/* internal defines */ /* internal defines */
typedef struct DisasContext { typedef struct DisasContext {
struct TranslationBlock *tb; struct TranslationBlock *tb;
@ -278,12 +270,12 @@ static always_inline void gen_compute_fprf (int set_fprf, int set_rc)
#endif #endif
gen_op_compute_fprf(1); gen_op_compute_fprf(1);
if (unlikely(set_rc)) if (unlikely(set_rc))
gen_op_store_T0_crf(1); tcg_gen_andi_i32(cpu_crf[1], cpu_T[0], 0xf);
gen_op_float_check_status(); gen_op_float_check_status();
} else if (unlikely(set_rc)) { } else if (unlikely(set_rc)) {
/* We always need to compute fpcc */ /* We always need to compute fpcc */
gen_op_compute_fprf(0); gen_op_compute_fprf(0);
gen_op_store_T0_crf(1); tcg_gen_andi_i32(cpu_crf[1], cpu_T[0], 0xf);
if (set_fprf) if (set_fprf)
gen_op_float_check_status(); gen_op_float_check_status();
} }
@ -1158,7 +1150,7 @@ GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type) \
gen_op_##name##_64(); \ gen_op_##name##_64(); \
else \ else \
gen_op_##name(); \ gen_op_##name(); \
gen_op_store_T0_crf(crfD(ctx->opcode)); \ tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf); \
} }
#else #else
#define GEN_CMP(name, opc, type) \ #define GEN_CMP(name, opc, type) \
@ -1167,7 +1159,7 @@ GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type) \
tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \ tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); \ tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); \
gen_op_##name(); \ gen_op_##name(); \
gen_op_store_T0_crf(crfD(ctx->opcode)); \ tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf); \
} }
#endif #endif
@ -1183,7 +1175,7 @@ GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
else else
#endif #endif
gen_op_cmpi(SIMM(ctx->opcode)); gen_op_cmpi(SIMM(ctx->opcode));
gen_op_store_T0_crf(crfD(ctx->opcode)); tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);
} }
/* cmpl */ /* cmpl */
GEN_CMP(cmpl, 0x01, PPC_INTEGER); GEN_CMP(cmpl, 0x01, PPC_INTEGER);
@ -1197,7 +1189,7 @@ GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
else else
#endif #endif
gen_op_cmpli(UIMM(ctx->opcode)); gen_op_cmpli(UIMM(ctx->opcode));
gen_op_store_T0_crf(crfD(ctx->opcode)); tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);
} }
/* isel (PowerPC 2.03 specification) */ /* isel (PowerPC 2.03 specification) */
@ -1213,7 +1205,7 @@ GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL)
} }
tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]); tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
mask = 1 << (3 - (bi & 0x03)); mask = 1 << (3 - (bi & 0x03));
gen_op_load_crf_T0(bi >> 2); tcg_gen_mov_i32(cpu_T[0], cpu_crf[bi >> 2]);
gen_op_test_true(mask); gen_op_test_true(mask);
gen_op_isel(); gen_op_isel();
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
@ -1977,7 +1969,7 @@ GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rB(ctx->opcode)]); tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rB(ctx->opcode)]);
gen_reset_fpstatus(); gen_reset_fpstatus();
gen_op_fcmpo(); gen_op_fcmpo();
gen_op_store_T0_crf(crfD(ctx->opcode)); tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);
gen_op_float_check_status(); gen_op_float_check_status();
} }
@ -1992,7 +1984,7 @@ GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rB(ctx->opcode)]); tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rB(ctx->opcode)]);
gen_reset_fpstatus(); gen_reset_fpstatus();
gen_op_fcmpu(); gen_op_fcmpu();
gen_op_store_T0_crf(crfD(ctx->opcode)); tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);
gen_op_float_check_status(); gen_op_float_check_status();
} }
@ -2034,7 +2026,7 @@ GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
gen_optimize_fprf(); gen_optimize_fprf();
bfa = 4 * (7 - crfS(ctx->opcode)); bfa = 4 * (7 - crfS(ctx->opcode));
gen_op_load_fpscr_T0(bfa); gen_op_load_fpscr_T0(bfa);
gen_op_store_T0_crf(crfD(ctx->opcode)); tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);
gen_op_fpscr_resetbit(~(0xF << bfa)); gen_op_fpscr_resetbit(~(0xF << bfa));
} }
@ -3015,7 +3007,7 @@ static always_inline void gen_bcond (DisasContext *ctx, int type)
} }
} else { } else {
mask = 1 << (3 - (bi & 0x03)); mask = 1 << (3 - (bi & 0x03));
gen_op_load_crf_T0(bi >> 2); tcg_gen_mov_i32(cpu_T[0], cpu_crf[bi >> 2]);
if (bo & 0x8) { if (bo & 0x8) {
switch (bo & 0x6) { switch (bo & 0x6) {
case 0: case 0:
@ -3109,13 +3101,13 @@ GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) \
{ \ { \
uint8_t bitmask; \ uint8_t bitmask; \
int sh; \ int sh; \
gen_op_load_crf_T0(crbA(ctx->opcode) >> 2); \ tcg_gen_mov_i32(cpu_T[0], cpu_crf[crbA(ctx->opcode) >> 2]); \
sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03); \ sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03); \
if (sh > 0) \ if (sh > 0) \
gen_op_srli_T0(sh); \ gen_op_srli_T0(sh); \
else if (sh < 0) \ else if (sh < 0) \
gen_op_sli_T0(-sh); \ gen_op_sli_T0(-sh); \
gen_op_load_crf_T1(crbB(ctx->opcode) >> 2); \ tcg_gen_mov_i32(cpu_T[1], cpu_crf[crbB(ctx->opcode) >> 2]); \
sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03); \ sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03); \
if (sh > 0) \ if (sh > 0) \
gen_op_srli_T1(sh); \ gen_op_srli_T1(sh); \
@ -3124,10 +3116,9 @@ GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) \
gen_op_##op(); \ gen_op_##op(); \
bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03)); \ bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03)); \
gen_op_andi_T0(bitmask); \ gen_op_andi_T0(bitmask); \
gen_op_load_crf_T1(crbD(ctx->opcode) >> 2); \ tcg_gen_andi_i32(cpu_T[1], cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask); \
gen_op_andi_T1(~bitmask); \
gen_op_or(); \ gen_op_or(); \
gen_op_store_T0_crf(crbD(ctx->opcode) >> 2); \ tcg_gen_andi_i32(cpu_crf[crbD(ctx->opcode) >> 2], cpu_T[0], 0xf); \
} }
/* crand */ /* crand */
@ -3149,8 +3140,7 @@ GEN_CRLOGIC(xor, 0x06);
/* mcrf */ /* mcrf */
GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER) GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
{ {
gen_op_load_crf_T0(crfS(ctx->opcode)); tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
gen_op_store_T0_crf(crfD(ctx->opcode));
} }
/*** System linkage ***/ /*** System linkage ***/
@ -3264,7 +3254,7 @@ GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B)
GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC) GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
{ {
gen_op_load_xer_cr(); gen_op_load_xer_cr();
gen_op_store_T0_crf(crfD(ctx->opcode)); tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);
gen_op_clear_xer_ov(); gen_op_clear_xer_ov();
gen_op_clear_xer_ca(); gen_op_clear_xer_ca();
} }
@ -3278,7 +3268,7 @@ GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
crm = CRM(ctx->opcode); crm = CRM(ctx->opcode);
if (likely((crm ^ (crm - 1)) == 0)) { if (likely((crm ^ (crm - 1)) == 0)) {
crn = ffs(crm); crn = ffs(crm);
gen_op_load_cro(7 - crn); tcg_gen_mov_i32(cpu_T[0], cpu_crf[7 - crn]);
} }
} else { } else {
gen_op_load_cr(); gen_op_load_cr();
@ -3380,8 +3370,7 @@ GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
if (likely((ctx->opcode & 0x00100000) || (crm ^ (crm - 1)) == 0)) { if (likely((ctx->opcode & 0x00100000) || (crm ^ (crm - 1)) == 0)) {
crn = ffs(crm); crn = ffs(crm);
gen_op_srli_T0(crn * 4); gen_op_srli_T0(crn * 4);
gen_op_andi_T0(0xF); tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_T[0], 0xf);
gen_op_store_cro(7 - crn);
} else { } else {
gen_op_store_cr(crm); gen_op_store_cr(crm);
} }
@ -5244,7 +5233,7 @@ GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC)
gen_op_store_xer_bc(); gen_op_store_xer_bc();
if (Rc(ctx->opcode)) { if (Rc(ctx->opcode)) {
gen_op_440_dlmzb_update_Rc(); gen_op_440_dlmzb_update_Rc();
gen_op_store_T0_crf(0); tcg_gen_andi_i32(cpu_crf[0], cpu_T[0], 0xf);
} }
} }
@ -5493,7 +5482,7 @@ static always_inline void gen_##name (DisasContext *ctx) \
gen_load_gpr64(cpu_T64[0], rA(ctx->opcode)); \ gen_load_gpr64(cpu_T64[0], rA(ctx->opcode)); \
gen_load_gpr64(cpu_T64[1], rB(ctx->opcode)); \ gen_load_gpr64(cpu_T64[1], rB(ctx->opcode)); \
gen_op_##name(); \ gen_op_##name(); \
gen_op_store_T0_crf(crfD(ctx->opcode)); \ tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf); \
} }
/* Logical */ /* Logical */
@ -5625,7 +5614,7 @@ static always_inline void gen_evsel (DisasContext *ctx)
GEN_EXCP_NO_AP(ctx); GEN_EXCP_NO_AP(ctx);
return; return;
} }
gen_op_load_crf_T0(ctx->opcode & 0x7); tcg_gen_mov_i32(cpu_T[0], cpu_crf[ctx->opcode & 0x7]);
gen_load_gpr64(cpu_T64[0], rA(ctx->opcode)); gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));
gen_load_gpr64(cpu_T64[1], rB(ctx->opcode)); gen_load_gpr64(cpu_T64[1], rB(ctx->opcode));
gen_op_evsel(); gen_op_evsel();