aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sim/ppc/ChangeLog28
-rw-r--r--sim/ppc/ppc-instructions97
2 files changed, 102 insertions, 23 deletions
diff --git a/sim/ppc/ChangeLog b/sim/ppc/ChangeLog
index 19730da..72d86eb 100644
--- a/sim/ppc/ChangeLog
+++ b/sim/ppc/ChangeLog
@@ -1,5 +1,15 @@
+Sun Nov 19 23:00:52 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+
+ * ppc-instructions (model data, model_busy): Rather than using a
+ bit mask for the busy units, just use a char array. Also, only
+ support 2 function units an insn can use, rather than a loop.
+
Fri Nov 17 14:08:08 1995 Michael Meissner <meissner@tiktok.cygnus.com>
+ * table.c (table_entry_read): Move setting entry->line_nr to after
+ the model specific fields so the line numbers for the annex are
+ correct.
+
* cpu.c (cpu_{create,init,halt}): Check for WITH_MODEL_ISSUE
before calling the model functions.
@@ -8,15 +18,21 @@ Fri Nov 17 14:08:08 1995 Michael Meissner <meissner@tiktok.cygnus.com>
* igen.c (gen_icache_h): Create type idecode_cache as void if not
caching instructions.
- (lf_print_c_semantic): Pass idecode_cache and instruction word to
- model_issue.
- (gen_model_{c,h}): Model_issue now takes two more arguments.
-
+ (gen_model_{c,h}): Drop model_issue support. Add support for
+ model_cleanup.
+ (lf_print_my_prefix): Initialize a const itable_index with the
+ current index.
+ (lf_print_c_semantic): Call model_cleanup at the end of the
+ function to check for instructions that aren't supported yet by
+ the scheduling code.
+
* mon.h (count_type): New type for counters.
* mon.c: Use count_type instead of unsigned.
- * ppc-instructions: Reorganize so insn dependent routine is called
- via a function pointer. Add initial scheduling code.
+ * ppc-instructions: Redo scheduling code once again. Make it all
+ inline friendly. Instead of having general code emitted by igen,
+ go the route of having each semantic routine call the appropriate
+ module.
Thu Nov 16 09:52:26 1995 Michael Meissner <meissner@tiktok.cygnus.com>
diff --git a/sim/ppc/ppc-instructions b/sim/ppc/ppc-instructions
index 8fe8a28..e0f0a1d 100644
--- a/sim/ppc/ppc-instructions
+++ b/sim/ppc/ppc-instructions
@@ -89,7 +89,7 @@
/* Structure to hold timing information on a per instruction basis */
struct _model_time {
ppc_function_unit first_unit; /* first functional unit this insn could use */
- ppc_function_unit last_unit; /* last functional unit this insn could use */
+ ppc_function_unit second_unit; /* second functional unit this insn could use */
signed16 issue; /* # cycles before function unit can process other insns */
signed16 done; /* # cycles before insn is done */
unsigned32 flags; /* any flags that are needed */
@@ -128,7 +128,6 @@
model_busy *busy_list; /* list of busy function units */
model_busy *free_list; /* list of model_busy structs not in use */
model_reg registers[NR_PPC_REGS]; /* register status */
- unsigned32 busy_mask; /* bitmask of busy function units */
count_type nr_cycles; /* # cycles */
count_type nr_branches; /* # branches */
count_type nr_branches_fallthrough; /* # conditional branches that fell through */
@@ -140,6 +139,7 @@
count_type nr_insns_not_handled; /* # of instructions not handled */
count_type nr_units[nr_ppc_function_units]; /* function unit counts */
int insn_handled; /* whether last insn was handled */
+ unsigned_1 busy[nr_ppc_function_units]; /* whether a function is busy or not */
};
STATIC_MODEL const char *const ppc_function_unit_name[ (int)nr_ppc_function_units ] = {
@@ -168,7 +168,6 @@ void::model-internal::model_new_cycle:model_data *model_ptr
model_busy *cur_busy = model_ptr->busy_list;
model_busy *free_list = model_ptr->free_list;
model_busy *next_busy = (model_busy *)0;
- unsigned32 busy_mask = model_ptr->busy_mask;
model_busy *next;
model_ptr->nr_cycles++;
@@ -182,13 +181,13 @@ void::model-internal::model_new_cycle:model_data *model_ptr
reg->in_use = 0;
reg = reg->next;
}
- busy_mask &= ~(1 << cur_busy->unit);
+ model_ptr->busy[cur_busy->unit] = 0;
cur_busy->next = free_list;
free_list = cur_busy;
}
else if (--cur_busy->issue <= 0) { /* function unit pipelined, allow new use */
TRACE(trace_model,("pipeline, %s ready for next client\n", ppc_function_unit_name[cur_busy->unit]));
- busy_mask &= ~(1 << cur_busy->unit);
+ model_ptr->busy[cur_busy->unit] = 0;
cur_busy->next = next_busy;
next_busy = cur_busy;
}
@@ -204,7 +203,6 @@ void::model-internal::model_new_cycle:model_data *model_ptr
model_ptr->busy_list = next_busy;
model_ptr->free_list = free_list;
- model_ptr->busy_mask = busy_mask;
# Mark a function unit as busy, return the busy structure so regs can be added to be released
model_busy *::model-internal::model_make_busy:model_data *model_ptr, ppc_function_unit unit, int issue, int done
@@ -226,27 +224,27 @@ model_busy *::model-internal::model_make_busy:model_data *model_ptr, ppc_functio
busy->issue = issue;
busy->done = done;
model_ptr->busy_list = busy;
- model_ptr->busy_mask |= (1 << unit);
+ model_ptr->busy[unit] = 1;
model_ptr->nr_units[unit]++;
return busy;
# Wait until a function unit is non-busy, and then allocate a busy pointer & return the pointer
model_busy *::model-internal::model_wait_for_unit:itable_index index, model_data *const model_ptr, const model_time *const time_ptr
ppc_function_unit first_unit = time_ptr->first_unit;
- ppc_function_unit last_unit = time_ptr->last_unit;
- ppc_function_unit unit;
+ ppc_function_unit second_unit = time_ptr->second_unit;
int stall_increment = 0;
for (;;) {
- unsigned32 busy_mask = model_ptr->busy_mask;
- for (unit = first_unit; unit <= last_unit; unit++) {
- if (((1 << unit) & busy_mask) == 0) {
- return model_make_busy(model_ptr, unit,
- model_ptr->timing[index].issue,
- model_ptr->timing[index].done);
+ if (!model_ptr->busy[first_unit])
+ return model_make_busy(model_ptr, first_unit,
+ model_ptr->timing[index].issue,
+ model_ptr->timing[index].done);
+
+ if (!model_ptr->busy[second_unit])
+ return model_make_busy(model_ptr, second_unit,
+ model_ptr->timing[index].issue,
+ model_ptr->timing[index].done);
- }
- }
TRACE(trace_model,("all function units are busy for %s\n", itable[index].name));
model_ptr->nr_stalls_unit += stall_increment; /* don't count first stall */
stall_increment = 1;
@@ -646,6 +644,62 @@ void::model-function::ppc_insn_mtcr:itable_index index, cpu *processor, model_da
busy_ptr->reg = prev_reg;
}
+# Convert a BIT32(x) number back into the original number
+int::model-internal::ppc_undo_bit32:unsigned bitmask
+ unsigned u = 0x80000000;
+ int i = 0;
+ while (u && (u & bitmask) == 0) {
+ u >>= 1;
+ i++;
+ }
+
+ return i;
+
+# Schedule an instruction that takes 2 CR input registers and produces an output CR register
+void::model-function::ppc_insn_cr2:itable_index index, cpu *processor, model_data *model_ptr, unsigned crD, unsigned crA_bit, unsigned crB_bit
+ if (!WITH_MODEL_ISSUE)
+ return;
+
+ else {
+ const unsigned ppc_CRA = ppc_undo_bit32(crA_bit) + PPC_CR_REG;
+ const unsigned ppc_CRB = ppc_undo_bit32(crB_bit) + PPC_CR_REG;
+ const unsigned ppc_CRD = crD + PPC_CR_REG;
+ model_reg *ppc_regs = model_ptr->registers;
+ model_busy *busy_ptr;
+
+ while (ppc_regs[ppc_CRA].in_use | ppc_regs[ppc_CRB].in_use) {
+ model_ptr->nr_stalls_data++;
+ model_new_cycle(model_ptr);
+ }
+
+ busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+ ppc_regs[ppc_CRD].next = (model_reg *)0;
+ ppc_regs[ppc_CRD].in_use = 1;
+ busy_ptr->reg = &ppc_regs[ppc_CRD];
+ }
+
+# Schedule an instruction that takes 1 CR input registers and produces an output CR register
+void::model-function::ppc_insn_cr1:itable_index index, cpu *processor, model_data *model_ptr, unsigned crD, unsigned CRA
+ if (!WITH_MODEL_ISSUE)
+ return;
+
+ else {
+ const unsigned ppc_CRA = CRA + PPC_CR_REG;
+ const unsigned ppc_CRD = crD + PPC_CR_REG;
+ model_reg *ppc_regs = model_ptr->registers;
+ model_busy *busy_ptr;
+
+ while (ppc_regs[ppc_CRA].in_use) {
+ model_ptr->nr_stalls_data++;
+ model_new_cycle(model_ptr);
+ }
+
+ busy_ptr = model_wait_for_unit(index, model_ptr, &model_ptr->timing[index]);
+ ppc_regs[ppc_CRD].next = (model_reg *)0;
+ ppc_regs[ppc_CRD].in_use = 1;
+ busy_ptr->reg = &ppc_regs[ppc_CRD];
+ }
+
model_data *::model-function::model_create:cpu *processor
model_data *model_ptr = ZALLOC(model_data);
ASSERT(CURRENT_MODEL > 0 && CURRENT_MODEL < nr_models);
@@ -1361,6 +1415,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
BLIT32(CR, BT, CR{BA} && CR{BB});
+ ppc_insn_cr2(my_index, processor, cpu_model(processor), BT, BIT32_BA, BIT32_BB);
0.19,6.BT,11.BA,16.BB,21.449,31./:XL::cror:Condition Register OR
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
@@ -1368,6 +1423,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
BLIT32(CR, BT, CR{BA} || CR{BB});
+ ppc_insn_cr2(my_index, processor, cpu_model(processor), BT, BIT32_BA, BIT32_BB);
0.19,6.BT,11.BA,16.BB,21.193,31./:XL::crxor:Condition Register XOR
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
@@ -1375,6 +1431,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
BLIT32(CR, BT, CR{BA} != CR{BB});
+ ppc_insn_cr2(my_index, processor, cpu_model(processor), BT, BIT32_BA, BIT32_BB);
0.19,6.BT,11.BA,16.BB,21.225,31./:XL::crnand:Condition Register NAND
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
@@ -1382,6 +1439,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
BLIT32(CR, BT, !(CR{BA} && CR{BB}));
+ ppc_insn_cr2(my_index, processor, cpu_model(processor), BT, BIT32_BA, BIT32_BB);
0.19,6.BT,11.BA,16.BB,21.33,31./:XL::crnor:Condition Register NOR
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
@@ -1389,6 +1447,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
BLIT32(CR, BT, !(CR{BA} || CR{BB}));
+ ppc_insn_cr2(my_index, processor, cpu_model(processor), BT, BIT32_BA, BIT32_BB);
0.19,6.BT,11.BA,16.BB,21.289,31./:XL::creqv:Condition Register Equivalent
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
@@ -1396,6 +1455,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
BLIT32(CR, BT, CR{BA} == CR{BB});
+ ppc_insn_cr2(my_index, processor, cpu_model(processor), BT, BIT32_BA, BIT32_BB);
0.19,6.BT,11.BA,16.BB,21.129,31./:XL::crandc:Condition Register AND with Complement
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
@@ -1403,6 +1463,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
BLIT32(CR, BT, CR{BA} && !CR{BB});
+ ppc_insn_cr2(my_index, processor, cpu_model(processor), BT, BIT32_BA, BIT32_BB);
0.19,6.BT,11.BA,16.BB,21.417,31./:XL::crorc:Condition Register OR with Complement
*601: PPC_UNIT_IU, PPC_UNIT_IU, 1, 1, 0
@@ -1410,6 +1471,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
BLIT32(CR, BT, CR{BA} || !CR{BB});
+ ppc_insn_cr2(my_index, processor, cpu_model(processor), BT, BIT32_BA, BIT32_BB);
#
# I.2.4.4 Condition Register Field Instruction
@@ -1420,6 +1482,7 @@ void::function::invalid_arithemetic_operation:cpu *processor, unsigned_word cia,
*603e:PPC_UNIT_SRU, PPC_UNIT_SRU, 1, 1, 0
*604: PPC_UNIT_BPU, PPC_UNIT_BPU, 1, 1, 0
MBLIT32(CR, 4*BF, 4*BF+3, EXTRACTED32(CR, 4*BFA, 4*BFA+3));
+ ppc_insn_cr1(my_index, processor, cpu_model(processor), BF, BFA);
#