Line 1... |
Line 1... |
/* parce.c -- Architecture independent load and parsing of assembly
|
/* parce.c -- Architecture independent load
|
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
|
Copyright (C) 1999 Damjan Lampret, lampret@opencores.org
|
|
|
This file is part of OpenRISC 1000 Architectural Simulator.
|
This file is part of OpenRISC 1000 Architectural Simulator.
|
|
|
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
Line 20... |
Line 20... |
#include <stdio.h>
|
#include <stdio.h>
|
#include <ctype.h>
|
#include <ctype.h>
|
#include <string.h>
|
#include <string.h>
|
#include <stdlib.h>
|
#include <stdlib.h>
|
|
|
#include "parse.h"
|
|
#include "abstract.h"
|
#include "abstract.h"
|
#include "arch.h"
|
#include "arch.h"
|
#include "dmmu.h"
|
#include "dmmu.h"
|
#include "coff.h"
|
#include "coff.h"
|
|
#include "debug_unit.h"
|
#include "opcode/or32.h"
|
#include "opcode/or32.h"
|
|
#include "parse.h"
|
|
|
#define MAXLINE_LEN 18000
|
#define MAXLINE_LEN 18000
|
|
|
extern char *disassembled;
|
extern char *disassembled;
|
|
|
Line 227... |
Line 228... |
|
|
/* Modified by CZ 26/05/01 */
|
/* Modified by CZ 26/05/01 */
|
/* Replaced several calls to translate(freemem) with vaddr */
|
/* Replaced several calls to translate(freemem) with vaddr */
|
/* Added new mode execution code */
|
/* Added new mode execution code */
|
/* Changed parameters so address can be passed as argument */
|
/* Changed parameters so address can be passed as argument */
|
void addprogram(char *insn, char *operands,unsigned int address,int* breakpoint)
|
void addprogram(unsigned long address, unsigned long insn, int* breakpoint)
|
{
|
{
|
int h_insn_is_word_flag=0;
|
|
char insn_first2_char[3];
|
char insn_first2_char[3];
|
int vaddr = GlobalMode ? translate(address,breakpoint) : translate(freemem,breakpoint);
|
int vaddr = GlobalMode ? translate(address,breakpoint) : translate(freemem,breakpoint);
|
|
|
debug("addprogram 1\n");
|
debug("addprogram 1\n");
|
if (!mem[vaddr].insn) {
|
|
mem[vaddr].insn = (struct insn_entry *)malloc (sizeof (struct insn_entry));
|
|
mem[vaddr].insn->insn_index = -1;
|
|
mem[vaddr].insn->op1 = null_str;
|
|
mem[vaddr].insn->op2 = null_str;
|
|
mem[vaddr].insn->op3 = null_str;
|
|
mem[vaddr].insn->op4 = null_str;
|
|
} else if(!GlobalMode) { /* Old mode */
|
|
printf("internal error: reloading the same location\n");
|
|
exit(1);
|
|
} else /* New mode */
|
|
{
|
|
if(mem[vaddr].insn->op1 != null_str) free(mem[vaddr].insn->op1);
|
|
if(mem[vaddr].insn->op2 != null_str) free(mem[vaddr].insn->op2);
|
|
if(mem[vaddr].insn->op3 != null_str) free(mem[vaddr].insn->op3);
|
|
if(mem[vaddr].insn->op4 != null_str) free(mem[vaddr].insn->op4);
|
|
mem[vaddr].insn->insn_index = -1;
|
|
mem[vaddr].insn->op1 = null_str;
|
|
mem[vaddr].insn->op2 = null_str;
|
|
mem[vaddr].insn->op3 = null_str;
|
|
mem[vaddr].insn->op4 = null_str;
|
|
}
|
|
|
|
debug("addprogram 2\n");
|
|
|
|
#ifdef OR16
|
|
|
|
printf("half:%s:\n", insn);
|
|
insn_first2_char[0]=insn[0];
|
|
insn_first2_char[1]=insn[1];
|
|
insn_first2_char[2]='\0';
|
|
debug("addprogram 3\n");
|
|
|
|
if(strcmp("h.", insn_first2_char) == 0) {
|
|
if(strcmp("h.load32u", insn) == 0 ||
|
|
strcmp("h.load16u", insn) == 0 ||
|
|
strcmp("h.load8u", insn) == 0 ||
|
|
strcmp("h.stor32", insn) == 0 ||
|
|
strcmp("h.stor16", insn) == 0 ||
|
|
strcmp("h.stor8", insn) == 0 ||
|
|
strcmp("h.jal", insn) == 0 ||
|
|
/* strcmp("h.mtsr", insn) == 0 ||
|
|
strcmp("h.mfsr", insn) == 0 || */
|
|
strcmp("h.movi16ze", insn) == 0 ||
|
|
strcmp("h.immhi16u", insn) == 0 ||
|
|
strcmp("h.addi16s", insn) == 0 ||
|
|
strcmp("h.subi16s", insn) == 0 ||
|
|
strcmp("h.xori16", insn) == 0 ||
|
|
strcmp("h.ori16", insn) == 0 ||
|
|
strcmp("h.andi16", insn) == 0
|
|
)
|
|
h_insn_is_word_flag = 2; /* h.xxx insn AND occupy 4 bytes */
|
|
else
|
|
h_insn_is_word_flag = 1; /* h.xxx insn AND occupy 2 bytes */
|
|
}
|
|
else {
|
|
h_insn_is_word_flag = 0; /* not h.xxx insn */
|
|
}
|
|
#else
|
|
debug("addprogram 4\n");
|
|
debug("addprogram 5\n");
|
|
#endif
|
|
|
|
/* MM: added instruction index */
|
|
mem[vaddr].insn->insn_index = insn_index (insn);
|
|
/* op1 */
|
|
if (*operands) {
|
|
mem[vaddr].insn->op1 = malloc(strlen(operands)+1);
|
|
strcpy(mem[vaddr].insn->op1, operands);
|
|
}
|
|
|
|
debug("addprogram 6\n");
|
|
debug("operands:%s\n", operands);
|
|
if (strstr(operands, OPERAND_DELIM)) {
|
|
debug("addprogram 6a\n");
|
|
operands = strstr(mem[vaddr].insn->op1, OPERAND_DELIM);
|
|
*operands = '\0';
|
|
operands++;
|
|
} else {
|
|
debug("addprogram 6b\n");
|
|
if(!GlobalMode)
|
|
{
|
|
#ifdef OR16
|
|
freemem += (h_insn_is_word_flag == 1) ? 2 : 4;
|
|
#else
|
|
freemem += 4;
|
|
#endif
|
|
}
|
|
return;
|
|
}
|
|
|
|
debug("addprogram 7\n");
|
|
/* op2 */
|
|
if (*operands) {
|
|
mem[vaddr].insn->op2 = malloc(strlen(operands)+1);
|
|
strcpy(mem[vaddr].insn->op2, operands);
|
|
}
|
|
if (strstr(operands, OPERAND_DELIM)) {
|
|
operands = strstr(mem[vaddr].insn->op2, OPERAND_DELIM);
|
|
*operands = '\0';
|
|
operands++;
|
|
} else {
|
|
if(!GlobalMode)
|
|
{
|
|
#ifdef OR16
|
|
freemem += (h_insn_is_word_flag == 1) ? 2 : 4;
|
|
#else
|
|
freemem += 4;
|
|
#endif
|
|
}
|
|
|
|
return;
|
*breakpoint += CheckDebugUnit(DebugStoreAddress,vaddr); /* 22/06/01 MM*/
|
}
|
*breakpoint += CheckDebugUnit(DebugStoreData,insn);
|
|
|
debug("addprogram 8\n");
|
|
/* op3 */
|
|
if (*operands) {
|
|
mem[vaddr].insn->op3 = malloc(strlen(operands)+1);
|
|
strcpy(mem[vaddr].insn->op3, operands);
|
|
}
|
|
if (strstr(operands, OPERAND_DELIM)) {
|
|
operands = strstr(mem[vaddr].insn->op3, OPERAND_DELIM);
|
|
*operands = '\0';
|
|
operands++;
|
|
} else {
|
|
if(!GlobalMode)
|
|
{
|
|
#ifdef OR16
|
|
freemem += (h_insn_is_word_flag == 1) ? 2 : 4;
|
|
#else
|
|
freemem += 4;
|
|
#endif
|
|
}
|
|
return;
|
|
}
|
|
|
|
/* op4 */
|
setsim_mem32 (vaddr, insn);
|
if (*operands) {
|
|
mem[vaddr].insn->op4 = malloc(strlen(operands)+1);
|
|
strcpy(mem[vaddr].insn->op4, operands);
|
|
}
|
|
if (strstr(operands, OPERAND_DELIM)) {
|
|
operands = strstr(mem[vaddr].insn->op4, OPERAND_DELIM);
|
|
*operands = '\0';
|
|
operands++;
|
|
}
|
|
|
|
if(!GlobalMode)
|
if(!GlobalMode)
|
{
|
freemem += insn_len (insn_decode (insn));
|
#ifdef OR16
|
|
freemem += (h_insn_is_word_flag == 1) ? 2 : 4;
|
|
#else
|
|
freemem += 4;
|
|
#endif
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/* Non-architecture dependent parsing: stripping comments, filling
|
|
abstract memory */
|
|
|
|
void parseline(char *inputline,int* breakpoint)
|
|
{
|
|
char item[MAXLINE_LEN];
|
|
char item2[MAXLINE_LEN];
|
|
int i = 0;
|
|
|
|
/* Strip comments: simply terminate line where
|
|
the first comment character appears. */
|
|
|
|
debug("PARSING: %s", inputline);
|
|
while (inputline[i] != '\0')
|
|
if (inputline[i] == COMMENT_CHAR) {
|
|
inputline[i] = '\0';
|
|
break;
|
|
} else
|
|
i++;
|
|
|
|
/* Get the first item from this line */
|
|
strtoken(inputline, item, 1); /* opcode */
|
|
strtoken(inputline, item2, 2); /* all the remaining one/two/three operands */
|
|
|
|
/* Is this item empty? Nothing to process, so return. */
|
|
if (strlen(item) == 0)
|
|
return;
|
|
|
|
/* Is this item a label? If yes, add it to the label table and return immediately. */
|
|
if (strstr(item, LABELEND_CHAR)) {
|
|
*strstr(item, LABELEND_CHAR) = '\0';
|
|
addlabel(item, translate(freemem,breakpoint),breakpoint);
|
|
return;
|
|
}
|
|
|
|
/* Is this item a .directive? If yes, check for some supported
|
|
and then return (even if unsupported found). */
|
|
if (item[0] == DIRECTIVE_CHAR) {
|
|
if (strcmp(item, ".align") == 0) {
|
|
int align = strtoul(item2, NULL, 0);
|
|
if (!(translate(freemem,breakpoint) % align))
|
|
return;
|
|
freemem &= -align;
|
|
freemem += align;
|
|
return;
|
|
} else
|
|
if (strcmp(item, ".org") == 0) {
|
|
int addr = strtoul(item2, NULL, 0);
|
|
freemem = addr;
|
|
return;
|
|
} else
|
|
if (strcmp(item, ".ascii") == 0) {
|
|
adddatastr(strstr(inputline, "\""),breakpoint);
|
|
return;
|
|
} else
|
|
if (strcmp(item, ".word") == 0) {
|
|
adddataword(item2,breakpoint);
|
|
return;
|
|
} else
|
|
if (strcmp(item, ".half") == 0) {
|
|
adddatahalf(item2,breakpoint);
|
|
return;
|
|
} else
|
|
if (strcmp(item, ".byte") == 0) {
|
|
adddatabyte(item2,breakpoint);
|
|
return;
|
|
} else
|
|
if (strcmp(item, ".space") == 0) {
|
|
adddataspace(item2);
|
|
return;
|
|
} else /* .directive but not one of the supported */
|
|
return;
|
|
}
|
|
|
|
/* This item can only be an instruction. Get all operands
|
|
and add everything to mem array but as a program. */
|
|
debug("%x: ", translate(freemem,breakpoint));
|
|
addprogram(item, item2,freemem,breakpoint);
|
|
|
|
/* Also do static, single stats. */
|
|
addsstats(item, 0, 1);
|
|
|
|
return;
|
|
|
|
}
|
}
|
|
|
/* Load big-endian COFF file. At the moment it doesn't load symbols yet. */
|
/* Load big-endian COFF file. At the moment it doesn't load symbols yet. */
|
|
|
void readfile_coff(char *filename, short sections)
|
void readfile_coff(char *filename, short sections)
|
Line 566... |
Line 331... |
perror("readfile_coff");
|
perror("readfile_coff");
|
exit(1);
|
exit(1);
|
}
|
}
|
while (sectsize > 0 && (len = fread(&inputbuf, sizeof(inputbuf), 1, inputfs))) {
|
while (sectsize > 0 && (len = fread(&inputbuf, sizeof(inputbuf), 1, inputfs))) {
|
insn = COFF_LONG_H(inputbuf);
|
insn = COFF_LONG_H(inputbuf);
|
len = disassemble_insn(insn);
|
len = insn_len (insn_decode (insn));
|
sprintf(item, "%u", insn);
|
if (len == 2)
|
adddataword(item,&breakpoint);
|
{
|
freemem -= len;
|
|
if (len == 2) {
|
|
fseek(inputfs, -2, SEEK_CUR);
|
fseek(inputfs, -2, SEEK_CUR);
|
debug("readfile_coff: %x 0x%x ", sectsize, insn >> 16);
|
debug("readfile_coff: %x 0x%x ", sectsize, insn >> 16);
|
}
|
}
|
else
|
else
|
debug("readfile_coff: %x 0x%x ", sectsize, insn);
|
debug("readfile_coff: %x 0x%x ", sectsize, insn);
|
debug("%s\n", disassembled);
|
addprogram (freemem, insn, &breakpoint);
|
strtoken(disassembled, item, 1); /* opcode */
|
|
strtoken(disassembled, item2, 2); /* all the remaining one/two/three operands */
|
|
addprogram(item, item2,freemem,&breakpoint);
|
|
sectsize -= len;
|
sectsize -= len;
|
}
|
}
|
}
|
}
|
if (firstthree < 3) {
|
if (firstthree < 3) {
|
printf("One or more missing sections. At least");
|
printf("One or more missing sections. At least");
|
Line 635... |
Line 395... |
fclose(inputfs);
|
fclose(inputfs);
|
printf("Finished loading symbols.\n");
|
printf("Finished loading symbols.\n");
|
return;
|
return;
|
}
|
}
|
|
|
/* Load file and hand over every line to parse routine. */
|
|
|
|
void readfile_assembly(char *filename)
|
|
{
|
|
FILE *inputfs;
|
|
char inputbuf[MAXLINE_LEN];
|
|
char *status;
|
|
int breakpoint = 0;
|
|
|
|
if (!(inputfs = fopen(filename, "r"))) {
|
|
perror("readfile_assembly");
|
|
exit(1);
|
|
}
|
|
|
|
while ((status = fgets(inputbuf, sizeof(inputbuf), inputfs))) {
|
|
if (nonempty(inputbuf))
|
|
parseline(inputbuf,&breakpoint);
|
|
}
|
|
fclose(inputfs);
|
|
|
|
return;
|
|
}
|
|
|
|
/* Identify file type and call appropriate readfile_X routine. It only
|
/* Identify file type and call appropriate readfile_X routine. It only
|
handles orX-coff-big executables at the moment. */
|
handles orX-coff-big executables at the moment. */
|
|
|
void identifyfile(char *filename)
|
void identifyfile(char *filename)
|
{
|
{
|
Line 697... |
Line 434... |
readfile_coff(filename, COFF_SHORT_H(coffhdr.f_nscns));
|
readfile_coff(filename, COFF_SHORT_H(coffhdr.f_nscns));
|
readsyms_coff(filename, COFF_LONG_H(coffhdr.f_symptr), COFF_LONG_H(coffhdr.f_nsyms));
|
readsyms_coff(filename, COFF_LONG_H(coffhdr.f_symptr), COFF_LONG_H(coffhdr.f_nsyms));
|
return;
|
return;
|
}
|
}
|
else {
|
else {
|
printf("Not COFF, trying to load as assembly.\n");
|
printf("Not COFF, quiting.\n");
|
fclose(inputfs);
|
fclose(inputfs);
|
readfile_assembly(filename);
|
exit (1);
|
return;
|
|
}
|
}
|
}
|
}
|
else {
|
else {
|
printf("yy %s", filename);
|
printf("yy %s", filename);
|
perror("identifyfile2");
|
perror("identifyfile2");
|