112855Sgabeblack@google.com/*****************************************************************************
212855Sgabeblack@google.com
312855Sgabeblack@google.com  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
412855Sgabeblack@google.com  more contributor license agreements.  See the NOTICE file distributed
512855Sgabeblack@google.com  with this work for additional information regarding copyright ownership.
612855Sgabeblack@google.com  Accellera licenses this file to you under the Apache License, Version 2.0
712855Sgabeblack@google.com  (the "License"); you may not use this file except in compliance with the
812855Sgabeblack@google.com  License.  You may obtain a copy of the License at
912855Sgabeblack@google.com
1012855Sgabeblack@google.com    http://www.apache.org/licenses/LICENSE-2.0
1112855Sgabeblack@google.com
1212855Sgabeblack@google.com  Unless required by applicable law or agreed to in writing, software
1312855Sgabeblack@google.com  distributed under the License is distributed on an "AS IS" BASIS,
1412855Sgabeblack@google.com  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1512855Sgabeblack@google.com  implied.  See the License for the specific language governing
1612855Sgabeblack@google.com  permissions and limitations under the License.
1712855Sgabeblack@google.com
1812855Sgabeblack@google.com *****************************************************************************/
1912855Sgabeblack@google.com
2012855Sgabeblack@google.com/*****************************************************************************
2112855Sgabeblack@google.com
2212855Sgabeblack@google.com  cycle_model.cpp --
2312855Sgabeblack@google.com
2412855Sgabeblack@google.com  Original Author: Martin Janssen, Synopsys, Inc., 2002-02-15
2512855Sgabeblack@google.com
2612855Sgabeblack@google.com *****************************************************************************/
2712855Sgabeblack@google.com
2812855Sgabeblack@google.com/*****************************************************************************
2912855Sgabeblack@google.com
3012855Sgabeblack@google.com  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
3112855Sgabeblack@google.com  changes you are making here.
3212855Sgabeblack@google.com
3312855Sgabeblack@google.com      Name, Affiliation, Date:
3412855Sgabeblack@google.com  Description of Modification:
3512855Sgabeblack@google.com
3612855Sgabeblack@google.com *****************************************************************************/
3712855Sgabeblack@google.com
3812855Sgabeblack@google.com//***************************************************************************
3912855Sgabeblack@google.com// FILE: cycle_model.cc
4012855Sgabeblack@google.com//
4112855Sgabeblack@google.com// AUTHOR: Luc Semeria    September, 21, 1998
4212855Sgabeblack@google.com//
4312855Sgabeblack@google.com// ABSTRACT: cycle-accurate model based on the dw8051 architecture
4412855Sgabeblack@google.com//
4512855Sgabeblack@google.com//
4612855Sgabeblack@google.com// MODIFICATION HISTORY:
4712855Sgabeblack@google.com//         Luc Semeria: 21/9/98 created
4812855Sgabeblack@google.com//
4912855Sgabeblack@google.com//***************************************************************************
5012855Sgabeblack@google.com//
5112855Sgabeblack@google.com// DESCRIPTION
5212855Sgabeblack@google.com//
5312855Sgabeblack@google.com// During initialization, the model parses the Intel hex file and put the
5412855Sgabeblack@google.com// program into memory.
5512855Sgabeblack@google.com// Then the cycle-accurate model does the following operations:
5612855Sgabeblack@google.com//
5712855Sgabeblack@google.com//   main loop:
5812855Sgabeblack@google.com//     fetch instruction
5912855Sgabeblack@google.com//     decode instruction
6012855Sgabeblack@google.com//     execute instruction                   /read instr mem
6112855Sgabeblack@google.com//              |\- fetch operand 1 (and 2) <             /mem bus access
6212855Sgabeblack@google.com//              |                            \fetch data <
6312855Sgabeblack@google.com//              |                                         \read data mem
6412855Sgabeblack@google.com//              |\- execute operation
6512855Sgabeblack@google.com//              |                     /mem bus access
6612855Sgabeblack@google.com//              |\- write back data  <
6712855Sgabeblack@google.com//              |                     \write data mem
6812855Sgabeblack@google.com//              |
6912855Sgabeblack@google.com//               \- compute next address
7012855Sgabeblack@google.com//
7112855Sgabeblack@google.com//
7212855Sgabeblack@google.com// The external instruction and data memories are part of the model
7312855Sgabeblack@google.com// so these memory accesses are just read and write in internal memory
7412855Sgabeblack@google.com// The simulation is then speeded up because no bus transactions occurs.
7512855Sgabeblack@google.com// The model doesn't switch from one process to another.
7612855Sgabeblack@google.com//
7712855Sgabeblack@google.com// To communicate with peripheral on the memory bus, the bus can be
7812855Sgabeblack@google.com// used and the model automatically switches to a real cycle-accurate mode
7912855Sgabeblack@google.com// for a given number of cycle. This is implemented within the function:
8012855Sgabeblack@google.com//   request_address(int addr);
8112855Sgabeblack@google.com//
8212855Sgabeblack@google.com// This cycle-accurate model implements only parts of the dw8051. The
8312855Sgabeblack@google.com// limitations are the following:
8412855Sgabeblack@google.com//       - some instructions are not supported (cf decode function)
8512855Sgabeblack@google.com//       - SFR, timers, io_interface and interrupts are not supported
8612855Sgabeblack@google.com//
8712855Sgabeblack@google.com//***************************************************************************
8812855Sgabeblack@google.com
8912855Sgabeblack@google.com#include "cycle_model.h"
9012855Sgabeblack@google.com#include <string.h>
9112855Sgabeblack@google.com
9212855Sgabeblack@google.com/* useful macros for sc_aproc */
9312855Sgabeblack@google.com#define AT_POSEDGE(CLK) wait(); while(!clk.posedge()) wait();
9412855Sgabeblack@google.com#define AT_NEGEDGE(CLK) wait(); while(!clk.negedge()) wait();
9512855Sgabeblack@google.com
9612855Sgabeblack@google.combool ALL_CYCLES;         /* flag to execute all cycles */
9712855Sgabeblack@google.com
9812855Sgabeblack@google.com
9912855Sgabeblack@google.com//-------------------------------------------------------------------------
10012855Sgabeblack@google.com// void cycle_model::parse_hex(char *name)
10112855Sgabeblack@google.com//
10212855Sgabeblack@google.com// parse Intel HEX file
10312855Sgabeblack@google.com// more information on hex format on-line at:
10412855Sgabeblack@google.com//         http://www.8052.com/tutintel.htm
10512855Sgabeblack@google.com//
10612855Sgabeblack@google.com//------------------------------------------------------------------------
10712855Sgabeblack@google.comvoid cycle_model::parse_hex(char *name) {
10812855Sgabeblack@google.com  char line_buffer[MEM_SIZE];
10912855Sgabeblack@google.com  FILE *hex_file;
11012855Sgabeblack@google.com
11112855Sgabeblack@google.com  // open file
11212855Sgabeblack@google.com  hex_file = fopen(name,"r");
11312855Sgabeblack@google.com  if(hex_file==NULL) {
11412855Sgabeblack@google.com    fprintf(stderr,"Error in opening file %s\n",name);
11512855Sgabeblack@google.com    exit(-1);
11612855Sgabeblack@google.com  }
11712855Sgabeblack@google.com
11812855Sgabeblack@google.com  // read new line at each loop ------------------------------------------
11912855Sgabeblack@google.com  while(fgets(line_buffer,MEM_SIZE,hex_file)!=NULL) {
12012855Sgabeblack@google.com#ifdef DEBUG
12112855Sgabeblack@google.com    printf("Read new line -> %s",line_buffer);
12212855Sgabeblack@google.com#endif
12312855Sgabeblack@google.com
12412855Sgabeblack@google.com    // parse line --------------------------------------------------------
12512855Sgabeblack@google.com
12612855Sgabeblack@google.com    // parse ':' (line[0])
12712855Sgabeblack@google.com    if(line_buffer[0]!=':') {
12812855Sgabeblack@google.com      continue;
12912855Sgabeblack@google.com    }
13012855Sgabeblack@google.com
13112855Sgabeblack@google.com
13212855Sgabeblack@google.com    // parse length (line[1..2])
13312855Sgabeblack@google.com    int length;
13412855Sgabeblack@google.com    // char length_string[2];
13512855Sgabeblack@google.com    char length_string[3];
13612855Sgabeblack@google.com    if(strncpy(length_string,&(line_buffer[1]),2)==NULL) {
13712855Sgabeblack@google.com      fprintf(stderr,"Error in parsing length\n");
13812855Sgabeblack@google.com      exit(-1);
13912855Sgabeblack@google.com    }
14012855Sgabeblack@google.com    length_string[2] = 0;
14112855Sgabeblack@google.com    length = (int)strtol(length_string, (char **)NULL, 16);
14212855Sgabeblack@google.com#ifdef DEBUG
14312855Sgabeblack@google.com    printf("length=%x\n",length);
14412855Sgabeblack@google.com#endif
14512855Sgabeblack@google.com
14612855Sgabeblack@google.com    // parse address (line[3..6])
14712855Sgabeblack@google.com    int address;
14812855Sgabeblack@google.com    // char address_string[4];
14912855Sgabeblack@google.com    char address_string[5];
15012855Sgabeblack@google.com    if(strncpy(address_string,&(line_buffer[3]),4)==NULL) {
15112855Sgabeblack@google.com      fprintf(stderr,"Error in parsing address\n");
15212855Sgabeblack@google.com      exit(-1);
15312855Sgabeblack@google.com    }
15412855Sgabeblack@google.com    address_string[4] = 0;
15512855Sgabeblack@google.com    address = (int)strtol(address_string, (char **)NULL, 16);
15612855Sgabeblack@google.com#ifdef DEBUG
15712855Sgabeblack@google.com    printf("address=%x\n",address);
15812855Sgabeblack@google.com#endif
15912855Sgabeblack@google.com
16012855Sgabeblack@google.com
16112855Sgabeblack@google.com    // parse Record Type (line[7..8])
16212855Sgabeblack@google.com    int record_type;
16312855Sgabeblack@google.com    // char record_string[2];
16412855Sgabeblack@google.com    char record_string[3];
16512855Sgabeblack@google.com    if(strncpy(record_string,&(line_buffer[7]),2)==NULL) {
16612855Sgabeblack@google.com      fprintf(stderr,"Error in parsing record type\n");
16712855Sgabeblack@google.com      exit(-1);
16812855Sgabeblack@google.com    }
16912855Sgabeblack@google.com    record_string[2] = 0;
17012855Sgabeblack@google.com    record_type = (int)strtol(record_string, (char **)NULL, 16);
17112855Sgabeblack@google.com#ifdef DEBUG
17212855Sgabeblack@google.com    printf("record_type=%x\n",record_type);
17312855Sgabeblack@google.com#endif
17412855Sgabeblack@google.com    if(record_type==01) {
17512855Sgabeblack@google.com      // end of file
17612855Sgabeblack@google.com      // return;
17712855Sgabeblack@google.com#ifdef DEBUG
17812855Sgabeblack@google.com      printf("end of file => return\n");
17912855Sgabeblack@google.com#endif
18012855Sgabeblack@google.com      fclose(hex_file);
18112855Sgabeblack@google.com      return;
18212855Sgabeblack@google.com    }
18312855Sgabeblack@google.com
18412855Sgabeblack@google.com    // parse data bytes
18512855Sgabeblack@google.com    char instr_string[3];
18612855Sgabeblack@google.com    for(int i=0;i<length;i++) {
18712855Sgabeblack@google.com      if(strncpy(instr_string,&(line_buffer[2*i+9]),2)==NULL) {
18812855Sgabeblack@google.com	fprintf(stderr,"Error in parsing data byte %d\n",i);
18912855Sgabeblack@google.com	exit(-1);
19012855Sgabeblack@google.com      }
19112855Sgabeblack@google.com
19212855Sgabeblack@google.com    instr_string[2] = 0;
19312855Sgabeblack@google.com    int temp = (int)strtol(instr_string, (char **)NULL, 16);
19412855Sgabeblack@google.com    instr_mem[address++] = temp;
19512855Sgabeblack@google.com#ifdef DEBUG
19612855Sgabeblack@google.com    printf("data byte = %x\n",temp);
19712855Sgabeblack@google.com#endif
19812855Sgabeblack@google.com    }
19912855Sgabeblack@google.com
20012855Sgabeblack@google.com    // skip the checksum bits
20112855Sgabeblack@google.com
20212855Sgabeblack@google.com    // verify end of line
20312855Sgabeblack@google.com    if(line_buffer[2*length+9+2]!='\n') {
20412855Sgabeblack@google.com      fprintf(stderr,"Error in parsing hex file: end of line expected\n");
20512855Sgabeblack@google.com      exit(-1);
20612855Sgabeblack@google.com    }
20712855Sgabeblack@google.com
20812855Sgabeblack@google.com  }
20912855Sgabeblack@google.com
21012855Sgabeblack@google.com  fprintf(stderr,"Error in parsing hex file: end of file record type expected\n");
21112855Sgabeblack@google.com  exit(-1);
21212855Sgabeblack@google.com
21312855Sgabeblack@google.com}
21412855Sgabeblack@google.com
21512855Sgabeblack@google.com
21612855Sgabeblack@google.com//---------------------------------------------------------------------
21712855Sgabeblack@google.com//void cycle_model::decode(int opcode, instr* i)
21812855Sgabeblack@google.com//
21912855Sgabeblack@google.com// take an opcode as an input and output the instruction with the
22012855Sgabeblack@google.com// proper operand types.
22112855Sgabeblack@google.com//
22212855Sgabeblack@google.com//---------------------------------------------------------------------
22312855Sgabeblack@google.comvoid cycle_model::decode(int opcode, instr* i) {
22412855Sgabeblack@google.com
22512855Sgabeblack@google.com  // default
22612855Sgabeblack@google.com  i->type = i_nop;
22712855Sgabeblack@google.com  i->n_src = 0;
22812855Sgabeblack@google.com  i->src1.type = o_null;
22912855Sgabeblack@google.com  i->src1.val = -1;
23012855Sgabeblack@google.com  i->src2.type = o_null;
23112855Sgabeblack@google.com  i->src2.val = -1;
23212855Sgabeblack@google.com  i->dst.type = o_null;
23312855Sgabeblack@google.com  i->dst.val = -1;
23412855Sgabeblack@google.com
23512855Sgabeblack@google.com  switch(opcode) {
23612855Sgabeblack@google.com    // arithmetic operations -----------------------------------------
23712855Sgabeblack@google.com  case 0x28:
23812855Sgabeblack@google.com  case 0x29:
23912855Sgabeblack@google.com  case 0x2A:
24012855Sgabeblack@google.com  case 0x2B:
24112855Sgabeblack@google.com  case 0x2C:
24212855Sgabeblack@google.com  case 0x2d:
24312855Sgabeblack@google.com  case 0x2e:
24412855Sgabeblack@google.com  case 0x2f: {
24512855Sgabeblack@google.com    // add register to A
24612855Sgabeblack@google.com    i->type = i_add;
24712855Sgabeblack@google.com    i->n_src = 2;
24812855Sgabeblack@google.com    i->src1.type = o_reg;
24912855Sgabeblack@google.com    i->src1.val = opcode&0x07;
25012855Sgabeblack@google.com    i->src2.type = o_acc;
25112855Sgabeblack@google.com    i->dst.type = o_acc;
25212855Sgabeblack@google.com    i->cycle = 1;
25312855Sgabeblack@google.com    break;
25412855Sgabeblack@google.com  }
25512855Sgabeblack@google.com  case 0x25: {
25612855Sgabeblack@google.com    // add direct byte to A
25712855Sgabeblack@google.com    i->type = i_add;
25812855Sgabeblack@google.com    i->n_src = 2;
25912855Sgabeblack@google.com    i->src1.type = o_dir;
26012855Sgabeblack@google.com    i->src2.type = o_acc;
26112855Sgabeblack@google.com    i->dst.type = o_acc;
26212855Sgabeblack@google.com    i->cycle = 2;
26312855Sgabeblack@google.com    break;
26412855Sgabeblack@google.com  }
26512855Sgabeblack@google.com  case 0x26:
26612855Sgabeblack@google.com  case 0x27: {
26712855Sgabeblack@google.com    // add data memory to A
26812855Sgabeblack@google.com    i->type = i_add;
26912855Sgabeblack@google.com    i->n_src = 2;
27012855Sgabeblack@google.com    i->src1.type = o_ind;
27112855Sgabeblack@google.com    i->src1.val = opcode&1;
27212855Sgabeblack@google.com    i->src2.type = o_acc;
27312855Sgabeblack@google.com    i->dst.type = o_acc;
27412855Sgabeblack@google.com    i->cycle = 1;
27512855Sgabeblack@google.com    break;
27612855Sgabeblack@google.com  }
27712855Sgabeblack@google.com  case 0x24: {
27812855Sgabeblack@google.com    // add immediate to A
27912855Sgabeblack@google.com    i->type = i_add;
28012855Sgabeblack@google.com    i->n_src = 2;
28112855Sgabeblack@google.com    i->src1.type = o_cst;
28212855Sgabeblack@google.com    i->src2.type = o_acc;
28312855Sgabeblack@google.com    i->dst.type = o_acc;
28412855Sgabeblack@google.com    i->cycle = 2;
28512855Sgabeblack@google.com    break;
28612855Sgabeblack@google.com  }
28712855Sgabeblack@google.com  case 0x98:
28812855Sgabeblack@google.com  case 0x99:
28912855Sgabeblack@google.com  case 0x9A:
29012855Sgabeblack@google.com  case 0x9B:
29112855Sgabeblack@google.com  case 0x9C:
29212855Sgabeblack@google.com  case 0x9d:
29312855Sgabeblack@google.com  case 0x9e:
29412855Sgabeblack@google.com  case 0x9f: {
29512855Sgabeblack@google.com    // sub register to A
29612855Sgabeblack@google.com    i->type = i_sub;
29712855Sgabeblack@google.com    i->n_src = 2;
29812855Sgabeblack@google.com    i->src1.type = o_reg;
29912855Sgabeblack@google.com    i->src1.val = opcode&0x07;
30012855Sgabeblack@google.com    i->src2.type = o_acc;
30112855Sgabeblack@google.com    i->dst.type = o_acc;
30212855Sgabeblack@google.com    i->cycle = 1;
30312855Sgabeblack@google.com    break;
30412855Sgabeblack@google.com  }
30512855Sgabeblack@google.com  case 0x95: {
30612855Sgabeblack@google.com    // sub direct byte to A
30712855Sgabeblack@google.com    i->type = i_sub;
30812855Sgabeblack@google.com    i->n_src = 2;
30912855Sgabeblack@google.com    i->src1.type = o_dir;
31012855Sgabeblack@google.com    i->src2.type = o_acc;
31112855Sgabeblack@google.com    i->dst.type = o_acc;
31212855Sgabeblack@google.com    i->cycle = 2;
31312855Sgabeblack@google.com    break;
31412855Sgabeblack@google.com  }
31512855Sgabeblack@google.com  case 0x96:
31612855Sgabeblack@google.com  case 0x97: {
31712855Sgabeblack@google.com    // sub data memory to A
31812855Sgabeblack@google.com    i->type = i_sub;
31912855Sgabeblack@google.com    i->n_src = 2;
32012855Sgabeblack@google.com    i->src1.type = o_ind;
32112855Sgabeblack@google.com    i->src1.val = opcode&1;
32212855Sgabeblack@google.com    i->src2.type = o_acc;
32312855Sgabeblack@google.com    i->dst.type = o_acc;
32412855Sgabeblack@google.com    i->cycle = 1;
32512855Sgabeblack@google.com    break;
32612855Sgabeblack@google.com  }
32712855Sgabeblack@google.com  case 0x94: {
32812855Sgabeblack@google.com    // sub immediate to A
32912855Sgabeblack@google.com    i->type = i_sub;
33012855Sgabeblack@google.com    i->n_src = 2;
33112855Sgabeblack@google.com    i->src1.type = o_cst;
33212855Sgabeblack@google.com    i->src2.type = o_acc;
33312855Sgabeblack@google.com    i->dst.type = o_acc;
33412855Sgabeblack@google.com    i->cycle = 2;
33512855Sgabeblack@google.com    break;
33612855Sgabeblack@google.com  }
33712855Sgabeblack@google.com  case 0x04: {
33812855Sgabeblack@google.com    // increment A
33912855Sgabeblack@google.com    i->type = i_inc;
34012855Sgabeblack@google.com    i->n_src = 1;
34112855Sgabeblack@google.com    i->src1.type = o_acc;
34212855Sgabeblack@google.com    i->dst.type = o_acc;
34312855Sgabeblack@google.com    i->cycle = 1;
34412855Sgabeblack@google.com    break;
34512855Sgabeblack@google.com  }
34612855Sgabeblack@google.com  case 0x08:
34712855Sgabeblack@google.com  case 0x09:
34812855Sgabeblack@google.com  case 0x0A:
34912855Sgabeblack@google.com  case 0x0B:
35012855Sgabeblack@google.com  case 0x0C:
35112855Sgabeblack@google.com  case 0x0d:
35212855Sgabeblack@google.com  case 0x0e:
35312855Sgabeblack@google.com  case 0x0f: {
35412855Sgabeblack@google.com    // increment register
35512855Sgabeblack@google.com    i->type = i_inc;
35612855Sgabeblack@google.com    i->n_src = 1;
35712855Sgabeblack@google.com    i->src1.type = o_reg;
35812855Sgabeblack@google.com    i->src1.val = opcode&0x07;
35912855Sgabeblack@google.com    i->dst.type = o_reg;
36012855Sgabeblack@google.com    i->dst.val = opcode&0x07;
36112855Sgabeblack@google.com    i->cycle = 1;
36212855Sgabeblack@google.com    break;
36312855Sgabeblack@google.com  }
36412855Sgabeblack@google.com  case 0x05: {
36512855Sgabeblack@google.com    // increment direct byte
36612855Sgabeblack@google.com    i->type = i_inc;
36712855Sgabeblack@google.com    i->n_src = 1;
36812855Sgabeblack@google.com    i->src1.type = o_dir;
36912855Sgabeblack@google.com    i->dst.type = o_dir;
37012855Sgabeblack@google.com    i->cycle = 2;
37112855Sgabeblack@google.com    break;
37212855Sgabeblack@google.com  }
37312855Sgabeblack@google.com  case 0x06:
37412855Sgabeblack@google.com  case 0x07: {
37512855Sgabeblack@google.com    // increment  data memory
37612855Sgabeblack@google.com    i->type = i_inc;
37712855Sgabeblack@google.com    i->n_src = 1;
37812855Sgabeblack@google.com    i->src1.type = o_ind;
37912855Sgabeblack@google.com    i->src1.val = opcode&1;
38012855Sgabeblack@google.com    i->dst.type = o_ind;
38112855Sgabeblack@google.com    i->dst.val = opcode&1;
38212855Sgabeblack@google.com    i->cycle = 1;
38312855Sgabeblack@google.com    break;
38412855Sgabeblack@google.com  }
38512855Sgabeblack@google.com  case 0x14: {
38612855Sgabeblack@google.com    // decrement A
38712855Sgabeblack@google.com    i->type = i_dec;
38812855Sgabeblack@google.com    i->n_src = 1;
38912855Sgabeblack@google.com    i->src1.type = o_acc;
39012855Sgabeblack@google.com    i->dst.type = o_acc;
39112855Sgabeblack@google.com    i->cycle = 1;
39212855Sgabeblack@google.com    break;
39312855Sgabeblack@google.com  }
39412855Sgabeblack@google.com  case 0x18:
39512855Sgabeblack@google.com  case 0x19:
39612855Sgabeblack@google.com  case 0x1A:
39712855Sgabeblack@google.com  case 0x1B:
39812855Sgabeblack@google.com  case 0x1C:
39912855Sgabeblack@google.com  case 0x1d:
40012855Sgabeblack@google.com  case 0x1e:
40112855Sgabeblack@google.com  case 0x1f: {
40212855Sgabeblack@google.com    // decrement register
40312855Sgabeblack@google.com    i->type = i_dec;
40412855Sgabeblack@google.com    i->n_src = 1;
40512855Sgabeblack@google.com    i->src1.type = o_reg;
40612855Sgabeblack@google.com    i->src1.val = opcode&0x07;
40712855Sgabeblack@google.com    i->dst.type = o_reg;
40812855Sgabeblack@google.com    i->dst.val = opcode&0x07;
40912855Sgabeblack@google.com    i->cycle = 1;
41012855Sgabeblack@google.com    break;
41112855Sgabeblack@google.com  }
41212855Sgabeblack@google.com  case 0x15: {
41312855Sgabeblack@google.com    // decrement direct byte
41412855Sgabeblack@google.com    i->type = i_dec;
41512855Sgabeblack@google.com    i->n_src = 1;
41612855Sgabeblack@google.com    i->src1.type = o_dir;
41712855Sgabeblack@google.com    i->dst.type = o_dir;
41812855Sgabeblack@google.com    i->cycle = 2;
41912855Sgabeblack@google.com    break;
42012855Sgabeblack@google.com  }
42112855Sgabeblack@google.com  case 0x16:
42212855Sgabeblack@google.com  case 0x17: {
42312855Sgabeblack@google.com    // increment  data memory
42412855Sgabeblack@google.com    i->type = i_dec;
42512855Sgabeblack@google.com    i->n_src = 1;
42612855Sgabeblack@google.com    i->src1.type = o_ind;
42712855Sgabeblack@google.com    i->src1.val = opcode&1;
42812855Sgabeblack@google.com    i->dst.type = o_ind;
42912855Sgabeblack@google.com    i->dst.val = opcode&1;
43012855Sgabeblack@google.com    i->cycle = 1;
43112855Sgabeblack@google.com    break;
43212855Sgabeblack@google.com  }
43312855Sgabeblack@google.com  // logic operation --------------------------------------------------
43412855Sgabeblack@google.com  case 0x58:
43512855Sgabeblack@google.com  case 0x59:
43612855Sgabeblack@google.com  case 0x5A:
43712855Sgabeblack@google.com  case 0x5B:
43812855Sgabeblack@google.com  case 0x5C:
43912855Sgabeblack@google.com  case 0x5d:
44012855Sgabeblack@google.com  case 0x5e:
44112855Sgabeblack@google.com  case 0x5f: {
44212855Sgabeblack@google.com    // and register to A
44312855Sgabeblack@google.com    i->type = i_and;
44412855Sgabeblack@google.com    i->n_src = 2;
44512855Sgabeblack@google.com    i->src1.type = o_reg;
44612855Sgabeblack@google.com    i->src1.val = opcode&0x07;
44712855Sgabeblack@google.com    i->src2.type = o_acc;
44812855Sgabeblack@google.com    i->dst.type = o_acc;
44912855Sgabeblack@google.com    i->cycle = 1;
45012855Sgabeblack@google.com    break;
45112855Sgabeblack@google.com  }
45212855Sgabeblack@google.com  case 0x55: {
45312855Sgabeblack@google.com    // and direct byte to A
45412855Sgabeblack@google.com    i->type = i_and;
45512855Sgabeblack@google.com    i->n_src = 2;
45612855Sgabeblack@google.com    i->src1.type = o_dir;
45712855Sgabeblack@google.com    i->src2.type = o_acc;
45812855Sgabeblack@google.com    i->dst.type = o_acc;
45912855Sgabeblack@google.com    i->cycle = 2;
46012855Sgabeblack@google.com    break;
46112855Sgabeblack@google.com  }
46212855Sgabeblack@google.com  case 0x56:
46312855Sgabeblack@google.com  case 0x57: {
46412855Sgabeblack@google.com    // and data memory to A
46512855Sgabeblack@google.com    i->type = i_and;
46612855Sgabeblack@google.com    i->n_src = 2;
46712855Sgabeblack@google.com    i->src1.type = o_ind;
46812855Sgabeblack@google.com    i->src1.val = opcode&1;
46912855Sgabeblack@google.com    i->src2.type = o_acc;
47012855Sgabeblack@google.com    i->dst.type = o_acc;
47112855Sgabeblack@google.com    i->cycle = 1;
47212855Sgabeblack@google.com    break;
47312855Sgabeblack@google.com  }
47412855Sgabeblack@google.com  case 0x54: {
47512855Sgabeblack@google.com    // and immediate to A
47612855Sgabeblack@google.com    i->type = i_and;
47712855Sgabeblack@google.com    i->n_src = 2;
47812855Sgabeblack@google.com    i->src1.type = o_cst;
47912855Sgabeblack@google.com    i->src2.type = o_acc;
48012855Sgabeblack@google.com    i->dst.type = o_acc;
48112855Sgabeblack@google.com    i->cycle = 2;
48212855Sgabeblack@google.com    break;
48312855Sgabeblack@google.com  }
48412855Sgabeblack@google.com  case 0x52: {
48512855Sgabeblack@google.com    // and A to direct byte
48612855Sgabeblack@google.com    i->type = i_and;
48712855Sgabeblack@google.com    i->n_src = 2;
48812855Sgabeblack@google.com    i->src1.type = o_dir;
48912855Sgabeblack@google.com    i->src2.type = o_acc;
49012855Sgabeblack@google.com    i->dst.type = o_dir;
49112855Sgabeblack@google.com    i->cycle = 2;
49212855Sgabeblack@google.com    break;
49312855Sgabeblack@google.com  }
49412855Sgabeblack@google.com  case 0x53: {
49512855Sgabeblack@google.com    // and immdiate to direct byte
49612855Sgabeblack@google.com    i->type = i_and;
49712855Sgabeblack@google.com    i->n_src = 2;
49812855Sgabeblack@google.com    i->src1.type = o_dir;
49912855Sgabeblack@google.com    i->src2.type = o_cst;
50012855Sgabeblack@google.com    i->dst.type = o_dir;
50112855Sgabeblack@google.com    i->cycle = 3;
50212855Sgabeblack@google.com    break;
50312855Sgabeblack@google.com  }
50412855Sgabeblack@google.com  case 0x48:
50512855Sgabeblack@google.com  case 0x49:
50612855Sgabeblack@google.com  case 0x4A:
50712855Sgabeblack@google.com  case 0x4B:
50812855Sgabeblack@google.com  case 0x4C:
50912855Sgabeblack@google.com  case 0x4d:
51012855Sgabeblack@google.com  case 0x4e:
51112855Sgabeblack@google.com  case 0x4f: {
51212855Sgabeblack@google.com    // or register to A
51312855Sgabeblack@google.com    i->type = i_or;
51412855Sgabeblack@google.com    i->n_src = 2;
51512855Sgabeblack@google.com    i->src1.type = o_reg;
51612855Sgabeblack@google.com    i->src1.val = opcode&0x07;
51712855Sgabeblack@google.com    i->src2.type = o_acc;
51812855Sgabeblack@google.com    i->dst.type = o_acc;
51912855Sgabeblack@google.com    i->cycle = 1;
52012855Sgabeblack@google.com    break;
52112855Sgabeblack@google.com  }
52212855Sgabeblack@google.com  case 0x45: {
52312855Sgabeblack@google.com    // or direct byte to A
52412855Sgabeblack@google.com    i->type = i_or;
52512855Sgabeblack@google.com    i->n_src = 2;
52612855Sgabeblack@google.com    i->src1.type = o_dir;
52712855Sgabeblack@google.com    i->src2.type = o_acc;
52812855Sgabeblack@google.com    i->dst.type = o_acc;
52912855Sgabeblack@google.com    i->cycle = 2;
53012855Sgabeblack@google.com    break;
53112855Sgabeblack@google.com  }
53212855Sgabeblack@google.com  case 0x46:
53312855Sgabeblack@google.com  case 0x47: {
53412855Sgabeblack@google.com    // or data memory to A
53512855Sgabeblack@google.com    i->type = i_or;
53612855Sgabeblack@google.com    i->n_src = 2;
53712855Sgabeblack@google.com    i->src1.type = o_ind;
53812855Sgabeblack@google.com    i->src1.val = opcode&1;
53912855Sgabeblack@google.com    i->src2.type = o_acc;
54012855Sgabeblack@google.com    i->dst.type = o_acc;
54112855Sgabeblack@google.com    i->cycle = 1;
54212855Sgabeblack@google.com    break;
54312855Sgabeblack@google.com  }
54412855Sgabeblack@google.com  case 0x44: {
54512855Sgabeblack@google.com    // or immediate to A
54612855Sgabeblack@google.com    i->type = i_or;
54712855Sgabeblack@google.com    i->n_src = 2;
54812855Sgabeblack@google.com    i->src1.type = o_cst;
54912855Sgabeblack@google.com    i->src2.type = o_acc;
55012855Sgabeblack@google.com    i->dst.type = o_acc;
55112855Sgabeblack@google.com    i->cycle = 2;
55212855Sgabeblack@google.com    break;
55312855Sgabeblack@google.com  }
55412855Sgabeblack@google.com  case 0x42: {
55512855Sgabeblack@google.com    // or A to direct byte
55612855Sgabeblack@google.com    i->type = i_or;
55712855Sgabeblack@google.com    i->n_src = 2;
55812855Sgabeblack@google.com    i->src1.type = o_dir;
55912855Sgabeblack@google.com    i->src2.type = o_acc;
56012855Sgabeblack@google.com    i->dst.type = o_dir;
56112855Sgabeblack@google.com    i->cycle = 2;
56212855Sgabeblack@google.com    break;
56312855Sgabeblack@google.com  }
56412855Sgabeblack@google.com  case 0x43: {
56512855Sgabeblack@google.com    // or immediate to direct byte
56612855Sgabeblack@google.com    i->type = i_or;
56712855Sgabeblack@google.com    i->n_src = 2;
56812855Sgabeblack@google.com    i->src1.type = o_dir;
56912855Sgabeblack@google.com    i->src2.type = o_cst;
57012855Sgabeblack@google.com    i->dst.type = o_dir;
57112855Sgabeblack@google.com    i->cycle = 3;
57212855Sgabeblack@google.com    break;
57312855Sgabeblack@google.com  }
57412855Sgabeblack@google.com  case 0x68:
57512855Sgabeblack@google.com  case 0x69:
57612855Sgabeblack@google.com  case 0x6A:
57712855Sgabeblack@google.com  case 0x6B:
57812855Sgabeblack@google.com  case 0x6C:
57912855Sgabeblack@google.com  case 0x6d:
58012855Sgabeblack@google.com  case 0x6e:
58112855Sgabeblack@google.com  case 0x6f: {
58212855Sgabeblack@google.com    // xor register to A
58312855Sgabeblack@google.com    i->type = i_xor;
58412855Sgabeblack@google.com    i->n_src = 2;
58512855Sgabeblack@google.com    i->src1.type = o_reg;
58612855Sgabeblack@google.com    i->src1.val = opcode&0x07;
58712855Sgabeblack@google.com    i->src2.type = o_acc;
58812855Sgabeblack@google.com    i->dst.type = o_acc;
58912855Sgabeblack@google.com    i->cycle = 1;
59012855Sgabeblack@google.com    break;
59112855Sgabeblack@google.com  }
59212855Sgabeblack@google.com  case 0x65: {
59312855Sgabeblack@google.com    // xor direct byte to A
59412855Sgabeblack@google.com    i->type = i_xor;
59512855Sgabeblack@google.com    i->n_src = 2;
59612855Sgabeblack@google.com    i->src1.type = o_dir;
59712855Sgabeblack@google.com    i->src2.type = o_acc;
59812855Sgabeblack@google.com    i->dst.type = o_acc;
59912855Sgabeblack@google.com    i->cycle = 2;
60012855Sgabeblack@google.com    break;
60112855Sgabeblack@google.com  }
60212855Sgabeblack@google.com  case 0x66:
60312855Sgabeblack@google.com  case 0x67: {
60412855Sgabeblack@google.com    // xor data memory to A
60512855Sgabeblack@google.com    i->type = i_xor;
60612855Sgabeblack@google.com    i->n_src = 2;
60712855Sgabeblack@google.com    i->src1.type = o_ind;
60812855Sgabeblack@google.com    i->src1.val = opcode&1;
60912855Sgabeblack@google.com    i->src2.type = o_acc;
61012855Sgabeblack@google.com    i->dst.type = o_acc;
61112855Sgabeblack@google.com    i->cycle = 1;
61212855Sgabeblack@google.com    break;
61312855Sgabeblack@google.com  }
61412855Sgabeblack@google.com  case 0x64: {
61512855Sgabeblack@google.com    // xor immediate to A
61612855Sgabeblack@google.com    i->type = i_xor;
61712855Sgabeblack@google.com    i->n_src = 2;
61812855Sgabeblack@google.com    i->src1.type = o_cst;
61912855Sgabeblack@google.com    i->src2.type = o_acc;
62012855Sgabeblack@google.com    i->dst.type = o_acc;
62112855Sgabeblack@google.com    i->cycle = 2;
62212855Sgabeblack@google.com    break;
62312855Sgabeblack@google.com  }
62412855Sgabeblack@google.com  case 0x62: {
62512855Sgabeblack@google.com    // and A to direct byte
62612855Sgabeblack@google.com    i->type = i_xor;
62712855Sgabeblack@google.com    i->n_src = 2;
62812855Sgabeblack@google.com    i->src1.type = o_dir;
62912855Sgabeblack@google.com    i->src2.type = o_acc;
63012855Sgabeblack@google.com    i->dst.type = o_dir;
63112855Sgabeblack@google.com    i->cycle = 2;
63212855Sgabeblack@google.com    break;
63312855Sgabeblack@google.com  }
63412855Sgabeblack@google.com  case 0x63: {
63512855Sgabeblack@google.com    // xor immdiate to direct byte
63612855Sgabeblack@google.com    i->type = i_xor;
63712855Sgabeblack@google.com    i->n_src = 2;
63812855Sgabeblack@google.com    i->src1.type = o_dir;
63912855Sgabeblack@google.com    i->src2.type = o_cst;
64012855Sgabeblack@google.com    i->dst.type = o_dir;
64112855Sgabeblack@google.com    i->cycle = 3;
64212855Sgabeblack@google.com    break;
64312855Sgabeblack@google.com  }
64412855Sgabeblack@google.com  case 0xf4: {
64512855Sgabeblack@google.com    // complement A
64612855Sgabeblack@google.com    i->type = i_cpl;
64712855Sgabeblack@google.com    i->n_src = 1;
64812855Sgabeblack@google.com    i->src1.type = o_acc;
64912855Sgabeblack@google.com    i->dst.type = o_acc;
65012855Sgabeblack@google.com    i->cycle = 1;
65112855Sgabeblack@google.com    break;
65212855Sgabeblack@google.com  }
65312855Sgabeblack@google.com  case 0x23: {
65412855Sgabeblack@google.com    // rotate A left
65512855Sgabeblack@google.com    i->type = i_rl;
65612855Sgabeblack@google.com    i->n_src = 1;
65712855Sgabeblack@google.com    i->src1.type = o_acc;
65812855Sgabeblack@google.com    i->dst.type = o_acc;
65912855Sgabeblack@google.com    i->cycle = 1;
66012855Sgabeblack@google.com    break;
66112855Sgabeblack@google.com  }
66212855Sgabeblack@google.com  case 0x03: {
66312855Sgabeblack@google.com    // rotate A right
66412855Sgabeblack@google.com    i->type = i_rr;
66512855Sgabeblack@google.com    i->n_src = 1;
66612855Sgabeblack@google.com    i->src1.type = o_acc;
66712855Sgabeblack@google.com    i->dst.type = o_acc;
66812855Sgabeblack@google.com    i->cycle = 1;
66912855Sgabeblack@google.com    break;
67012855Sgabeblack@google.com  }
67112855Sgabeblack@google.com  // data transfer -----------------------------------------------
67212855Sgabeblack@google.com  case 0xe8:
67312855Sgabeblack@google.com  case 0xe9:
67412855Sgabeblack@google.com  case 0xeA:
67512855Sgabeblack@google.com  case 0xeB:
67612855Sgabeblack@google.com  case 0xeC:
67712855Sgabeblack@google.com  case 0xed:
67812855Sgabeblack@google.com  case 0xee:
67912855Sgabeblack@google.com  case 0xef: {
68012855Sgabeblack@google.com    // move register to A
68112855Sgabeblack@google.com    i->type = i_mov;
68212855Sgabeblack@google.com    i->n_src = 1;
68312855Sgabeblack@google.com    i->src1.type = o_reg;
68412855Sgabeblack@google.com    i->src1.val = opcode&0x07;
68512855Sgabeblack@google.com    i->dst.type = o_acc;
68612855Sgabeblack@google.com    i->cycle = 1;
68712855Sgabeblack@google.com    break;
68812855Sgabeblack@google.com  }
68912855Sgabeblack@google.com  case 0xe5: {
69012855Sgabeblack@google.com    // move direct bit to A
69112855Sgabeblack@google.com    i->type = i_mov;
69212855Sgabeblack@google.com    i->n_src = 1;
69312855Sgabeblack@google.com    i->src1.type = o_dir;
69412855Sgabeblack@google.com    i->dst.type = o_acc;
69512855Sgabeblack@google.com    i->cycle = 2;
69612855Sgabeblack@google.com    break;
69712855Sgabeblack@google.com  }
69812855Sgabeblack@google.com  case 0xe6:
69912855Sgabeblack@google.com  case 0xe7: {
70012855Sgabeblack@google.com    // move data memory to A
70112855Sgabeblack@google.com    i->type = i_mov;
70212855Sgabeblack@google.com    i->n_src = 1;
70312855Sgabeblack@google.com    i->src1.type = o_ind;
70412855Sgabeblack@google.com    i->src1.val = opcode&1;
70512855Sgabeblack@google.com    i->dst.type = o_acc;
70612855Sgabeblack@google.com    i->cycle = 1;
70712855Sgabeblack@google.com    break;
70812855Sgabeblack@google.com  }
70912855Sgabeblack@google.com  case 0x74: {
71012855Sgabeblack@google.com    // move immediate to A
71112855Sgabeblack@google.com    i->type = i_mov;
71212855Sgabeblack@google.com    i->n_src = 1;
71312855Sgabeblack@google.com    i->src1.type = o_cst;
71412855Sgabeblack@google.com    i->dst.type = o_acc;
71512855Sgabeblack@google.com    i->cycle = 2;
71612855Sgabeblack@google.com    break;
71712855Sgabeblack@google.com  }
71812855Sgabeblack@google.com  case 0xf8:
71912855Sgabeblack@google.com  case 0xf9:
72012855Sgabeblack@google.com  case 0xfA:
72112855Sgabeblack@google.com  case 0xfB:
72212855Sgabeblack@google.com  case 0xfC:
72312855Sgabeblack@google.com  case 0xfd:
72412855Sgabeblack@google.com  case 0xfe:
72512855Sgabeblack@google.com  case 0xff: {
72612855Sgabeblack@google.com    // move A to register
72712855Sgabeblack@google.com    i->type = i_mov;
72812855Sgabeblack@google.com    i->n_src = 1;
72912855Sgabeblack@google.com    i->src1.type = o_acc;
73012855Sgabeblack@google.com    i->dst.type = o_reg;
73112855Sgabeblack@google.com    i->dst.val = opcode&0x07;
73212855Sgabeblack@google.com    i->cycle = 1;
73312855Sgabeblack@google.com    break;
73412855Sgabeblack@google.com  }
73512855Sgabeblack@google.com  case 0xa8:
73612855Sgabeblack@google.com  case 0xa9:
73712855Sgabeblack@google.com  case 0xaA:
73812855Sgabeblack@google.com  case 0xaB:
73912855Sgabeblack@google.com  case 0xaC:
74012855Sgabeblack@google.com  case 0xad:
74112855Sgabeblack@google.com  case 0xae:
74212855Sgabeblack@google.com  case 0xaf: {
74312855Sgabeblack@google.com    // move direct to register
74412855Sgabeblack@google.com    i->type = i_mov;
74512855Sgabeblack@google.com    i->n_src = 1;
74612855Sgabeblack@google.com    i->src1.type = o_dir;
74712855Sgabeblack@google.com    i->dst.type = o_reg;
74812855Sgabeblack@google.com    i->dst.val = opcode&0x07;
74912855Sgabeblack@google.com    i->cycle = 2;
75012855Sgabeblack@google.com    break;
75112855Sgabeblack@google.com  }
75212855Sgabeblack@google.com  case 0x78:
75312855Sgabeblack@google.com  case 0x79:
75412855Sgabeblack@google.com  case 0x7A:
75512855Sgabeblack@google.com  case 0x7B:
75612855Sgabeblack@google.com  case 0x7C:
75712855Sgabeblack@google.com  case 0x7d:
75812855Sgabeblack@google.com  case 0x7e:
75912855Sgabeblack@google.com  case 0x7f: {
76012855Sgabeblack@google.com    // move immediate to register
76112855Sgabeblack@google.com    i->type = i_mov;
76212855Sgabeblack@google.com    i->n_src = 1;
76312855Sgabeblack@google.com    i->src1.type = o_cst;
76412855Sgabeblack@google.com    i->dst.type = o_reg;
76512855Sgabeblack@google.com    i->dst.val = opcode&0x07;
76612855Sgabeblack@google.com    i->cycle = 2;
76712855Sgabeblack@google.com    break;
76812855Sgabeblack@google.com  }
76912855Sgabeblack@google.com  case 0xf5: {
77012855Sgabeblack@google.com    // move A to direct byte
77112855Sgabeblack@google.com    i->type = i_mov;
77212855Sgabeblack@google.com    i->n_src = 1;
77312855Sgabeblack@google.com    i->src1.type = o_acc;
77412855Sgabeblack@google.com    i->dst.type = o_dir;
77512855Sgabeblack@google.com    i->cycle = 2;
77612855Sgabeblack@google.com  }
77712855Sgabeblack@google.com  case 0x88:
77812855Sgabeblack@google.com  case 0x89:
77912855Sgabeblack@google.com  case 0x8A:
78012855Sgabeblack@google.com  case 0x8B:
78112855Sgabeblack@google.com  case 0x8C:
78212855Sgabeblack@google.com  case 0x8d:
78312855Sgabeblack@google.com  case 0x8e:
78412855Sgabeblack@google.com  case 0x8f: {
78512855Sgabeblack@google.com    // move register to direct byte
78612855Sgabeblack@google.com    i->type = i_mov;
78712855Sgabeblack@google.com    i->n_src = 1;
78812855Sgabeblack@google.com    i->src1.type = o_reg;
78912855Sgabeblack@google.com    i->src1.val = opcode&0x07;
79012855Sgabeblack@google.com    i->dst.type = o_dir;
79112855Sgabeblack@google.com    i->cycle = 2;
79212855Sgabeblack@google.com    break;
79312855Sgabeblack@google.com  }
79412855Sgabeblack@google.com  case 0x85: {
79512855Sgabeblack@google.com    // move direct byte to direct byte
79612855Sgabeblack@google.com    i->type = i_mov;
79712855Sgabeblack@google.com    i->n_src = 1;
79812855Sgabeblack@google.com    i->src1.type = o_dir;
79912855Sgabeblack@google.com    i->dst.type = o_dir;
80012855Sgabeblack@google.com    i->cycle = 3;
80112855Sgabeblack@google.com    break;
80212855Sgabeblack@google.com  }
80312855Sgabeblack@google.com  case 0x86:
80412855Sgabeblack@google.com  case 0x87: {
80512855Sgabeblack@google.com    // move data memory to direct byte
80612855Sgabeblack@google.com    i->type = i_mov;
80712855Sgabeblack@google.com    i->n_src = 1;
80812855Sgabeblack@google.com    i->src1.type = o_ind;
80912855Sgabeblack@google.com    i->src1.val = opcode&0x01;
81012855Sgabeblack@google.com    i->dst.type = o_dir;
81112855Sgabeblack@google.com    i->cycle = 2;
81212855Sgabeblack@google.com    break;
81312855Sgabeblack@google.com  }
81412855Sgabeblack@google.com  case 0x75: {
81512855Sgabeblack@google.com    // move immediate to direct byte
81612855Sgabeblack@google.com    i->type = i_mov;
81712855Sgabeblack@google.com    i->n_src = 1;
81812855Sgabeblack@google.com    i->src1.type = o_cst;
81912855Sgabeblack@google.com    i->dst.type = o_dir;
82012855Sgabeblack@google.com    i->cycle = 2;
82112855Sgabeblack@google.com    break;
82212855Sgabeblack@google.com    }
82312855Sgabeblack@google.com  case 0xf6:
82412855Sgabeblack@google.com  case 0xf7: {
82512855Sgabeblack@google.com    // move A to data memory
82612855Sgabeblack@google.com    i->type = i_mov;
82712855Sgabeblack@google.com    i->n_src = 1;
82812855Sgabeblack@google.com    i->src1.type = o_acc;
82912855Sgabeblack@google.com    i->dst.type = o_ind;
83012855Sgabeblack@google.com    i->dst.val = opcode&1;
83112855Sgabeblack@google.com    i->cycle = 1;
83212855Sgabeblack@google.com    break;
83312855Sgabeblack@google.com  }
83412855Sgabeblack@google.com  case 0xa6:
83512855Sgabeblack@google.com  case 0xa7: {
83612855Sgabeblack@google.com    // move direct byte to data memory
83712855Sgabeblack@google.com    i->type = i_mov;
83812855Sgabeblack@google.com    i->n_src = 1;
83912855Sgabeblack@google.com    i->src1.type = o_dir;
84012855Sgabeblack@google.com    i->dst.type = o_ind;
84112855Sgabeblack@google.com    i->dst.val = opcode&1;
84212855Sgabeblack@google.com    i->cycle = 2;
84312855Sgabeblack@google.com    break;
84412855Sgabeblack@google.com  }
84512855Sgabeblack@google.com  case 0x76:
84612855Sgabeblack@google.com  case 0x77: {
84712855Sgabeblack@google.com    // move immediate to data memory
84812855Sgabeblack@google.com    i->type = i_mov;
84912855Sgabeblack@google.com    i->n_src = 1;
85012855Sgabeblack@google.com    i->src1.type = o_cst;
85112855Sgabeblack@google.com    i->dst.type = o_ind;
85212855Sgabeblack@google.com    i->dst.val = opcode&1;
85312855Sgabeblack@google.com    i->cycle = 2;
85412855Sgabeblack@google.com    break;
85512855Sgabeblack@google.com  }
85612855Sgabeblack@google.com  case 0xe2:
85712855Sgabeblack@google.com  case 0xe3: {
85812855Sgabeblack@google.com    // move external data to A
85912855Sgabeblack@google.com    i->type = i_mov;
86012855Sgabeblack@google.com    i->n_src = 1;
86112855Sgabeblack@google.com    i->src1.type = o_ext;
86212855Sgabeblack@google.com    i->src1.val = opcode&1;
86312855Sgabeblack@google.com    i->dst.type = o_acc;
86412855Sgabeblack@google.com    i->cycle = 2+stretch_cycles;
86512855Sgabeblack@google.com    break;
86612855Sgabeblack@google.com  }
86712855Sgabeblack@google.com  case 0xf2:
86812855Sgabeblack@google.com  case 0xf3: {
86912855Sgabeblack@google.com    // move A to external data
87012855Sgabeblack@google.com    i->type = i_mov;
87112855Sgabeblack@google.com    i->n_src = 1;
87212855Sgabeblack@google.com    i->src1.type = o_acc;
87312855Sgabeblack@google.com    i->dst.type = o_ext;
87412855Sgabeblack@google.com    i->dst.val = opcode&1;
87512855Sgabeblack@google.com    i->cycle = 2+stretch_cycles;
87612855Sgabeblack@google.com    break;
87712855Sgabeblack@google.com  }
87812855Sgabeblack@google.com  // branching ----------------------------------------------------
87912855Sgabeblack@google.com  case 0x11:
88012855Sgabeblack@google.com  case 0x31:
88112855Sgabeblack@google.com  case 0x51:
88212855Sgabeblack@google.com  case 0x71:
88312855Sgabeblack@google.com  case 0x91:
88412855Sgabeblack@google.com  case 0xb1:
88512855Sgabeblack@google.com  case 0xd1:
88612855Sgabeblack@google.com  case 0xf1: {
88712855Sgabeblack@google.com    // absolute call to subroutine
88812855Sgabeblack@google.com    i->type = i_call;
88912855Sgabeblack@google.com    i->n_src = 1;
89012855Sgabeblack@google.com    i->src1.type = o_add;
89112855Sgabeblack@google.com    i->src1.val = (opcode>>5)&7;
89212855Sgabeblack@google.com    i->cycle = 3;
89312855Sgabeblack@google.com    break;
89412855Sgabeblack@google.com  }
89512855Sgabeblack@google.com  case 0x12: {
89612855Sgabeblack@google.com    // Long call to subroutine
89712855Sgabeblack@google.com    i->type = i_call;
89812855Sgabeblack@google.com    i->n_src = 1;
89912855Sgabeblack@google.com    i->src1.type = o_ladd;
90012855Sgabeblack@google.com    i->cycle = 4;
90112855Sgabeblack@google.com    break;
90212855Sgabeblack@google.com  }
90312855Sgabeblack@google.com  case 0x22: {
90412855Sgabeblack@google.com    // return from subroutine
90512855Sgabeblack@google.com    i->type = i_ret;
90612855Sgabeblack@google.com    i->cycle = 4;
90712855Sgabeblack@google.com    break;
90812855Sgabeblack@google.com  }
90912855Sgabeblack@google.com  case 0x01:
91012855Sgabeblack@google.com  case 0x21:
91112855Sgabeblack@google.com  case 0x41:
91212855Sgabeblack@google.com  case 0x61:
91312855Sgabeblack@google.com  case 0x81:
91412855Sgabeblack@google.com  case 0xa1:
91512855Sgabeblack@google.com  case 0xc1:
91612855Sgabeblack@google.com  case 0xe1: {
91712855Sgabeblack@google.com    // absolute jump unconditional
91812855Sgabeblack@google.com    i->type = i_jmp;
91912855Sgabeblack@google.com    i->n_src = 1;
92012855Sgabeblack@google.com    i->src1.type = o_add;
92112855Sgabeblack@google.com    i->src1.val = (opcode>>5)&7;
92212855Sgabeblack@google.com    i->cycle = 3;
92312855Sgabeblack@google.com    break;
92412855Sgabeblack@google.com  }
92512855Sgabeblack@google.com  case 0x02: {
92612855Sgabeblack@google.com    // Long jump unconditional
92712855Sgabeblack@google.com    i->type = i_jmp;
92812855Sgabeblack@google.com    i->n_src = 1;
92912855Sgabeblack@google.com    i->src1.type = o_ladd;
93012855Sgabeblack@google.com    i->cycle = 4;
93112855Sgabeblack@google.com    break;
93212855Sgabeblack@google.com  }
93312855Sgabeblack@google.com  case 0x60: {
93412855Sgabeblack@google.com    // jump on accumulator = 0
93512855Sgabeblack@google.com    i->type = i_jz;
93612855Sgabeblack@google.com    i->n_src = 1;
93712855Sgabeblack@google.com    i->src1.type = o_rel;
93812855Sgabeblack@google.com    i->cycle = 3;
93912855Sgabeblack@google.com    break;
94012855Sgabeblack@google.com  }
94112855Sgabeblack@google.com  case 0x70: {
94212855Sgabeblack@google.com    // jump on accumulator != 0
94312855Sgabeblack@google.com    i->type = i_jnz;
94412855Sgabeblack@google.com    i->n_src = 1;
94512855Sgabeblack@google.com    i->src1.type = o_rel;
94612855Sgabeblack@google.com    i->cycle = 3;
94712855Sgabeblack@google.com    break;
94812855Sgabeblack@google.com  }
94912855Sgabeblack@google.com  case 0xb5: {
95012855Sgabeblack@google.com    // compare A,direct JNE
95112855Sgabeblack@google.com    i->type = i_cjne;
95212855Sgabeblack@google.com    i->n_src = 2;
95312855Sgabeblack@google.com    i->src1.type = o_acc;
95412855Sgabeblack@google.com    i->src2.type = o_dir;
95512855Sgabeblack@google.com    i->dst.type = o_rel;
95612855Sgabeblack@google.com    i->cycle = 4;
95712855Sgabeblack@google.com    break;
95812855Sgabeblack@google.com  }
95912855Sgabeblack@google.com  case 0xb4: {
96012855Sgabeblack@google.com    // compare A,immeditate JNE
96112855Sgabeblack@google.com    i->type = i_cjne;
96212855Sgabeblack@google.com    i->n_src = 2;
96312855Sgabeblack@google.com    i->src1.type = o_acc;
96412855Sgabeblack@google.com    i->src2.type = o_cst;
96512855Sgabeblack@google.com    i->dst.type = o_rel;
96612855Sgabeblack@google.com    i->cycle = 4;
96712855Sgabeblack@google.com    break;
96812855Sgabeblack@google.com  }
96912855Sgabeblack@google.com  case 0xB8:
97012855Sgabeblack@google.com  case 0xB9:
97112855Sgabeblack@google.com  case 0xBa:
97212855Sgabeblack@google.com  case 0xBb:
97312855Sgabeblack@google.com  case 0xBc:
97412855Sgabeblack@google.com  case 0xBd:
97512855Sgabeblack@google.com  case 0xBe:
97612855Sgabeblack@google.com  case 0xBf: {
97712855Sgabeblack@google.com    // compare reg,immeditate JNE
97812855Sgabeblack@google.com    i->type = i_cjne;
97912855Sgabeblack@google.com    i->n_src = 2;
98012855Sgabeblack@google.com    i->src1.type = o_reg;
98112855Sgabeblack@google.com    i->src1.val = opcode & 0x7;
98212855Sgabeblack@google.com    i->src2.type = o_cst;
98312855Sgabeblack@google.com    i->dst.type = o_rel;
98412855Sgabeblack@google.com    i->cycle = 4;
98512855Sgabeblack@google.com    break;
98612855Sgabeblack@google.com  }
98712855Sgabeblack@google.com  case 0xb6:
98812855Sgabeblack@google.com  case 0xb7: {
98912855Sgabeblack@google.com    // compare memory byte,immeditate JNE
99012855Sgabeblack@google.com    i->type = i_cjne;
99112855Sgabeblack@google.com    i->n_src = 2;
99212855Sgabeblack@google.com    i->src1.type = o_ind;
99312855Sgabeblack@google.com    i->src1.val = opcode & 0x1;
99412855Sgabeblack@google.com    i->src2.type = o_cst;
99512855Sgabeblack@google.com    i->dst.type = o_rel;
99612855Sgabeblack@google.com    i->cycle = 4;
99712855Sgabeblack@google.com    break;
99812855Sgabeblack@google.com  }
99912855Sgabeblack@google.com  case 0xd8:
100012855Sgabeblack@google.com  case 0xd9:
100112855Sgabeblack@google.com  case 0xda:
100212855Sgabeblack@google.com  case 0xdb:
100312855Sgabeblack@google.com  case 0xdc:
100412855Sgabeblack@google.com  case 0xdd:
100512855Sgabeblack@google.com  case 0xde:
100612855Sgabeblack@google.com  case 0xdf: {
100712855Sgabeblack@google.com    // decrement reg, JNZ relative
100812855Sgabeblack@google.com    i->type = i_djnz;
100912855Sgabeblack@google.com    i->n_src = 2;
101012855Sgabeblack@google.com    i->src1.type = o_reg;
101112855Sgabeblack@google.com    i->src1.val = opcode & 0x7;
101212855Sgabeblack@google.com    i->src2.type = o_rel;
101312855Sgabeblack@google.com    i->cycle = 3;
101412855Sgabeblack@google.com    break;
101512855Sgabeblack@google.com  }
101612855Sgabeblack@google.com  case 0xd5: {
101712855Sgabeblack@google.com    // decrement direct byte, JNZ relative
101812855Sgabeblack@google.com    i->type = i_djnz;
101912855Sgabeblack@google.com    i->n_src = 2;
102012855Sgabeblack@google.com    i->src1.type = o_dir;
102112855Sgabeblack@google.com    i->src2.type = o_rel;
102212855Sgabeblack@google.com    i->cycle = 4;
102312855Sgabeblack@google.com    break;
102412855Sgabeblack@google.com  }
102512855Sgabeblack@google.com  // NOP --------------------------------------------------------------
102612855Sgabeblack@google.com  case 0x00: {
102712855Sgabeblack@google.com    break;
102812855Sgabeblack@google.com  }
102912855Sgabeblack@google.com  default: {
103012855Sgabeblack@google.com
103112855Sgabeblack@google.com    break;
103212855Sgabeblack@google.com    fprintf(stderr,"opcode 0x%x not supported\n",opcode);
103312855Sgabeblack@google.com    break;
103412855Sgabeblack@google.com  }
103512855Sgabeblack@google.com  }
103612855Sgabeblack@google.com
103712855Sgabeblack@google.com#ifdef DEBUG
103812855Sgabeblack@google.com  printf("decode instr type:%d, src1: %d, src2: %d, dest %d, nb_cycles: %d\n",i->type, i->src1.type, i->src2.type, i->dst.type, i->cycle);
103912855Sgabeblack@google.com#endif
104012855Sgabeblack@google.com}
104112855Sgabeblack@google.com
104212855Sgabeblack@google.com
104312855Sgabeblack@google.com//--------------------------------------------------------------------
104412855Sgabeblack@google.com// bool request_address(int ad);
104512855Sgabeblack@google.com//
104612855Sgabeblack@google.com//    return 0 if the memory adress is external (i.e. external peripheral)
104712855Sgabeblack@google.com//    update cycles2execute so that the simulation runs for a given
104812855Sgabeblack@google.com//    number of clock cycles.
104912855Sgabeblack@google.com//
105012855Sgabeblack@google.com//--------------------------------------------------------------------
105112855Sgabeblack@google.combool cycle_model::request_address(int ad) {
105212855Sgabeblack@google.com  // add peripheral driver here
105312855Sgabeblack@google.com  //
105412855Sgabeblack@google.com  // if(ad==<ADDRESS OF THE PERIPH>) {
105512855Sgabeblack@google.com  //    if(cycles2execute<=<NB_CYCLES>)
105612855Sgabeblack@google.com  //        cycles2execute = <NB_CYCLES>;
105712855Sgabeblack@google.com  //    return 0;
105812855Sgabeblack@google.com  // }
105912855Sgabeblack@google.com
106012855Sgabeblack@google.com  if(ad==0x10) {
106112855Sgabeblack@google.com    if(cycles2execute<=30)
106212855Sgabeblack@google.com      cycles2execute = 30;
106312855Sgabeblack@google.com    return 0;
106412855Sgabeblack@google.com  }
106512855Sgabeblack@google.com
106612855Sgabeblack@google.com  if(ad==0x11) {
106712855Sgabeblack@google.com    return 0;
106812855Sgabeblack@google.com  }
106912855Sgabeblack@google.com
107012855Sgabeblack@google.com  return 1;
107112855Sgabeblack@google.com}
107212855Sgabeblack@google.com
107312855Sgabeblack@google.com
107412855Sgabeblack@google.com//--------------------------------------------------------------------
107512855Sgabeblack@google.com// exec_bus_cycle(bus_cycle_type op, int addr, int data, int* result)
107612855Sgabeblack@google.com//
107712855Sgabeblack@google.com//    executes a bus cycle (IDLE, MEM_READ, MEM_WRITE).
107812855Sgabeblack@google.com//       - IDLE: executes an idle cycle (4 clocks)
107912855Sgabeblack@google.com//       - MEM_READ: reads from the memory bus (stretch+1 clocks)
108012855Sgabeblack@google.com//       - MEM_WRITE: writes on the memory bus (stretch+1 clocks)
108112855Sgabeblack@google.com//
108212855Sgabeblack@google.com//--------------------------------------------------------------------
108312855Sgabeblack@google.comvoid cycle_model::exec_bus_cycle(bus_cycle_type op, int addr, int data, int* result) {
108412855Sgabeblack@google.com  int cycles = 0;
108512855Sgabeblack@google.com  int mem_idle =0;
108612855Sgabeblack@google.com
108712855Sgabeblack@google.com
108812855Sgabeblack@google.com  if(op==OP_IDLE) {
108912855Sgabeblack@google.com    // OP_IDLE
109012855Sgabeblack@google.com    if((cycles2execute>0)||ALL_CYCLES) {
109112855Sgabeblack@google.com      // wait 4 cycles
109212855Sgabeblack@google.com      mem_ale.write(0);
109312855Sgabeblack@google.com      mem_wr_n.write(1);
109412855Sgabeblack@google.com      mem_pswr_n.write(1);
109512855Sgabeblack@google.com      mem_rd_n.write(1);
109612855Sgabeblack@google.com      mem_psrd_n.write(1);
109712855Sgabeblack@google.com      p0_mem_reg_n.write(0);
109812855Sgabeblack@google.com      p0_addr_data_n.write(0);
109912855Sgabeblack@google.com      AT_POSEDGE(clk);
110012855Sgabeblack@google.com      AT_POSEDGE(clk);
110112855Sgabeblack@google.com      AT_POSEDGE(clk);
110212855Sgabeblack@google.com      AT_POSEDGE(clk);
110312855Sgabeblack@google.com      cycles2execute -= 1;
110412855Sgabeblack@google.com    }
110512855Sgabeblack@google.com
110612855Sgabeblack@google.com    cycle_count += 1;
110712855Sgabeblack@google.com    return;
110812855Sgabeblack@google.com  }
110912855Sgabeblack@google.com
111012855Sgabeblack@google.com
111112855Sgabeblack@google.com  // OP_MEM_READ or OP_MEM_WRITE
111212855Sgabeblack@google.com  do {
111312855Sgabeblack@google.com    cycles++;
111412855Sgabeblack@google.com
111512855Sgabeblack@google.com    // Cycle 1 *********************************************************
111612855Sgabeblack@google.com    if(mem_idle==0) {
111712855Sgabeblack@google.com      mem_ale.write(1);
111812855Sgabeblack@google.com      mem_wr_n.write(1);
111912855Sgabeblack@google.com      mem_pswr_n.write(1);
112012855Sgabeblack@google.com      mem_rd_n.write(1);
112112855Sgabeblack@google.com      mem_psrd_n.write(1);
112212855Sgabeblack@google.com      p0_mem_reg_n.write(0);
112312855Sgabeblack@google.com      p0_addr_data_n.write(0);
112412855Sgabeblack@google.com
112512855Sgabeblack@google.com      if(op==OP_MEM_WRITE) {
112612855Sgabeblack@google.com	mem_data_out.write( sc_bv<8>( data ) );
112712855Sgabeblack@google.com	p0_mem_reg_n.write(1);
112812855Sgabeblack@google.com	p0_addr_data_n.write(1);
112912855Sgabeblack@google.com      }
113012855Sgabeblack@google.com    }
113112855Sgabeblack@google.com
113212855Sgabeblack@google.com    AT_POSEDGE(clk);
113312855Sgabeblack@google.com
113412855Sgabeblack@google.com
113512855Sgabeblack@google.com    // Cycle 2 *********************************************************
113612855Sgabeblack@google.com    if(mem_idle==0) {
113712855Sgabeblack@google.com      switch (op) {
113812855Sgabeblack@google.com      case OP_MEM_READ: {
113912855Sgabeblack@google.com	mem_addr.write( sc_bv<16>( addr & 0x0000ffff ) );
114012855Sgabeblack@google.com	p0_mem_reg_n.write(1);
114112855Sgabeblack@google.com	p0_addr_data_n.write(1);
114212855Sgabeblack@google.com	p2_mem_reg_n.write(1);
114312855Sgabeblack@google.com	break;
114412855Sgabeblack@google.com      }
114512855Sgabeblack@google.com      case OP_MEM_WRITE: {
114612855Sgabeblack@google.com	mem_addr.write( sc_bv<16>( addr & 0x0000ffff ) );
114712855Sgabeblack@google.com	p0_addr_data_n.write(0);
114812855Sgabeblack@google.com	p2_mem_reg_n.write(1);
114912855Sgabeblack@google.com	break;
115012855Sgabeblack@google.com      }
115112855Sgabeblack@google.com      default: {
115212855Sgabeblack@google.com	// do nothing
115312855Sgabeblack@google.com	break;
115412855Sgabeblack@google.com      }
115512855Sgabeblack@google.com      }
115612855Sgabeblack@google.com    }
115712855Sgabeblack@google.com    if(mem_idle==0) {
115812855Sgabeblack@google.com      AT_NEGEDGE(clk);
115912855Sgabeblack@google.com      mem_ale.write(0);
116012855Sgabeblack@google.com    }
116112855Sgabeblack@google.com
116212855Sgabeblack@google.com    AT_POSEDGE(clk);
116312855Sgabeblack@google.com
116412855Sgabeblack@google.com
116512855Sgabeblack@google.com    // Cycle 3 *********************************************************
116612855Sgabeblack@google.com    if(mem_idle==0) {
116712855Sgabeblack@google.com      switch (op) {
116812855Sgabeblack@google.com      case OP_MEM_READ: {
116912855Sgabeblack@google.com	p0_mem_reg_n.write(0);
117012855Sgabeblack@google.com	p0_addr_data_n.write(0);
117112855Sgabeblack@google.com
117212855Sgabeblack@google.com	if(stretch_cycles==0)
117312855Sgabeblack@google.com	  mem_rd_n.write(0); // read RAM
117412855Sgabeblack@google.com	break;
117512855Sgabeblack@google.com      }
117612855Sgabeblack@google.com      case OP_MEM_WRITE: {
117712855Sgabeblack@google.com	if(stretch_cycles==0)
117812855Sgabeblack@google.com	  mem_wr_n.write(0); // write RAM
117912855Sgabeblack@google.com	break;
118012855Sgabeblack@google.com      }
118112855Sgabeblack@google.com      default: {
118212855Sgabeblack@google.com	// do nothing
118312855Sgabeblack@google.com	break;
118412855Sgabeblack@google.com      }
118512855Sgabeblack@google.com      }
118612855Sgabeblack@google.com    }
118712855Sgabeblack@google.com    AT_POSEDGE(clk);
118812855Sgabeblack@google.com
118912855Sgabeblack@google.com
119012855Sgabeblack@google.com    // Cycle 4 *********************************************************
119112855Sgabeblack@google.com    if (mem_idle==0) {
119212855Sgabeblack@google.com      switch (op) {
119312855Sgabeblack@google.com      case OP_MEM_READ: {
119412855Sgabeblack@google.com	if(stretch_cycles>0) {
119512855Sgabeblack@google.com	  mem_idle=stretch_cycles+1;
119612855Sgabeblack@google.com	  mem_rd_n.write(0); // read RAM
119712855Sgabeblack@google.com	}
119812855Sgabeblack@google.com	break;
119912855Sgabeblack@google.com      }
120012855Sgabeblack@google.com      case OP_MEM_WRITE: {
120112855Sgabeblack@google.com	if(stretch_cycles>0) {
120212855Sgabeblack@google.com	  mem_idle=stretch_cycles+1;
120312855Sgabeblack@google.com	  mem_wr_n.write(0); // write RAM
120412855Sgabeblack@google.com	}
120512855Sgabeblack@google.com	break;
120612855Sgabeblack@google.com      }
120712855Sgabeblack@google.com      default: {
120812855Sgabeblack@google.com	// do nothing
120912855Sgabeblack@google.com	break;
121012855Sgabeblack@google.com      }
121112855Sgabeblack@google.com      }
121212855Sgabeblack@google.com    }
121312855Sgabeblack@google.com    else if(mem_idle==1) {
121412855Sgabeblack@google.com      // read/write enable <- 1 when stretch>0
121512855Sgabeblack@google.com      switch (op) {
121612855Sgabeblack@google.com      case OP_MEM_READ: {
121712855Sgabeblack@google.com	if(stretch_cycles>0) {
121812855Sgabeblack@google.com	  // read value
121912855Sgabeblack@google.com	  *result = mem_data_in.read().to_uint();
122012855Sgabeblack@google.com	  // reset read enable
122112855Sgabeblack@google.com	  mem_rd_n.write(1); // read RAM
122212855Sgabeblack@google.com	}
122312855Sgabeblack@google.com	break;
122412855Sgabeblack@google.com      }
122512855Sgabeblack@google.com      case OP_MEM_WRITE: {
122612855Sgabeblack@google.com	if(stretch_cycles>0) {
122712855Sgabeblack@google.com	  // reset write enable
122812855Sgabeblack@google.com	  mem_wr_n.write(1); // write RAM
122912855Sgabeblack@google.com	}
123012855Sgabeblack@google.com	break;
123112855Sgabeblack@google.com      }
123212855Sgabeblack@google.com      default: {
123312855Sgabeblack@google.com	break;
123412855Sgabeblack@google.com      }
123512855Sgabeblack@google.com      }
123612855Sgabeblack@google.com    }
123712855Sgabeblack@google.com    AT_POSEDGE(clk);
123812855Sgabeblack@google.com
123912855Sgabeblack@google.com
124012855Sgabeblack@google.com    // Cycle 1 (1st part) **********************************************
124112855Sgabeblack@google.com    if(mem_idle>0)
124212855Sgabeblack@google.com      mem_idle--;
124312855Sgabeblack@google.com
124412855Sgabeblack@google.com    if(mem_idle==0){
124512855Sgabeblack@google.com      switch(op) {
124612855Sgabeblack@google.com      case OP_MEM_READ:
124712855Sgabeblack@google.com	if(stretch_cycles==0) {
124812855Sgabeblack@google.com	  mem_rd_n.write(1);
124912855Sgabeblack@google.com	  *result = mem_data_in.read().to_uint();
125012855Sgabeblack@google.com	}
125112855Sgabeblack@google.com	break;
125212855Sgabeblack@google.com      case OP_MEM_WRITE:
125312855Sgabeblack@google.com	if(stretch_cycles==0)
125412855Sgabeblack@google.com	  mem_wr_n.write(1);
125512855Sgabeblack@google.com	break;
125612855Sgabeblack@google.com      default:
125712855Sgabeblack@google.com	break;
125812855Sgabeblack@google.com      }
125912855Sgabeblack@google.com    }
126012855Sgabeblack@google.com  } while(mem_idle>0);
126112855Sgabeblack@google.com
126212855Sgabeblack@google.com  sc_assert(cycles==(stretch_cycles+1));
126312855Sgabeblack@google.com  cycle_count += cycles;
126412855Sgabeblack@google.com  cycles2execute-=cycles;
126512855Sgabeblack@google.com  return;
126612855Sgabeblack@google.com}
126712855Sgabeblack@google.com
126812855Sgabeblack@google.com
126912855Sgabeblack@google.com
127012855Sgabeblack@google.com
127112855Sgabeblack@google.com//------------------------------------------------------------------------
127212855Sgabeblack@google.com// int cycle_model::fetch_instr(int ad)
127312855Sgabeblack@google.com//
127412855Sgabeblack@google.com//    fetches data (1byte) from instruction memory
127512855Sgabeblack@google.com//
127612855Sgabeblack@google.com//------------------------------------------------------------------------
127712855Sgabeblack@google.comint cycle_model::fetch_instr(int ad) {
127812855Sgabeblack@google.com
127912855Sgabeblack@google.com  sc_assert((ad<MEM_SIZE)&&(ad>=0));
128012855Sgabeblack@google.com
128112855Sgabeblack@google.com  int temp;
128212855Sgabeblack@google.com  exec_bus_cycle(OP_IDLE, 0,0, &temp);
128312855Sgabeblack@google.com
128412855Sgabeblack@google.com  int opcode = instr_mem[ad];
128512855Sgabeblack@google.com#ifdef DEBUG
128612855Sgabeblack@google.com  printf("Fetch instruction @0x%x (= 0x%x)\n",ad,opcode);
128712855Sgabeblack@google.com#endif
128812855Sgabeblack@google.com  return opcode;
128912855Sgabeblack@google.com}
129012855Sgabeblack@google.com
129112855Sgabeblack@google.com//------------------------------------------------------------------------
129212855Sgabeblack@google.com// int cycle_model::fetch_data(int ad)
129312855Sgabeblack@google.com//
129412855Sgabeblack@google.com//   fetches data from memory which can be internal to the block or
129512855Sgabeblack@google.com//   external (case of an hardware peripheral)
129612855Sgabeblack@google.com//
129712855Sgabeblack@google.com//------------------------------------------------------------------------
129812855Sgabeblack@google.comint cycle_model::fetch_data(int addr) {
129912855Sgabeblack@google.com
130012855Sgabeblack@google.com  int data = 0, result;
130112855Sgabeblack@google.com
130212855Sgabeblack@google.com  bool is_internal = request_address(addr);
130312855Sgabeblack@google.com  if(is_internal) {
130412855Sgabeblack@google.com    // is internal
130512855Sgabeblack@google.com    if((cycles2execute>0)||ALL_CYCLES) {
130612855Sgabeblack@google.com      // Wait
130712855Sgabeblack@google.com      for(int i=0; i<stretch_cycles+1; i++) {
130812855Sgabeblack@google.com	exec_bus_cycle(OP_IDLE,addr,data,&result);
130912855Sgabeblack@google.com      }
131012855Sgabeblack@google.com    }
131112855Sgabeblack@google.com    result = ext_mem[addr];
131212855Sgabeblack@google.com  } else {
131312855Sgabeblack@google.com    // is external
131412855Sgabeblack@google.com    exec_bus_cycle(OP_MEM_READ,addr,data,&result);
131512855Sgabeblack@google.com  }
131612855Sgabeblack@google.com
131712855Sgabeblack@google.com  return result;
131812855Sgabeblack@google.com}
131912855Sgabeblack@google.com
132012855Sgabeblack@google.com
132112855Sgabeblack@google.com
132212855Sgabeblack@google.com//------------------------------------------------------------------------
132312855Sgabeblack@google.com// int cycle_model::write_data(int addr, int data)
132412855Sgabeblack@google.com//
132512855Sgabeblack@google.com//    writes data on data memory which can be internal to the block or
132612855Sgabeblack@google.com//    external (case of an hardware peripheral)
132712855Sgabeblack@google.com//
132812855Sgabeblack@google.com//------------------------------------------------------------------------
132912855Sgabeblack@google.comint cycle_model::write_data(int addr, int data) {
133012855Sgabeblack@google.com
133112855Sgabeblack@google.com  int result = 0;
133212855Sgabeblack@google.com
133312855Sgabeblack@google.com  bool is_internal = request_address(addr);
133412855Sgabeblack@google.com
133512855Sgabeblack@google.com  if(is_internal) {
133612855Sgabeblack@google.com    // is internal
133712855Sgabeblack@google.com    if((cycles2execute>0)||ALL_CYCLES) {
133812855Sgabeblack@google.com      for(int i=0; i<stretch_cycles+1; i++) {
133912855Sgabeblack@google.com	exec_bus_cycle(OP_IDLE,addr,data,&result);
134012855Sgabeblack@google.com      }
134112855Sgabeblack@google.com    }
134212855Sgabeblack@google.com    ext_mem[addr]=data;
134312855Sgabeblack@google.com  } else {
134412855Sgabeblack@google.com    // is external
134512855Sgabeblack@google.com    exec_bus_cycle(OP_MEM_WRITE,addr,data,&result);
134612855Sgabeblack@google.com  }
134712855Sgabeblack@google.com
134812855Sgabeblack@google.com  return result;
134912855Sgabeblack@google.com}
135012855Sgabeblack@google.com
135112855Sgabeblack@google.com
135212855Sgabeblack@google.com//--------------------------------------------------------------------
135312855Sgabeblack@google.com// int cycle_model::fetch_operand(operand* op)
135412855Sgabeblack@google.com//
135512855Sgabeblack@google.com//   returns the value of the operand
135612855Sgabeblack@google.com//
135712855Sgabeblack@google.com//--------------------------------------------------------------------
135812855Sgabeblack@google.comint cycle_model::fetch_operand(operand* op) {
135912855Sgabeblack@google.com  switch(op->type) {
136012855Sgabeblack@google.com  case o_acc: {
136112855Sgabeblack@google.com    return A;
136212855Sgabeblack@google.com    break;
136312855Sgabeblack@google.com  }
136412855Sgabeblack@google.com  case o_reg: {
136512855Sgabeblack@google.com    sc_assert((op->val<8)&&(op->val>=0));
136612855Sgabeblack@google.com#ifdef DEBUG
136712855Sgabeblack@google.com    printf("read R%d=%d\n",op->val,R[op->val]);
136812855Sgabeblack@google.com#endif
136912855Sgabeblack@google.com    return R[op->val];
137012855Sgabeblack@google.com    break;
137112855Sgabeblack@google.com  }
137212855Sgabeblack@google.com  case o_dir: {
137312855Sgabeblack@google.com    // fetch address
137412855Sgabeblack@google.com    my_stack->address += 1;
137512855Sgabeblack@google.com    int temp = fetch_instr(my_stack->address);
137612855Sgabeblack@google.com    sc_assert((op->val<INT_SIZE)&&(op->val>=0));
137712855Sgabeblack@google.com    return int_mem[temp];
137812855Sgabeblack@google.com    break;
137912855Sgabeblack@google.com  }
138012855Sgabeblack@google.com  case o_ind: {
138112855Sgabeblack@google.com    sc_assert((op->val==0)||(op->val==1));
138212855Sgabeblack@google.com    sc_assert((R[op->val]<INT_SIZE)&&(R[op->val]>=0));
138312855Sgabeblack@google.com    return int_mem[R[op->val]];
138412855Sgabeblack@google.com    break;
138512855Sgabeblack@google.com  }
138612855Sgabeblack@google.com  case o_ext: {
138712855Sgabeblack@google.com    sc_assert((op->val==1)||(op->val==0));
138812855Sgabeblack@google.com    int addr = R[op->val];
138912855Sgabeblack@google.com    sc_assert((addr<MEM_SIZE)&&(addr>=0));
139012855Sgabeblack@google.com
139112855Sgabeblack@google.com    int result = fetch_data(addr);
139212855Sgabeblack@google.com
139312855Sgabeblack@google.com    return result;
139412855Sgabeblack@google.com    break;
139512855Sgabeblack@google.com  }
139612855Sgabeblack@google.com  case o_cst: {
139712855Sgabeblack@google.com    // fetch next byte
139812855Sgabeblack@google.com    my_stack->address += 1;
139912855Sgabeblack@google.com    int temp = fetch_instr(my_stack->address);
140012855Sgabeblack@google.com    return temp;
140112855Sgabeblack@google.com    break;
140212855Sgabeblack@google.com  }
140312855Sgabeblack@google.com  case o_lcst: {
140412855Sgabeblack@google.com    // fetch next 2 bytes
140512855Sgabeblack@google.com
140612855Sgabeblack@google.com    my_stack->address += 1;
140712855Sgabeblack@google.com    int temp = fetch_instr(my_stack->address);
140812855Sgabeblack@google.com
140912855Sgabeblack@google.com    my_stack->address += 1;
141012855Sgabeblack@google.com    sc_assert(my_stack->address<=MEM_SIZE);
141112855Sgabeblack@google.com    temp = (temp<<8) +  fetch_instr(my_stack->address);
141212855Sgabeblack@google.com
141312855Sgabeblack@google.com    return temp;
141412855Sgabeblack@google.com    break;
141512855Sgabeblack@google.com  }
141612855Sgabeblack@google.com  case o_add: {
141712855Sgabeblack@google.com    // fetch next byte
141812855Sgabeblack@google.com    my_stack->address += 1;
141912855Sgabeblack@google.com    int temp = ((op->val)<<8) + fetch_instr(my_stack->address);
142012855Sgabeblack@google.com    return temp;
142112855Sgabeblack@google.com    break;
142212855Sgabeblack@google.com  }
142312855Sgabeblack@google.com  case o_ladd: {
142412855Sgabeblack@google.com    // fetch next 2 bytes
142512855Sgabeblack@google.com    my_stack->address += 1;
142612855Sgabeblack@google.com    int temp = fetch_instr(my_stack->address);
142712855Sgabeblack@google.com
142812855Sgabeblack@google.com    my_stack->address += 1;
142912855Sgabeblack@google.com    temp = (temp<<8) + fetch_instr(my_stack->address);
143012855Sgabeblack@google.com    return temp;
143112855Sgabeblack@google.com    break;
143212855Sgabeblack@google.com  }
143312855Sgabeblack@google.com  case o_rel: {
143412855Sgabeblack@google.com    // fetch next byte
143512855Sgabeblack@google.com    my_stack->address += 1;
143612855Sgabeblack@google.com    int temp = fetch_instr(my_stack->address);
143712855Sgabeblack@google.com    if(temp<0x80)
143812855Sgabeblack@google.com      return temp;
143912855Sgabeblack@google.com    else
144012855Sgabeblack@google.com      return -(0x100-temp);
144112855Sgabeblack@google.com    break;
144212855Sgabeblack@google.com  }
144312855Sgabeblack@google.com  default: {
144412855Sgabeblack@google.com    return -1;
144512855Sgabeblack@google.com    break;
144612855Sgabeblack@google.com  }
144712855Sgabeblack@google.com  }
144812855Sgabeblack@google.com  return -1;
144912855Sgabeblack@google.com}
145012855Sgabeblack@google.com
145112855Sgabeblack@google.com//--------------------------------------------------------------------
145212855Sgabeblack@google.com// int write_back(operand *op, int value)
145312855Sgabeblack@google.com//
145412855Sgabeblack@google.com//    write the value into the operand
145512855Sgabeblack@google.com//
145612855Sgabeblack@google.com//--------------------------------------------------------------------
145712855Sgabeblack@google.comint cycle_model::write_back(operand* op, int v) {
145812855Sgabeblack@google.com  switch(op->type) {
145912855Sgabeblack@google.com  case o_acc: {
146012855Sgabeblack@google.com    A = v;
146112855Sgabeblack@google.com    return A;
146212855Sgabeblack@google.com    break;
146312855Sgabeblack@google.com  }
146412855Sgabeblack@google.com  case o_reg: {
146512855Sgabeblack@google.com    sc_assert((op->val<8)&&(op->val>=0));
146612855Sgabeblack@google.com    R[op->val] = v;
146712855Sgabeblack@google.com#ifdef DEBUG
146812855Sgabeblack@google.com    printf("write R%d <- %d\n",op->val,R[op->val]);
146912855Sgabeblack@google.com#endif
147012855Sgabeblack@google.com    return R[op->val];
147112855Sgabeblack@google.com    break;
147212855Sgabeblack@google.com  }
147312855Sgabeblack@google.com  case o_dir: {
147412855Sgabeblack@google.com    // write address
147512855Sgabeblack@google.com    my_stack->address += 1;
147612855Sgabeblack@google.com    int temp = fetch_instr(my_stack->address);
147712855Sgabeblack@google.com    sc_assert((temp<INT_SIZE)&&(temp>=0));
147812855Sgabeblack@google.com    int_mem[temp] = v;
147912855Sgabeblack@google.com    return int_mem[temp];
148012855Sgabeblack@google.com    break;
148112855Sgabeblack@google.com  }
148212855Sgabeblack@google.com  case o_ind: {
148312855Sgabeblack@google.com    sc_assert((op->val==0)||(op->val==1));
148412855Sgabeblack@google.com    sc_assert((R[op->val]<INT_SIZE)&&(R[op->val]>=0));
148512855Sgabeblack@google.com    int_mem[R[op->val]] = v;
148612855Sgabeblack@google.com    return int_mem[R[op->val]];
148712855Sgabeblack@google.com    break;
148812855Sgabeblack@google.com  }
148912855Sgabeblack@google.com  case o_ext: {
149012855Sgabeblack@google.com    sc_assert((op->val==1)||(op->val==0));
149112855Sgabeblack@google.com    int addr = R[op->val];
149212855Sgabeblack@google.com    sc_assert((addr<MEM_SIZE)&&(addr>=0));
149312855Sgabeblack@google.com    int data, result;
149412855Sgabeblack@google.com    data = v;
149512855Sgabeblack@google.com    result = write_data(addr,data);
149612855Sgabeblack@google.com    return result;
149712855Sgabeblack@google.com    break;
149812855Sgabeblack@google.com  }
149912855Sgabeblack@google.com  default: {
150012855Sgabeblack@google.com    return -1;
150112855Sgabeblack@google.com    break;
150212855Sgabeblack@google.com  }
150312855Sgabeblack@google.com  }
150412855Sgabeblack@google.com  return -1;
150512855Sgabeblack@google.com}
150612855Sgabeblack@google.com
150712855Sgabeblack@google.com
150812855Sgabeblack@google.com
150912855Sgabeblack@google.com//--------------------------------------------------------------------
151012855Sgabeblack@google.com// void execute(instr *i)
151112855Sgabeblack@google.com//
151212855Sgabeblack@google.com//   execute consists of the following tasks:
151312855Sgabeblack@google.com//        - fetch the operands
151412855Sgabeblack@google.com//        - execute the operation in the intruction
151512855Sgabeblack@google.com//        - write the data back in the destination
151612855Sgabeblack@google.com//        - compute the next address for (jmp, call, return...)
151712855Sgabeblack@google.com//
151812855Sgabeblack@google.com//--------------------------------------------------------------------
151912855Sgabeblack@google.comvoid cycle_model::execute(instr *i) {
152012855Sgabeblack@google.com  int in1, in2, out = 0;
152112855Sgabeblack@google.com
152212855Sgabeblack@google.com  // fetch operands ---------------------------------------------------
152312855Sgabeblack@google.com  if(i->n_src>=1)
152412855Sgabeblack@google.com    in1 = fetch_operand(&(i->src1));
152512855Sgabeblack@google.com
152612855Sgabeblack@google.com  if(i->n_src>=2)
152712855Sgabeblack@google.com    in2 = fetch_operand(&(i->src2));
152812855Sgabeblack@google.com
152912855Sgabeblack@google.com#ifdef DEBUG
153012855Sgabeblack@google.com  printf("execute %d, with in1=%d and in2=%d\n",i->type,in1, in2);
153112855Sgabeblack@google.com#endif
153212855Sgabeblack@google.com
153312855Sgabeblack@google.com  // execute ----------------------------------------------------------
153412855Sgabeblack@google.com  switch(i->type) {
153512855Sgabeblack@google.com  case i_add: {
153612855Sgabeblack@google.com    out = in1 + in2;
153712855Sgabeblack@google.com    break;
153812855Sgabeblack@google.com  }
153912855Sgabeblack@google.com  case i_sub: {
154012855Sgabeblack@google.com    out = in1 - in2;
154112855Sgabeblack@google.com    break;
154212855Sgabeblack@google.com  }
154312855Sgabeblack@google.com  case i_inc: {
154412855Sgabeblack@google.com    out = in1+1;
154512855Sgabeblack@google.com    break;
154612855Sgabeblack@google.com  }
154712855Sgabeblack@google.com  case i_dec: {
154812855Sgabeblack@google.com    out = in1-1;
154912855Sgabeblack@google.com    break;
155012855Sgabeblack@google.com  }
155112855Sgabeblack@google.com  case i_mul: {
155212855Sgabeblack@google.com    out = in1 * in2;
155312855Sgabeblack@google.com    break;
155412855Sgabeblack@google.com  }
155512855Sgabeblack@google.com  case i_div: {
155612855Sgabeblack@google.com    out = in1/in2;
155712855Sgabeblack@google.com    break;
155812855Sgabeblack@google.com  }
155912855Sgabeblack@google.com  // logic operations
156012855Sgabeblack@google.com  case i_and: {
156112855Sgabeblack@google.com    out = in1 & in2;
156212855Sgabeblack@google.com    break;
156312855Sgabeblack@google.com  }
156412855Sgabeblack@google.com  case i_or: {
156512855Sgabeblack@google.com    out = in1 | in2;
156612855Sgabeblack@google.com    break;
156712855Sgabeblack@google.com  }
156812855Sgabeblack@google.com  case i_xor: {
156912855Sgabeblack@google.com    out = in1 ^ in2;
157012855Sgabeblack@google.com    break;
157112855Sgabeblack@google.com  }
157212855Sgabeblack@google.com  case i_rl: {
157312855Sgabeblack@google.com    out = in1<<1;
157412855Sgabeblack@google.com    break;
157512855Sgabeblack@google.com  }
157612855Sgabeblack@google.com  case i_rr: {
157712855Sgabeblack@google.com    out = in2>>1;
157812855Sgabeblack@google.com    break;
157912855Sgabeblack@google.com  }
158012855Sgabeblack@google.com  // data transfer
158112855Sgabeblack@google.com  case i_mov: {
158212855Sgabeblack@google.com    out = in1;
158312855Sgabeblack@google.com    break;
158412855Sgabeblack@google.com  }
158512855Sgabeblack@google.com  // branching (out==0 -> don't branch)
158612855Sgabeblack@google.com  case i_call:
158712855Sgabeblack@google.com  case i_ret:
158812855Sgabeblack@google.com  case i_jmp:
158912855Sgabeblack@google.com  case i_sjmp: {
159012855Sgabeblack@google.com    out = 1;
159112855Sgabeblack@google.com    break;
159212855Sgabeblack@google.com  }
159312855Sgabeblack@google.com  case i_jz: {
159412855Sgabeblack@google.com    out = (A==0);
159512855Sgabeblack@google.com    break;
159612855Sgabeblack@google.com  }
159712855Sgabeblack@google.com  case i_jnz: {
159812855Sgabeblack@google.com    out = (A!=0);
159912855Sgabeblack@google.com    break;
160012855Sgabeblack@google.com  }
160112855Sgabeblack@google.com  case i_cjne: {
160212855Sgabeblack@google.com    out = (in1!=in2);
160312855Sgabeblack@google.com    break;
160412855Sgabeblack@google.com  }
160512855Sgabeblack@google.com  case i_djnz: {
160612855Sgabeblack@google.com    out=in1-1; // decrement reg/direct and jump if != 0
160712855Sgabeblack@google.com    break;
160812855Sgabeblack@google.com  }
160912855Sgabeblack@google.com  default: {
161012855Sgabeblack@google.com    break;
161112855Sgabeblack@google.com  }
161212855Sgabeblack@google.com  }
161312855Sgabeblack@google.com
161412855Sgabeblack@google.com
161512855Sgabeblack@google.com  // write back --------------------------------------------------------
161612855Sgabeblack@google.com  write_back(&(i->dst),out);
161712855Sgabeblack@google.com
161812855Sgabeblack@google.com  // compute next address ----------------------------------------------
161912855Sgabeblack@google.com  switch(i->type) {
162012855Sgabeblack@google.com  case i_call: {
162112855Sgabeblack@google.com    stack_el *new_stack_el= (stack_el *) malloc(sizeof(stack_el));
162212855Sgabeblack@google.com    new_stack_el->up = my_stack;
162312855Sgabeblack@google.com    new_stack_el->address = in1;
162412855Sgabeblack@google.com    my_stack = new_stack_el;
162512855Sgabeblack@google.com
162612855Sgabeblack@google.com    /* wait additional cycles */
162712855Sgabeblack@google.com    int result;
162812855Sgabeblack@google.com    exec_bus_cycle(OP_IDLE,0,0,&result);
162912855Sgabeblack@google.com
163012855Sgabeblack@google.com    break;
163112855Sgabeblack@google.com  }
163212855Sgabeblack@google.com  case i_ret: {
163312855Sgabeblack@google.com    stack_el *new_stack_el = my_stack->up;
163412855Sgabeblack@google.com    free(my_stack);
163512855Sgabeblack@google.com    my_stack = new_stack_el;
163612855Sgabeblack@google.com    if(my_stack!=NULL)
163712855Sgabeblack@google.com      my_stack->address += 1; // increment address after jump
163812855Sgabeblack@google.com
163912855Sgabeblack@google.com    /* wait additional cycles */
164012855Sgabeblack@google.com    int result;
164112855Sgabeblack@google.com    exec_bus_cycle(OP_IDLE,0,0,&result);
164212855Sgabeblack@google.com    exec_bus_cycle(OP_IDLE,0,0,&result);
164312855Sgabeblack@google.com    exec_bus_cycle(OP_IDLE,0,0,&result);
164412855Sgabeblack@google.com    break;
164512855Sgabeblack@google.com  }
164612855Sgabeblack@google.com  case i_jmp: {
164712855Sgabeblack@google.com    my_stack->address = in1;
164812855Sgabeblack@google.com
164912855Sgabeblack@google.com    /* wait additional cycles */
165012855Sgabeblack@google.com    int result;
165112855Sgabeblack@google.com    exec_bus_cycle(OP_IDLE,0,0,&result);
165212855Sgabeblack@google.com
165312855Sgabeblack@google.com    break;
165412855Sgabeblack@google.com  }
165512855Sgabeblack@google.com  case i_sjmp:
165612855Sgabeblack@google.com  case i_jz:
165712855Sgabeblack@google.com  case i_jnz: {
165812855Sgabeblack@google.com    if(out!=0)
165912855Sgabeblack@google.com      my_stack->address += in1+1;
166012855Sgabeblack@google.com    else
166112855Sgabeblack@google.com      my_stack->address += 1;
166212855Sgabeblack@google.com
166312855Sgabeblack@google.com    /* wait additional cycles */
166412855Sgabeblack@google.com    int result;
166512855Sgabeblack@google.com    exec_bus_cycle(OP_IDLE,0,0,&result);
166612855Sgabeblack@google.com
166712855Sgabeblack@google.com    break;
166812855Sgabeblack@google.com  }
166912855Sgabeblack@google.com  case i_cjne: {
167012855Sgabeblack@google.com    int in3 = fetch_operand(&i->dst);
167112855Sgabeblack@google.com    if(out!=0)
167212855Sgabeblack@google.com      my_stack->address += in3+1;
167312855Sgabeblack@google.com    else
167412855Sgabeblack@google.com      my_stack->address += 1;
167512855Sgabeblack@google.com
167612855Sgabeblack@google.com    /* wait additional cycles */
167712855Sgabeblack@google.com    int result;
167812855Sgabeblack@google.com    exec_bus_cycle(OP_IDLE,0,0,&result);
167912855Sgabeblack@google.com
168012855Sgabeblack@google.com    break;
168112855Sgabeblack@google.com  }
168212855Sgabeblack@google.com  case i_djnz: {
168312855Sgabeblack@google.com    if(out!=0)
168412855Sgabeblack@google.com      my_stack->address += in2+1;
168512855Sgabeblack@google.com    else
168612855Sgabeblack@google.com      my_stack->address += 1;
168712855Sgabeblack@google.com
168812855Sgabeblack@google.com    /* wait additional cycles */
168912855Sgabeblack@google.com    int result;
169012855Sgabeblack@google.com    exec_bus_cycle(OP_IDLE,0,0,&result);
169112855Sgabeblack@google.com
169212855Sgabeblack@google.com    break;
169312855Sgabeblack@google.com  }
169412855Sgabeblack@google.com  default: {
169512855Sgabeblack@google.com     my_stack->address += 1;
169612855Sgabeblack@google.com     break;
169712855Sgabeblack@google.com  }
169812855Sgabeblack@google.com  }
169912855Sgabeblack@google.com}
170012855Sgabeblack@google.com
170112855Sgabeblack@google.com
170212855Sgabeblack@google.com
170312855Sgabeblack@google.com//---------------------------------------------------------------------
170412855Sgabeblack@google.com// cycle_model::init()
170512855Sgabeblack@google.com//
170612855Sgabeblack@google.com//   initialize the stack
170712855Sgabeblack@google.com//
170812855Sgabeblack@google.com//---------------------------------------------------------------------
170912855Sgabeblack@google.comvoid cycle_model::init() {
171012855Sgabeblack@google.com
171112855Sgabeblack@google.com  cycles2execute = 0;
171212855Sgabeblack@google.com  cycle_count = 0;
171312855Sgabeblack@google.com  stretch_cycles = 0;
171412855Sgabeblack@google.com
171512855Sgabeblack@google.com  // initialize stack
171612855Sgabeblack@google.com  my_stack = (stack_el *) malloc(sizeof(stack_el));
171712855Sgabeblack@google.com  my_stack->up = NULL;
171812855Sgabeblack@google.com  my_stack->address = 0;
171912855Sgabeblack@google.com}
172012855Sgabeblack@google.com
172112855Sgabeblack@google.com
172212855Sgabeblack@google.com
172312855Sgabeblack@google.com//------------------------------------------------------------------------
172412855Sgabeblack@google.com// void cycle_mode::entry()
172512855Sgabeblack@google.com//
172612855Sgabeblack@google.com// main loop: fetch instruction
172712855Sgabeblack@google.com//            decode opcode
172812855Sgabeblack@google.com//            execute instruction
172912855Sgabeblack@google.com//
173012855Sgabeblack@google.com//------------------------------------------------------------------------
173112855Sgabeblack@google.comvoid cycle_model::entry() {
173212855Sgabeblack@google.com
173312855Sgabeblack@google.com  wait();
173412855Sgabeblack@google.com
173512855Sgabeblack@google.com  mem_ale.write(0);
173612855Sgabeblack@google.com  mem_wr_n.write(1);
173712855Sgabeblack@google.com  mem_pswr_n.write(1);
173812855Sgabeblack@google.com  mem_rd_n.write(1);
173912855Sgabeblack@google.com  mem_psrd_n.write(1);
174012855Sgabeblack@google.com  p0_mem_reg_n.write(0);
174112855Sgabeblack@google.com  p0_addr_data_n.write(0);
174212855Sgabeblack@google.com  wait();
174312855Sgabeblack@google.com
174412855Sgabeblack@google.com  while(true) {
174512855Sgabeblack@google.com    instr the_instr;
174612855Sgabeblack@google.com    // fetch instruction
174712855Sgabeblack@google.com    if(my_stack==NULL) {
174812855Sgabeblack@google.com      // printf("cycles count = %d\n",cycle_count);
174912855Sgabeblack@google.com      sc_stop();
175012855Sgabeblack@google.com      wait();
175112855Sgabeblack@google.com    } else {
175212855Sgabeblack@google.com      int opcode = fetch_instr(my_stack->address);
175312855Sgabeblack@google.com
175412855Sgabeblack@google.com      // decode instruction
175512855Sgabeblack@google.com      decode(opcode, &the_instr);
175612855Sgabeblack@google.com
175712855Sgabeblack@google.com      // execute
175812855Sgabeblack@google.com      execute(&the_instr);
175912855Sgabeblack@google.com    }
176012855Sgabeblack@google.com  }
176112855Sgabeblack@google.com}
1762