Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**************************************************************************
- *
- * Filename: Ace2.c
- *
- * Synopsis:
- *
- * Purpose:
- *
- * Author:
- * Louise Watson, Reg no: 201347438
- *
- * Group:
- * Thu 3-5
- *
- * Promise: I confirm that this submission is all my own work.
- *
- * (Signed)_____________________________________(Louise Watson)
- *
- *
- * Version: See VERSION below
- *
- *********************************************************************/
- /**************************************************************************
- *Version History
- *V1.0 Removed most of the unnecessary code provided in Duncan's Sample code in order to
- *begin Ace2. Pasted in Get Hex provided by Duncan.
- *V1.1 Added in program counter to code and changed '6' to '2' so it will shift 2 bits
- *instead of 6 bits.
- *v1.2 Used the previously defined Opcode function and used OpDigits to get the first six digit
- *opcode from the first hex number. This allowed me to use OpDigits to check if it was I, r or J
- *type instruction. Done this by creating an array of J-type instructions and using an if
- *statement. This will compare if OpDigits is equal to 0, if so, return r, compare to J, if equal
- *return j, else it will return it to be of an I type instruction.
- *v1.3 Trying to correct as many errors as possible by adding in Uint_t before my program counter
- *
- *********************************************************************/
- #define VERSION "Ace 2. Version 1.4. by Louise Watson, Last Update 23/11/2014\n"
- #define USAGE "Usage: %s <regNo>\n",argv[0]
- #include <stdio.h>
- #include <limits.h>
- #include <ctype.h>
- #include <stdlib.h>
- #include <string.h>
- /* #include "p4sample.h */
- /* ** Start of p4sample.h (if the following were moved into that .h file) ** */
- #if SHRT_MAX == 2147483647
- typedef unsigned short int uint32_t;
- #elif INT_MAX == 2147483647
- typedef unsigned int uint32_t;
- #elif LONG_MAX == 2147483647
- typedef unsigned long uint32_t ;
- #elif LLONG_MAX == 2147483647
- typedef unsigned long long uint32_t;
- #else
- #error "Cannot find 32bit integer."
- #endif
- /* On some systems an UINT32_MAX is already defined, if not... */
- #ifndef UINT32_MAX
- #define UINT32_MAX ((uint32_t)-1)
- #endif
- /* Note on the following #define suffix nomenclature:
- _L = Least significant bit position of the field
- _M = Most significant bit position of the field
- _SZ = Size of the field
- */
- /* Fields in the lower 16 bits of the MIPS instruction format: */
- /* I-type field in lower 16 bits */
- #define I_L 0
- #define I_M 15
- #define I_SZ ((I_M-I_L)+1)
- /* R-type fields in lower 16 bits */
- /* Function */
- #define FN_L 0
- #define FN_M 5
- #define FN_SZ ((FN_M-FN_L)+1)
- /* Shamt - shift amount */
- #define SH_L 6
- #define SH_M 10
- #define SH_SZ ((SH_M-SH_L)+1)
- /* Register RD */
- #define RD_L 11
- #define RD_M 15
- /* Fields in the upper 16 bits of the MIPS instruction format: */
- /* I-type and R-type share a commmon set of fields in the upper 16 bits */
- /* Register RT */
- #define RT_L 16
- #define RT_M 20
- /* Register RS */
- #define RS_L 21
- #define RS_M 25
- /* Registers RD, RT and RS are all the same size */
- #define R_SZ ((RD_M-RD_L)+1)
- /* Opcode is in the top 6 bits for _all_ instructions */
- #define OP_L 26
- #define OP_M 31
- #define OP_SZ ((OP_M-OP_L)+1)
- /* The J(ump) instruction is a special case */
- /* J-type uses all the bits other than the opcode field */
- #define J_L 0
- #define J_M 25
- #define J_SZ ((J_M-J_L)+1)
- /* The IEEE 754 Single Precision FP fields */
- /* Sign Bit */
- #define FPS_L 31
- #define FPS_M 31
- #define FPS_SZ ((FPS_M-FPS_L)+1)
- /* Exponent Bits */
- #define FPE_L 23
- #define FPE_M 30
- #define FPE_SZ ((FPE_M-FPE_L)+1)
- /* Fraction Bits */
- #define FPF_L 0
- #define FPF_M 22
- #define FPF_SZ ((FPF_M-FPF_L)+1)
- /* IEEE 754 uses a Biased Exponent */
- #define IEEE754_BIAS 127
- /* INERR is an Input Error */
- #define INERR -1
- /* The following union allows the unsigned 32 bits to also be interpreted as
- a 32-bit floating point number */
- typedef union {
- uint32_t i;
- float f;
- } fp_i_t;
- /* The following structs represent the fields in the various MIPS instructions.
- The members of the struct include:
- - the 32-bit representation of the instruction in the .in member
- - the contents of the field as an integer value, e.g. 14 in .rs
- - the (pointer to the) corresponding bit string, e.g. &"01110" in .rsbits
- - the (pointer to the) name/label of the field, e.g. &"RS" in .rsname
- */
- typedef struct {
- uint32_t in;
- int op; char *opbits; char *opname;
- int rs; char *rsbits; char *rsname;
- int rt; char *rtbits; char *rtname;
- int rd; char *rdbits; char *rdname;
- int sh; char *shbits; char *shname;
- int fn; char *fnbits; char *fnname;
- } mips_rtype_t;
- typedef struct {
- uint32_t in;
- int op; char *opbits; char *opname;
- int rs; char *rsbits; char *rsname;
- int rt; char *rtbits; char *rtname;
- int immediate; char *ibits; char *iname;
- } mips_itype_t;
- typedef struct {
- uint32_t in;
- int op; char *opbits; char *opname;
- int address; char *jbits; char *jname;
- } mips_jtype_t;
- typedef struct {
- fp_i_t in;
- int s; char *sbits; char *sname;
- int e; char *ebits; char *ename;
- int f; char *fbits; char *fname;
- } ieee_754_t;
- /* The following is a macro that 'extracts' from the bits passed in the
- value of the field of size bit_sz that begins at bit position bit_l.
- */
- #define IN(bits,bit_l,bit_sz) ((bits >> bit_l) & ((1 << bit_sz) - 1))
- /* The PC value as stipulated in the specification */
- #define PC 0X10000000
- /* ** End of p4sample.h (if the above had been contained in that .h file) ** */
- /* Start of the actual code */
- /* Synopsis:
- * #include <ctype.h>
- * int isnumeric(char *s)
- *
- * Description:
- * A convenience function similar to isdigit() except that it works for
- * strings rather than single characters.
- *
- * Returns:
- * The same result as isdigit()
- */
- int isnumeric(char *s) {
- int result; /* Current isdigit() return value */
- do /* Check that each character of the...*/
- result = isdigit(*s++); /* ...string is a digit and move on...*/
- while (result && *s) ; /* ...until non-digit found or at EOS */
- return result; /* Return result of last isdigit() call */
- }
- /* Synopsis:
- * uint32_t strtouint32(const char * restrict s,int base)
- *
- * Description:
- * Converts a string into an uint32_t (32 bit unsigned) integer value.
- * A conversion function in the style of strtol(). The character string s is
- * interpreted as a numeral to the base specified by the second parameter base.
- * The string should only contain digits between 0 and 9 even though the
- * the base can be >10. This restriction is allowed since only 9 digit
- * student registration numbers are expected to be converted. If the input
- * string is not a valid numeral then the return value is UINT32_MAX.
- *
- * Returns:
- * The numeric value of the string or UINT32_MAX if string isn't numeric
- */
- uint32_t strtouint32(char *s,int base) {
- uint32_t result = 0;
- if (!isnumeric(s)) /* Basic sanity check on input string */
- return(UINT32_MAX); /* UINT32_MAX uses as error indicator */
- while (*s)
- result = (result * base) + ((*s++) - '0'); /* Convert */
- return (result);
- }
- /* Synopsis:
- * #include <stdlib.h>
- * char* bitstostr (uint32_t bits, int size, int split)
- *
- * Description:
- * Converts the first parameter into a character string that contains the
- * bit pattern equivalent of the internal representation of the integer.
- * The second parameter is the number of bits to be inserted into the string.
- * The third parameter determines the number of bits to be grouped together.
- * A value of 0 for split means that no splitting is to take place. Non-zero
- * values for split cause a space to be inserted into the string after split
- * bits have been inserted.
- *
- * Returns:
- * The return value is a pointer to the (dynamically allocated) string of bits.
- * However, if the string cannot be allocated, it returns a pointer to the
- * "Calloc Failed" error string. This is rather a kludge since calloc is not
- * expected to fail and so the user may assume it succeeds and won't bother
- * checking the return result. Better error reporting/handling is left as an
- * exercise to the reader!
- */
- char* bitstostr (uint32_t bits, int size, int split) {
- char *bitsPtr; /* Pointer to the bit string being built */
- int stringsize, /* (Maximum) Size of the string that's required */
- splitter; /* Countdown count until a splitting space insertion */
- stringsize = (split)?size+size/split:size; /* Calculate size with splits */
- splitter = split; /* Initialise countdown to a splitting space insertion */
- /* Now we know the maximum number of characters needed calloc() them. */
- if (NULL == (bitsPtr = calloc(stringsize+1,sizeof(char))))
- return("Calloc Failed"); /* Left as an exercise for future improvement */
- /* We now have our array initialised to '\0's so no need to plant an EOS */
- bitsPtr += stringsize; /* String is built in reverse so start at the end */
- /* Now perform the conversion. The (bits&1) mask is used to pick off the
- * lowest bit of the number.
- */
- for ( ; size-- ; bits >>= 1) { /* Keep shifting bits down until all done */
- *--bitsPtr = (bits&1)?'1':'0'; /* (Back)Fill string with 1s and 0s */
- if (splitter > 0) /* Do the bits get split up into groups? */
- if (0 == (--splitter)) { /* if so do we split them this time round? */
- *--bitsPtr = ' '; /* Yes, so insert a space into the string */
- splitter = split; /* ...and reset the split countdown count. */
- }
- }
- if (' ' == *bitsPtr) ++bitsPtr; /* Skip any leading space */
- return(bitsPtr);
- }
- /* The following init_? functions initialise the appropriate members of the
- data structure with the values derived from the first parameter - bits.
- The second parameter in each function is a pointer to the data structure.
- The semantics of each function should be self-explanatory ;)
- */
- void init_rtype(uint32_t bits, mips_rtype_t *rtype) {
- rtype->in = bits;
- rtype->op = IN(bits,OP_L,OP_SZ);
- rtype->opbits = bitstostr(rtype->op,OP_SZ,0);
- rtype->rs = IN(bits,RS_L,R_SZ);
- rtype->rsbits = bitstostr(rtype->rs,R_SZ,0);
- rtype->rt = IN(bits,RT_L,R_SZ);
- rtype->rtbits = bitstostr(rtype->rt,R_SZ,0);
- rtype->rd = IN(bits,RD_L,R_SZ);
- rtype->rdbits = bitstostr(rtype->rd,R_SZ,0);
- rtype->sh = IN(bits,SH_L,SH_SZ);
- rtype->shbits = bitstostr(rtype->sh,SH_SZ,0);
- rtype->fn = IN(bits,FN_L,FN_SZ);
- rtype->fnbits = bitstostr(rtype->fn,FN_SZ,0);
- return;
- }
- void init_itype (uint32_t bits,mips_itype_t *itype) {
- itype->in = bits;
- itype->op = IN(bits,OP_L,OP_SZ);
- itype->opbits = bitstostr(itype->op,OP_SZ,0);
- itype->rs = IN(bits,RS_L,R_SZ);
- itype->rsbits = bitstostr(itype->rs,R_SZ,0);
- itype->rt = IN(bits,RT_L,R_SZ);
- itype->rtbits = bitstostr(itype->rt,R_SZ,0);
- itype->immediate = IN(bits,I_L,I_SZ);
- itype->ibits = bitstostr(itype->immediate,I_SZ,0);
- return;
- }
- void init_jtype (uint32_t bits,mips_jtype_t *jtype) {
- jtype->in = bits;
- jtype->op = IN(bits,OP_L,OP_SZ);
- jtype->opbits = bitstostr(jtype->op,OP_SZ,0);
- jtype->address = IN(bits,J_L,J_SZ);
- jtype->jbits = bitstostr(jtype->address,J_SZ,0);
- return;
- }
- void init_ftype (uint32_t bits,ieee_754_t *ftype) {
- ftype->in.i = bits;
- ftype->s = IN(bits,FPS_L,FPS_SZ);
- ftype->sbits = bitstostr(ftype->s,FPS_SZ,0);
- ftype->e = IN(bits,FPE_L,FPE_SZ);
- ftype->ebits = bitstostr(ftype->e,FPE_SZ,0);
- ftype->f = IN(bits,FPF_L,FPF_SZ);
- ftype->fbits = bitstostr(ftype->f,FPF_SZ,0);
- return;
- }
- /* A wrapper function for all the data structures to be initialsed */
- void init_all_types(uint32_t bits,
- mips_rtype_t *rtype,
- mips_itype_t *itype,
- mips_jtype_t *jtype,
- ieee_754_t *ftype) {
- init_rtype(bits,rtype);
- init_itype(bits,itype);
- init_jtype(bits,jtype);
- init_ftype(bits,ftype);
- return;
- }
- /* The following print_? functions are really just wrappers round the
- printf()s. This is intended to be a help when (in no particular order):
- - reading the code
- - understanding the code
- - maintaining the code
- - adapting the code
- */
- void print_rtype (mips_rtype_t *rtype) {
- printf("R-Type fields:\t+ %6s + %5s + %5s + %5s + %5s + %6s +\n",
- rtype->opname,
- rtype->rsname,
- rtype->rtname,
- rtype->rdname,
- rtype->shname,
- rtype->fnname);
- printf("\tBits:\t| %s | %s | %s | %s | %s | %s |\n",
- rtype->opbits,
- rtype->rsbits,
- rtype->rtbits,
- rtype->rdbits,
- rtype->shbits,
- rtype->fnbits);
- printf("\tValues:\t+ %6d + %5d + %5d + %5d + %5d + %6d +\n",
- rtype->op,
- rtype->rs,
- rtype->rt,
- rtype->rd,
- rtype->sh,
- rtype->fn);
- }
- void print_itype (mips_itype_t *itype) {
- printf("I_Type fields:\t+ %6s + %5s + %5s + %16s +\n",
- itype->opname,itype->rsname,itype->rtname,itype->iname);
- printf("\tBits:\t| %s | %s | %s | %s |\n",
- itype->opbits,itype->rsbits,itype->rtbits,itype->ibits);
- printf("\tValues:\t+ %6d + %5d + %5d + %11hd(dec) +\n",
- itype->op,itype->rs,itype->rt,(short)itype->immediate);
- }
- void print_jtype (mips_jtype_t *jtype) {
- printf("J-Type fields:\t+ %6s + %26s +\n",jtype->opname,jtype->jname);
- printf("\tBits:\t| %s | %s |\n",jtype->opbits,jtype->jbits);
- printf("\tValues:\t+ %6d + %21X(hex) +\n",jtype->op,jtype->address);
- }
- void print_ieee_754 (ieee_754_t *ftype) {
- printf("FP fields:\t+ %1s + %8s + %23s +\n",
- ftype->sname,ftype->ename,ftype->fname);
- printf("\tBits:\t| %s | %s | %s |\n",ftype->sbits,ftype->ebits,ftype->fbits);
- printf("\tValues:\t+ %1d + %8d + %18d(ten) +\n",ftype->s,ftype->e,ftype->f);
- }
- void print_all_types(mips_rtype_t *rtype,
- mips_itype_t *itype,
- mips_jtype_t *jtype,
- ieee_754_t *ftype) {
- print_rtype(rtype);
- print_itype(itype);
- print_jtype(jtype);
- print_ieee_754(ftype);
- return;
- }
- /* The following print_? functions just format the instructions as they
- would appear in MIPS assembly language.
- */
- void print_i_type_mem(mips_itype_t *itype) { /* Load/Store instructions */
- printf("%s\t$%d,%hd($%d)\n",
- itype->opname,itype->rt,(short)itype->immediate,itype->rs);
- return;
- }
- void print_i_type_alu(mips_itype_t *itype) { /* I-type ALU instructions */
- printf("%s\t$%d,$%d,%hd\n",
- itype->opname,itype->rt,itype->rs,(short)itype->immediate);
- return;
- }
- void print_r_type_shift(mips_rtype_t *rtype) { /* R-type shift instructions */
- printf("%s\t$%d,$%d,%d\n",
- rtype->opname,rtype->rd,rtype->rt,rtype->sh);
- return;
- }
- void print_r_type(mips_rtype_t *rtype) { /* R-type ALU instructions */
- printf("%s\t$%d,$%d,$%d\n",
- rtype->opname,rtype->rd,rtype->rs,rtype->rt);
- return;
- }
- void print_j_type(mips_jtype_t *jtype) { /* J-type instruction(s) */
- printf("%s\t%08X(hex)\n",
- jtype->opname,((jtype->address << 2) | (PC & 0XF0000000)));
- return;
- }
- void print_ieee_754_actual(ieee_754_t *ftype) { /* IEEE 754 FP (32-bit) */
- float actualf = 1.0+((float)ftype->f/(1 << FPF_SZ));
- int actuale = ftype->e - IEEE754_BIAS;
- print_ieee_754(ftype);
- printf("\tActual:\t %c 2^(%3d) %24f\n",
- (ftype->s)?'-':'+',actuale,actualf);
- printf("\tResult:\t %c%f * 2^(%3d) -> %15G\n",
- (ftype->s)?'-':'+', /* Translate sign bit of the FP */
- actualf, /* Converted (actual) fraction of the FP */
- actuale, /* Converted (actual) exponent of the FP */
- ftype->in.f /* Interpret bits as the value of the FP */
- );
- return;
- }
- uint32_t GetHex(void) {
- #define MAXIN 4096 /* MAXIN is the maximum number of input characters */
- static char input[MAXIN]; /* declared as static so it's not on the stack */
- char last;
- uint32_t result;
- fgets(input,MAXIN,stdin); /* fgets as scanf() can't handle blank lines */
- /* First of all check if it was a blank line, i.e. just a '\n' input...*/
- if ('\n' == input[0]) return(INERR); /* ...which is invalid input too */
- /* Now sscanf() can be used to parse a hex # but we still need to detect
- extraneous input _after_ a valid hex #. has been parsed, hence the %c
- that should have '\n' assigned to it. So, if a valid hex # is parsed
- _and_ there was at least one more character - which there should be -
- then sscanf() will return 2 - the number of successfully parsed items */
- if ((sscanf(input,"%8x%c",&result,&last) < 2)) return(INERR);
- /* Now check to make sure the last character input was a '\n', if not... */
- if ('\n' != last) return(INERR); /* ...then return an input error value */
- /* If we get to this point it has to be a valid hex # so just return it. */
- return(result);
- }
- /*declaring OpDigits */
- static int OpDigits;
- /* Here I will declare array for J type instructions*/
- int main(int argc, char *argv[]) {
- uint32_t regashextouint32, regasuint32lslby2, regasdectouint32, programcounter, input;
- /* Declare & (partially) initialise vars for each type of instruction/data */
- mips_rtype_t rtypeinstruction = {0,
- 0,NULL,"Opcode",
- 0,NULL,"RS",
- 0,NULL,"RT",
- 0,NULL,"RD",
- 0,NULL,"Shamt",
- 0,NULL,"Funct"
- };
- mips_itype_t itypeinstruction = {0,
- 0,NULL,"Opcode",
- 0,NULL,"RS",
- 0,NULL,"RT",
- 0,NULL,"Immediate"
- };
- mips_jtype_t jtypeinstruction = {0,
- 0,NULL,"Opcode",
- 0,NULL,"Address"
- };
- ieee_754_t ftypenumber = {{0},
- 0,NULL,"S",
- 0,NULL,"E",
- 0,NULL,"F"
- };
- printf(VERSION);
- /* Now perform some basic sanity checks on the command line input string... */
- if ( argc != 2 || /* if there's an input string carry on & check its length */
- strlen(argv[1]) != 9 || /* if OK then convert it and check the result: */
- (UINT32_MAX==(regashextouint32=strtouint32(&argv[1][1],16))) ){ /* OK? */
- printf(USAGE); /* Failed at least one of the above checks so alert user */
- exit(1); /* ...and exit. */
- }
- /* All of the above tests passed so continue on with the rest of the code. */
- regasdectouint32 = strtouint32(&argv[1][0],10); /* Treat reg no as base 10 */
- regasuint32lslby2 = regasdectouint32 << 2; /* Calculate the LSL by 2 value */
- programcounter = regasuint32lslby2;
- printf("\t%s treated as a 32-bit number and printed as 0x%%08X notation is: 0x%08X\n", argv[1], regasdectouint32 );
- do {
- printf("Type in a hex number please: ");
- input = GetHex(); /* input is a uint32_t, this is your mips instruction code */
- printf("That hex number is %d (base 10)\n",input);
- OpDigits = IN(input, OP_L,OP_SZ);
- printf("\tInitial program counter is %08X << 2 => %08X (hex)\n", regasdectouint32, programcounter);
- /*if statement to check if i, r or j type */
- if (OpDigits ==0) { /* checks if digit is equal to opcode 000000*/
- printf("This is of type r\n"); /*Returns that digit is of type r*/
- }
- else if (OpDigits == (2|3)){ /*checks to see if digit is equal to opcode 2 or 3 as that is the opcode numbers for the J types*/
- printd("This is a J type"); /*returns that digit is of type J*/
- }
- else {
- printf("This is an i type instruction"); /*else will return that digit is of type I*/
- }
- } while (INERR != input);
- puts("Quitting");
- return(0);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement