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