LOGIN   :::   RECOVER PASS   :::   GET ACCOUNT    
Browse
  • Projects
  • Code (CVS)
  • Forums
  • News
  • Articles
  • Polls
  •  
    OpenCores
  • FAQ
  • CVS HowTo
  • Mission
  • Media
  • Tools
  • Advertise
  • Mirrors
  • Logos
  • Contact us
  • Find Resources
  • Job Opportunity
  •  
    Tools
  • Search
      
  • Download Cores (CVSGet)
  •  
    More
  • Wishbone
  • Perlilog
  • EDA tools
  • OpenTech CD
  •  
    Navigation: All forums > Openrisc > Message List > Message Post

    Message

    Reply | Reply all
    Date Prev | Date Next | Thread Prev | Thread Next Date Index | Thread Index

    From: =?unknown-8bit?Q?Gy=F6rgy?= 'nog' Jeney<nog@s...>
    Date: Tue Jan 25 21:18:32 CET 2005
    Subject: [openrisc] [or1ksim #6] Remove global op variable
    Top
    Hi,

    This patch removes the global op structure and all the administration that comes
    with it. This patch has a noticable speed improvement when booting linux,
    though it is only slight.

    I have basically rewritten depend_operands. It was basically useless. Among
    others the last operand would never have been checked.

    I have again modified or32.c to set the OPTYPE_DIS flag on all the operands that
    are part of the immediate value and not just the last. I have checked and this
    change does not break anything in gdb or binutils.

    ChangeLog:
    * Remove the global op structure.

    nog.
    -------------- next part --------------
    --- cpu/or32/execute.c 2005-01-25 19:04:57.000000000 +0100
    +++ ../or1ksim-ac/cpu/or32/execute.c 2005-01-25 20:56:50.000000000 +0100
    @@ -1,5 +1,6 @@
    /* execute.c -- OR1K architecture dependent simulation
    Copyright (C) 1999 Damjan Lampret, lampret@o...
    + Copyright (C) 2005 Gy?rgy `nog' Jeney, nog@s...

    This file is part of OpenRISC 1000 Architectural Simulator.

    @@ -102,8 +103,10 @@
    /* Local data needed for execution. */
    static int next_delay_insn;
    static int breakpoint;
    -static unsigned long *op;
    -static int num_op;
    +
    +/* Effective address of instructions that have an effective address. This is
    + * only used to get dump_exe_log correct */
    +static unsigned long insn_ea;

    /* Implementation specific.
    Get an actual value of a specific register. */
    @@ -182,7 +185,34 @@
    }
    }

    -/* Does srcoperand depend on computation of dstoperand? Return
    +/* Implementation specific.
    + Evaluates source operand opd. */
    +
    +static unsigned long eval_operand_val(unsigned long insn,
    + struct insn_op_struct *opd)
    +{
    + unsigned long operand = 0;
    + unsigned long sbit;
    + unsigned int nbits = 0;
    +
    + while(1) {
    + operand |= ((insn >> (opd->type & OPTYPE_SHR)) & ((1 << opd->data) - 1)) << nbits;
    + nbits += opd->data;
    +
    + if(opd->type & OPTYPE_OP)
    + break;
    + opd++;
    + }
    +
    + if(opd->type & OPTYPE_SIG) {
    + sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR;
    + if(operand & (1 << sbit)) operand |= 0xffffffff << sbit;
    + }
    +
    + return operand;
    +}
    +
    +/* Does source operand depend on computation of dstoperand? Return
    non-zero if yes.

    Cycle t Cycle t+1
    @@ -201,40 +231,61 @@
    {
    /* Find destination type. */
    unsigned long type = 0;
    - int i = 0;
    + int prev_dis, next_dis;
    + unsigned int prev_reg_val = 0;
    + struct insn_op_struct *opd;
    +
    if (or32_opcodes[prev->insn_index].flags & OR32_W_FLAG
    && or32_opcodes[next->insn_index].flags & OR32_R_FLAG)
    return 1;

    - while (!(prev->op[i + MAX_OPERANDS] & OPTYPE_LAST))
    - if (prev->op[i + MAX_OPERANDS] & OPTYPE_DST)
    - {
    - type = prev->op[i + MAX_OPERANDS];
    - break;
    - }
    - else
    - i++;
    + opd = op_start[prev->insn_index];
    + prev_dis = 0;
    +
    + while (1) {
    + if (opd->type & OPTYPE_DIS)
    + prev_dis = 1; + + if (opd->type & OPTYPE_DST) { + type = opd->type; + if (prev_dis) + type |= OPTYPE_DIS; + /* Destination is always a register */ + prev_reg_val = eval_operand_val (prev->insn, opd); + break; + } + if (opd->type & OPTYPE_LAST) + return 0; /* Doesn't have a destination operand */ + if (opd->type & OPTYPE_OP) + prev_dis = 0; + opd++; + } /* We search all source operands - if we find confict => return 1 */ - i = 0; - while (!(next->op[i + MAX_OPERANDS] & OPTYPE_LAST)) - if (!(next->op[i + MAX_OPERANDS] & OPTYPE_DST)) - { - if (next->op[i + MAX_OPERANDS] & OPTYPE_DIS) { - if (type & OPTYPE_DIS) - return 1; - else if (next->op[i] == prev->op[i] - && (next->op[i + MAX_OPERANDS] & OPTYPE_REG)) - return 1; - } - if (next->op[i] == prev->op[i] - && (next->op[i + MAX_OPERANDS] & OPTYPE_REG) - && (type & OPTYPE_REG)) + opd = op_start[next->insn_index]; + next_dis = 0; + + while (1) { + if (opd->type & OPTYPE_DIS) + next_dis = 1; + /* This instruction sequence also depends on order of execution: + * l.lw r1, k(r1) + * l.sw k(r1), r4 + * Here r1 is a destination in l.sw */ + /* FIXME: This situation is not handeld here when r1 == r2: + * l.sw k(r1), r4 + * l.lw r3, k(r2) + */ + if (!(opd->type & OPTYPE_DST) || (next_dis && (opd->type & OPTYPE_DST))) { + if (opd->type & OPTYPE_REG) + if (eval_operand_val (next->insn, opd) == prev_reg_val) return 1; - i++; - } - else - i++; + } + if (opd->type & OPTYPE_LAST) + break; + opd++; + } + return 0; } @@ -427,18 +478,26 @@ /* Outputs dissasembled instruction */ void dump_exe_log () { - unsigned long i = iqueue[0].insn_addr; + unsigned long insn_addr = iqueue[0].insn_addr; + unsigned long i, j; - if (i == 0xffffffff) return; - if (config.sim.exe_log_start <= runtime.cpu.instructions && (config.sim.exe_log_end <= 0 || runtime.cpu.instructions <= config.sim.exe_log_end)) { - if (config.sim.exe_log_marker && runtime.cpu.instructions % config.sim.exe_log_marker == 0) { + if (insn_addr == 0xffffffff) return; + if ((config.sim.exe_log_start <= runtime.cpu.instructions) && + ((config.sim.exe_log_end <= 0) || + (runtime.cpu.instructions <= config.sim.exe_log_end))) { + if (config.sim.exe_log_marker && + !(runtime.cpu.instructions % config.sim.exe_log_marker)) { fprintf (runtime.sim.fexe_log, "--------------------- %8lli instruction ---------------------\n", runtime.cpu.instructions); } switch (config.sim.exe_log_type) { case EXE_LOG_HARDWARE: - fprintf (runtime.sim.fexe_log, "\nEXECUTED(%11llu): %.8lx: ", runtime.cpu.instructions, i); - fprintf (runtime.sim.fexe_log, "%.2x%.2x", evalsim_mem8_void(i), evalsim_mem8_void(i + 1)); - fprintf (runtime.sim.fexe_log, "%.2x%.2x", evalsim_mem8_void(i + 2), evalsim_mem8_void(i + 3)); + fprintf (runtime.sim.fexe_log, "\nEXECUTED(%11llu): %.8lx: ", + runtime.cpu.instructions, insn_addr); + fprintf (runtime.sim.fexe_log, "%.2x%.2x", evalsim_mem8_void(insn_addr), + evalsim_mem8_void(insn_addr + 1)); + fprintf (runtime.sim.fexe_log, "%.2x%.2x", + evalsim_mem8_void(insn_addr + 2), + evalsim_mem8_void(insn_addr + 3)); for(i = 0; i < MAX_GPRS; i++) { if (i % 4 == 0) fprintf(runtime.sim.fexe_log, "\n"); @@ -457,30 +516,40 @@ disassemble_index (iqueue[0].insn, iqueue[0].insn_index); { struct label_entry *entry; - entry = get_label(i); + entry = get_label(insn_addr); if (entry) fprintf (runtime.sim.fexe_log, "%s:\n", entry->name); } if (config.sim.exe_log_type == EXE_LOG_SOFTWARE) { - int i,j=0; + struct insn_op_struct *opd = op_start[iqueue[0].insn_index]; - for (i = 0; i < num_op; i++) - if (op[i + MAX_OPERANDS] & OPTYPE_DIS) { - j=1; - fprintf (runtime.sim.fexe_log, "EA =%08lx PA =%08lx ", op[i], - peek_into_dtlb(op[i],0,0)); - } else if ((op[i + MAX_OPERANDS] & OPTYPE_REG) && op[i]) { - fprintf (runtime.sim.fexe_log, "r%-2li=%08lx ", op[i], - evalsim_reg32 (op[i])); + j = 0; + while (1) { + i = eval_operand_val (iqueue[0].insn, opd); + while (!(opd->type & OPTYPE_OP)) + opd++; + if (opd->type & OPTYPE_DIS) { + fprintf (runtime.sim.fexe_log, "EA =%08lx PA =%08lx ", insn_ea, + peek_into_dtlb(insn_ea,0,0)); + opd++; /* Skip of register operand */ + j++; + } else if ((opd->type & OPTYPE_REG) && i) { + fprintf (runtime.sim.fexe_log, "r%-2li=%08lx ", i, + evalsim_reg32 (i)); } else fprintf (runtime.sim.fexe_log, " "); - - i+=j; - for (; i < 3; i++) + j++; + if(opd->type & OPTYPE_LAST) + break; + opd++; + } + while(j < 3) { fprintf (runtime.sim.fexe_log, " "); + j++; + } } - fprintf (runtime.sim.fexe_log, "%.8lx ", i); + fprintf (runtime.sim.fexe_log, "%.8lx ", insn_addr); fprintf (runtime.sim.fexe_log, "%s\n", disassembled); } } @@ -630,84 +699,62 @@ #define INSTRUCTION(name) void name (struct iqueue_entry *current) /* Implementation specific. - Parses and returns operands. */ + Evaluates source operand op_no. */ -static void -eval_operands (unsigned long insn, int insn_index, int* breakpoint) +static unsigned long eval_operand (int op_no, unsigned long insn_index, + unsigned long insn) { struct insn_op_struct *opd = op_start[insn_index]; - unsigned long data = 0; - int dis = 0; - int no = 0; - - while (1) - { - unsigned long tmp = 0, nbits = 0; - while (1) - { - tmp |= ((insn >> (opd->type & OPTYPE_SHR)) & ((1 << opd->data) - 1)) << nbits; - nbits += opd->data; - if (opd->type & OPTYPE_OP) - break; - opd++; - } + unsigned long ret; - /* Do we have to sign extend? */ - if (opd->type & OPTYPE_SIG) - { - int sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR; - if (tmp & (1 << sbit)) - tmp |= 0xFFFFFFFF << sbit; - } - if (opd->type & OPTYPE_DIS) { - /* We have to read register later. */ - data += tmp; - dis = 1; - } else - { - if (dis && (opd->type & OPTYPE_REG)) - op[no] = data + eval_reg32 (tmp); - else - op[no] = tmp; - op[no + MAX_OPERANDS] = opd->type | (dis ? OPTYPE_DIS : 0); - no++; - data = 0; - dis = 0; - } - if(opd->type & OPTYPE_LAST) { - num_op = no; - return; - } - opd++; + while (op_no) { + if(opd->type & OPTYPE_LAST) { + fprintf (stderr, "Instruction requested more operands than it has\n"); + exit (1); } - num_op = no; -} - -/* Implementation specific. - Evaluates source operand op_no. */ + if((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS)) + op_no--; + opd++; + } -static unsigned long eval_operand (int op_no) -{ - if (op[op_no + MAX_OPERANDS] & OPTYPE_DIS) { - return op[op_no]; - } else if (op[op_no + MAX_OPERANDS] & OPTYPE_REG) { - return eval_reg32 (op[op_no]); - } else { - return op[op_no]; + if (opd->type & OPTYPE_DIS) { + ret = eval_operand_val (insn, opd); + while (!(opd->type & OPTYPE_OP)) + opd++; + opd++; + ret += eval_reg32 (eval_operand_val (insn, opd)); + insn_ea = ret; + return ret; } + if (opd->type & OPTYPE_REG) + return eval_reg32 (eval_operand_val (insn, opd)); + + return eval_operand_val (insn, opd); } /* Implementation specific. Set destination operand (reister direct) with value. */ -inline static void set_operand(int op_no, unsigned long value) +inline static void set_operand(int op_no, unsigned long value, + unsigned long insn_index, unsigned long insn) { - /* Mark this as destination operand. */ - if (!(op[op_no + MAX_OPERANDS] & OPTYPE_REG)) { + struct insn_op_struct *opd = op_start[insn_index]; + + while (op_no) { + if(opd->type & OPTYPE_LAST) { + fprintf (stderr, "Instruction requested more operands than it has\n"); + exit (1); + } + if((opd->type & OPTYPE_OP) && !(opd->type & OPTYPE_DIS)) + op_no--; + opd++; + } + + if (!(opd->type & OPTYPE_REG)) { fprintf (stderr, "Trying to set a non-register operand\n"); exit (1); } - set_reg32(op[op_no], value); + set_reg32 (eval_operand_val (insn, opd), value); } /* Simple and rather slow decoding function based on built automata. */ @@ -720,18 +767,16 @@ if (insn_index < 0) l_invalid(current); else { - op = &current->op[0]; - eval_operands (current->insn, insn_index, &breakpoint); or32_opcodes[insn_index].exec(current); } if (do_stats) analysis(&iqueue[0]); } -#define SET_PARAM0(val) set_operand(0, val) +#define SET_PARAM0(val) set_operand(0, val, current->insn_index, current->insn) -#define PARAM0 eval_operand(0) -#define PARAM1 eval_operand(1) -#define PARAM2 eval_operand(2) +#define PARAM0 eval_operand(0, current->insn_index, current->insn) +#define PARAM1 eval_operand(1, current->insn_index, current->insn) +#define PARAM2 eval_operand(2, current->insn_index, current->insn) #include "insnset.c" --- cpu/or32/or32.c 2005-01-25 19:04:57.000000000 +0100 +++ ../or1ksim-ac/cpu/or32/or32.c 2005-01-25 18:06:11.000000000 +0100 @@ -860,6 +857,7 @@ { char *args = opcode->args; int i, type; + int num_cur_op = 0;; i = 0; type = 0; @@ -892,6 +890,7 @@ type |= ((num_ones (arg) - 1) << OPTYPE_SBIT_SHR) & OPTYPE_SBIT; } + num_cur_op = 0; /* Split argument to sequences of consecutive ones. */ while (arg) { @@ -912,16 +911,21 @@ arg &= ~(((1 << mask) - 1) << shr); debug(6, "|%08X %08X\n", cur->type, cur->data); cur++; + num_cur_op++; } args++; } else if (*args == '(') { /* Next param is displacement. Later we will treat them as one operand. */ - cur--; - cur->type = type | cur->type | OPTYPE_DIS | OPTYPE_OP; + /* Set the OPTYPE_DIS flag on all insn_op_structs that belong to this + * operand */ + while(num_cur_op > 0) { + cur[-num_cur_op].type |= type | OPTYPE_DIS; + num_cur_op--; + } + cur[-1].type |= OPTYPE_OP; debug(9, ">%08X %08X\n", cur->type, cur->data); - cur++; type = 0; i++; args++; --- cpu/or32/generate.c 2005-01-25 08:50:59.000000000 +0100 +++ ../or1ksim-ac/cpu/or32/generate.c 2005-01-25 21:04:32.000000000 +0100 @@ -30,7 +30,6 @@ static char *in_file; static char *out_file; -static unsigned long op[MAX_OPERANDS]; /* Whether this instruction stores something in register */ static int write_to_reg; @@ -129,8 +128,7 @@ return 0; } -/* Parses and puts operands into op[] structure. - Replacement for eval_operands routine. */ +/* Parses operands. */ static int gen_eval_operands (FILE *fo, int insn_index, int level) @@ -142,6 +140,7 @@ int set_param = 0; int dis = 0; int sbit; + int dis_op = -1; write_to_reg = 0; @@ -188,7 +187,7 @@ nbits += opd->data; - if (opd->type & OPTYPE_DIS) { + if ((opd->type & OPTYPE_DIS) && (opd->type & OPTYPE_OP)) { sbit = (opd->type & OPTYPE_SBIT) >> OPTYPE_SBIT_SHR; if (opd->type & OPTYPE_SIG) shift_fprintf (level, fo, "if(%c & 0x%08x) %c |= 0x%x;\n", @@ -199,6 +198,7 @@ 'a' + num_ops, opd->type & OPTYPE_SHR, (1 << opd->data) - 1); dis = 1; + dis_op = num_ops; } if (opd->type & OPTYPE_OP) { @@ -220,10 +220,6 @@ shift_fprintf (level, fo, "#define PARAM%i %c\n", num_ops, 'a' + num_ops); } - - op[num_ops] = opd->type; - if(dis) - op[num_ops] |= OPTYPE_DIS; num_ops++; nbits = 0; dis = 0; @@ -243,39 +239,33 @@ for (i = 0; i < num_ops; i++) shift_fprintf (level, fo, "#undef PARAM%i\n", i); - return num_ops; + return dis_op; } /* Generates decode and execute for one instruction instance */ static int output_call (FILE *fo, int index, int level) { - int i; - int num_op; + int dis_op = -1; /*printf ("%i:%s\n", index, insn_name (index));*/ shift_fprintf (level++, fo, "{\n"); if (index >= 0) - num_op = gen_eval_operands (fo, index, level); - else - num_op = 0; + dis_op = gen_eval_operands (fo, index, level); if (index < 0) output_function (fo, "l_invalid", level); fprintf (fo, "\n"); shift_fprintf (level++, fo, "if (do_stats) {\n"); - shift_fprintf (level, fo, "num_op = %i;\n", num_op); - if (num_op) shift_fprintf (level, fo, "op = &current->op[0];\n"); + if (dis_op >= 0) + shift_fprintf (level, fo, "insn_ea = %c;\n", 'a' + dis_op); + shift_fprintf (level, fo, "current->insn_index = %i; /* \"%s\" */\n", index, insn_name (index)); - for (i = 0; i < num_op; i++) { - shift_fprintf (level, fo, "op[%i] = %c;\n", i, 'a' + i); - shift_fprintf (level, fo, "op[%i + MAX_OPERANDS] = 0x%08x;\n", i, op[i]); - } shift_fprintf (level, fo, "analysis(current);\n"); shift_fprintf (--level, fo, "}\n"); if (write_to_reg) --- cpu/common/abstract.h 2005-01-25 19:04:57.000000000 +0100 +++ ../or1ksim-ac/cpu/common/abstract.h 2005-01-25 21:03:13.000000000 +0100 @@ -39,7 +39,6 @@ struct iqueue_entry { int insn_index; unsigned long insn; - unsigned long op[2 * MAX_OPERANDS]; unsigned long insn_addr; };

     
    Copyright (c) 1999 OPENCORES.ORG. All rights reserved.