casm.l  |  casm.y  |  casm.h  |  Makefile

%{

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string.h>
#include "casm.h"

typedef struct label_array {
  char data[100][80];
  int addr[100];
} label_array;
  
int x;
int i, str_cntr;
int errno;
int cmd_cntr = 0;
FILE* ausgabe;
unsigned int command;
label_array my_labelarray;

%}

%token ERROR
%token WS  KM  RM LE
%token reg imm lab str
%token DW
%token LW SW PDI PDO
%token HI SET XCH
%token ADD SUB MUL DIV MOD PCA PCS
%token AND OR XOR SHL SHR RTL RTR FBS CBS
%token CST CGT CE
%token JMP JMR BEZ BGZ ISP ISD IRD IRE
%token LDA SVA DTA
%start lines
%%

lines                   :stmt LE
                        |data_assign LE
                        |stmt LE lines
                        |data_assign LE lines
                        |RM LE lines
                        |lab LE lines
                        |RM LE
                        |WS lines
                        |LE
                        |LE lines
                     ;                         
/*---------------------------------------------*/
/*data_assign*/
data_assign                     :DW WS imm { printf("found DW!\n"); assemble(d_type, yylval, 0, 0, 0); }
                                |DW WS str {
                                             for (str_cntr = 1; yytext[str_cntr] != '\''; str_cntr++) {        
                                               if (yytext[str_cntr] < 32) printf("Warning: control char in string!\r\n");
                                               assemble(d_type , yytext[str_cntr] , str_cntr-1 , 0 ,0 );
                                             }
                                             printf("found DW/S! \n");
                                           }
                                ;
/*---------------------------------------------*/
/*stmt*/
stmt                            :data_transfer
                                |stmt_sets
                                |arithmetics
                                |logical
                                |conditions
                                |sqce_control
                                |special
                                ;
/*---------------------------------------------*/
/*stmt-data_transfer*/
data_transfer                   :data
                                |data_peripheral
                                ;
                               
/*---------------------------------------------*/
data                            :LW WS reg KM reg { printf("found LW!\n"); assemble(r_type, op_NUL, $3, $5, sc_LW); }
                                |SW WS reg KM reg { printf("found SW!\n"); assemble(r_type, op_NUL, $3, $5, sc_SW); }
                                ;
/*---------------------------------------------*/
data_peripheral                 :peri_reg_cmd
                                |peri_imm_cmd
                                ;
                               
peri_reg_cmd                    :PDI WS reg KM reg { printf("found PDI_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_PDI); }
                                |PDO WS reg KM reg { printf("found PDI_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_PDO); }
                                ;
                               
peri_imm_cmd                    :PDI WS reg KM imm { printf("found PDI_imm\n"); assemble(i_type, op_PDI, $3, $5, 0); }
                                |PDO WS reg KM imm { printf("found PDI_imm\n"); assemble(i_type, op_PDO, $3, $5, 0); }
                                ;
/*---------------------------------------------*/
/*stmt-sets*/
stmt_sets                       :set_reg_cmd
                                |set_imm_cmd
                                |set_lab_cmd
                                ;
                               
set_reg_cmd                     :HI WS reg KM  reg      { printf("found HI__reg\n"); assemble(r_type, op_NUL, $3, $5, sc_HI ); }       
                                |SET WS reg KM reg      { printf("found SET_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_SET); }
                                |XCH WS reg KM reg      { printf("found XCH_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_XCH); }
                                ;
                               
set_imm_cmd                     :HI WS reg KM  imm      { printf("found HI__imm\n"); assemble(i_type, op_HI , $3, $5, 0); }
                                |SET WS reg KM imm      { printf("found SET_imm\n"); assemble(i_type, op_SET, $3, $5, 0); }
                                ;
                               
set_lab_cmd                     :SET WS reg KM lab      { printf("found SET_lab\n"); assemble(i_type, op_SET, $3, search4Label(my_labelarray, yytext), 0); }
                                ;
                               
/*---------------------------------------------*/
/*stmt-arithmetics*/
arithmetics                     :ADD WS reg KM reg      { printf("found ADD_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_ADD); }
                                |ADD WS reg KM imm      { printf("found ADD_imm\n"); assemble(i_type, op_ADD, $3, $5, 0); }
                                |SUB WS reg KM reg      { printf("found SUB_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_SUB); }
                                |SUB WS reg KM imm      { printf("found SUB_imm\n"); assemble(i_type, op_SUB, $3, $5, 0); }
                                |MUL WS reg KM reg      { printf("found MUL_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_MUL); }
                                |MUL WS reg KM imm      { printf("found MUL_imm\n"); assemble(i_type, op_MUL, $3, $5, 0); }
                                |DIV WS reg KM reg      { printf("found DIV_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_DIV); }
                                |DIV WS reg KM imm      { printf("found DIV_imm\n"); assemble(i_type, op_DIV, $3, $5, 0); }
                                |MOD WS reg KM reg      { printf("found MOD_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_MOD); }
                                |MOD WS reg KM imm      { printf("found MOD_imm\n"); assemble(i_type, op_MOD, $3, $5, 0); }
                                |PCA WS reg KM reg      { printf("found PCA_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_PCA); }
                                |PCA WS reg KM imm      { printf("found PCA_imm\n"); assemble(i_type, op_PCA, $3, $5, 0); }
                                |PCS WS reg KM reg      { printf("found PCS_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_PCS); }
                                |PCS WS reg KM imm      { printf("found PCS_imm\n"); assemble(i_type, op_PCS, $3, $5, 0); }
                                ;

/*---------------------------------------------*/
/*stmt-logical*/
logical                         :arit_reg_cmd
                                |arit_imm_cmd
                                ;

arit_reg_cmd                    :AND WS reg KM reg      { printf("found AND_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_AND); }
                                |OR  WS reg KM reg      { printf("found OR__reg\n"); assemble(r_type, op_NUL, $3, $5, sc_OR ); }
                                |XOR WS reg KM reg      { printf("found XOR_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_XOR); }
                                |SHL WS reg KM reg      { printf("found SHL_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_SHL); }
                                |SHR WS reg KM reg      { printf("found SHR_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_SHR); }
                                |RTL WS reg KM reg      { printf("found RTL_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_RTL); }
                                |RTR WS reg KM reg      { printf("found RTR_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_RTR); }
                                |FBS WS reg KM reg      { printf("found FBS_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_FBS); }
                                |CBS WS reg KM reg      { printf("found CBS_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_CBS); }
                                ;
                               
arit_imm_cmd                    :AND WS reg KM imm      { printf("found AND_imm\n"); assemble(i_type, op_AND, $3, $5, 0); }                            
                                |OR  WS reg KM imm      { printf("found OR__imm\n"); assemble(i_type, op_OR , $3, $5, 0); }
                                |XOR WS reg KM imm      { printf("found XOR_imm\n"); assemble(i_type, op_XOR, $3, $5, 0); }
                                |SHL WS reg KM imm      { printf("found SHL_imm\n"); assemble(i_type, op_SHL, $3, $5, 0); }
                                |SHR WS reg KM imm      { printf("found SHR_imm\n"); assemble(i_type, op_SHR, $3, $5, 0); }
                                |RTL WS reg KM imm      { printf("found RTL_imm\n"); assemble(i_type, op_RTL, $3, $5, 0); }
                                |RTR WS reg KM imm      { printf("found RTR_imm\n"); assemble(i_type, op_RTR, $3, $5, 0); }
                                |FBS WS reg KM imm      { printf("found FBS_imm\n"); assemble(i_type, op_FBS, $3, $5, 0); }
                                |CBS WS reg KM imm      { printf("found CBS_imm\n"); assemble(i_type, op_CBS, $3, $5, 0); }
                                ;
/*--------------------------------------------- */                             
/*stmt-conditions*/
conditions                      :cond_reg_cmd
                                |cond_imm_cmd
                                ;

cond_reg_cmd                    :CST WS reg KM reg      { printf("found CST_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_CST); }
                                |CGT WS reg KM reg      { printf("found CGT_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_CGT); }
                                |CE  WS reg KM reg      { printf("found CE__reg\n"); assemble(r_type, op_NUL, $3, $5, sc_CE ); }
                                ;
                               
cond_imm_cmd                    :CST WS reg KM imm      { printf("found CST_imm\n"); assemble(i_type, op_CST, $3, $5, 0); }
                                |CGT WS reg KM imm      { printf("found CGT_imm\n"); assemble(i_type, op_CGT, $3, $5, 0); }
                                |CE  WS reg KM imm      { printf("found CE__imm\n"); assemble(i_type, op_CE , $3, $5, 0); }
                                ;
/*---------------------------------------------*/
/*stmt-sqce_control*/
sqce_control                    :jmp_reg_cmd
                                |jmp_imm_cmd
                                |jmp_lab_cmd
                                |bch_reg_cmd
                                |bch_imm_cmd
                                |bch_lab_cmd
                                |isp_cmd
                                |ISD                    { printf("found ISD!\n"); assemble(v_type, op_NUL, 0, 0, sc_ISD ); }
                                |IRD                    { printf("found IRD!\n"); assemble(v_type, op_NUL, 0, 0, sc_IRD ); }
                                |IRE                    { printf("found IRE!\n"); assemble(v_type, op_NUL, 0, 0, sc_IRE ); }
                               
                               
                                ;
                               
jmp_reg_cmd                     :JMP WS reg             { printf("found JMP_reg\n"); assemble(v_type, op_NUL, $3, 0, sc_JMP); }
                                |JMR WS reg             { printf("found JMR_reg\n"); assemble(v_type, op_NUL, $3, 0, sc_JMR); }
                                ;
                                                               
jmp_imm_cmd                     :JMP WS imm             { printf("found JMP_imm\n"); assemble(j_type, op_JMP, $3, 0, 0); }
                                |JMR WS imm             { printf("found JMR_imm\n"); assemble(j_type, op_JMR, $3, 0, 0); }
                                ;
                               
jmp_lab_cmd                     :JMP WS lab             { printf("found JMP_lab\n"); assemble(j_type, op_JMP, search4Label(my_labelarray, yytext), 0, 0); }
                                |JMR WS lab             { printf("found JMR_lab\n"); assemble(j_type, op_JMR, search4Label(my_labelarray, yytext), 0, 0); }
                                ;
                                               
bch_reg_cmd                     :BEZ WS reg KM reg      { printf("found BEZ_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_BEZ ); }
                                |BGZ WS reg KM reg      { printf("found BGZ_reg\n"); assemble(r_type, op_NUL, $3,  0, sc_BGZ ); }
                                ;
                               
bch_imm_cmd                     :BEZ WS reg KM imm      { printf("found BEZ_imm\n"); assemble(i_type, op_BEZ, $3, $5, 0); }
                                |BGZ WS reg KM imm      { printf("found BGZ_imm\n"); assemble(i_type, op_BGZ, $3, $5, 0); }
                                ;
                               
bch_lab_cmd                     :BEZ WS reg KM lab      { printf("found BEZ_lab\n"); assemble(i_type, op_BEZ, $3, search4Label(my_labelarray, yytext), 0); }
                                |BGZ WS reg KM lab      { printf("found BGZ_lab\n"); assemble(i_type, op_BGZ, $3, search4Label(my_labelarray, yytext), 0); }
                                ;
                               
isp_cmd                         :ISP WS reg KM reg      { printf("found ISP_reg\n"); assemble(r_type, op_NUL, $3, $5, sc_ISP); }
                                |ISP WS reg KM imm      { printf("found ISP_imm\n"); assemble(i_type, op_ISP, $3, $5, 0); }
                                |ISP WS reg KM lab      { printf("found ISP_lab\n"); assemble(i_type, op_ISP, $3, search4Label(my_labelarray, yytext), 0); }
                                ;
/*---------------------------------------------*/
/*stmt-special*/
special                         :special_reg_cmd
                                |special_imm_cmd
                                |special_lab_cmd
                                ;
                               
special_reg_cmd                 :LDA WS reg             { printf("found LDA_reg\n"); assemble(v_type, op_NUL, $3, 0, sc_LDA); }
                                |SVA WS reg             { printf("found SVA_reg\n"); assemble(v_type, op_NUL, $3, 0, sc_SVA); }
                                ;
                               
special_imm_cmd                 :LDA WS imm             { printf("found LDA_imm\n"); assemble(i_type, op_LDA, $3, 0, 0); }
                                |SVA WS imm             { printf("found SVA_imm\n"); assemble(j_type, op_SVA, $3, 0, 0); }
                                |DTA WS imm             { printf("found DTA_imm\n"); assemble(j_type, op_DTA, $3, 0, 0); }
                                ;
                               
special_lab_cmd                 :LDA WS lab             { printf("found LDA_lab\n"); assemble(j_type, op_LDA, search4Label(my_labelarray, yytext), 0, 0); }
                                |SVA WS lab             { printf("found SVA_lab\n"); assemble(j_type, op_SVA, search4Label(my_labelarray, yytext), 0, 0); }
                                |DTA WS lab             { printf("found DTA_lab\n"); assemble(j_type, op_DTA, search4Label(my_labelarray, yytext) - cmd_cntr - 1, 0, 0); }
                                ;
/*---------------------------------------------*/
%%
#include "lex.yy.c"

int collectLabels(FILE* _eingabe, label_array* array) {
  char zeile[256] ;
  char zeichen = 0;
  int running = 0;
  int i = 0;
  int s = 0;
  int char_cnt = 0;
  int label_count = 0;
  int command_counter = 0;
  int stringstart = 0;
  int stringend = 0;

  int k;
        
  do { 
    running = fread(&zeichen, 1, 1, _eingabe);
    zeile[i] = zeichen;
    i++;

    if ((zeichen == '\n') || (running == 0 )) {
      if (running == 0 && zeichen != '\n') {
        zeile[i] = '\0';
      }

      zeile[i - 1] = '\0';

      i = s = 0;
      for (i = 0; zeile[i] == ' ' || zeile[i] == '\r'; i++) s++; // CR/Space ignore
      for (i = 0; zeile[s] != '\0'; i = i + 1, s = s + 1) zeile[i] = zeile[s];
      zeile[i] = '\0';
                       
      if ((zeile[0] >= 'a' && zeile[0] <= 'z') || (zeile[0] >= 'A' && zeile[0] <= 'Z')) {
        for (i = 3; zeile[i] && zeile[i] != '\'' && zeile[i] != ';'; i++);  // find stringdef start
        if (zeile[i] == '\'')                                               // if a stringdef start has been found
          for (k = i + 1; zeile[k] && zeile[k] != '\''; k++)                // increase counter stringsize times
            command_counter++;
        else  
          command_counter++;
      }

      if (zeile[0] == '(' ) {
        for (i = 0; zeile[i] != ')' && zeile[i] != '\0'; i++);
        zeile[i+1] = '\0';
        array->addr[label_count] = command_counter + char_cnt;
        strcpy(array->data[label_count], zeile);
        label_count++; 
      }

      memset(zeile, 0, sizeof(zeile));
      i = s = 0 ;
    }


  } while (running);

  return label_count;
};


int search4Label(label_array array, char* my_label) {
  int counter;

  for (i = 0; my_label[i] != '\0'; i++)
    if (my_label[i] == ')') {
      my_label[i+1] = '\0';
      break;
    }

  for (counter = 0; counter < 100; counter++ ) {
    if (!array.data[counter][0]) { return -1; }
    if (!strcmp(array.data[counter], my_label)) break;
  }
  return array.addr[counter];
}


void assemble(int typ, unsigned int opcode, unsigned int param1, unsigned int param2, unsigned int sc) {
  unsigned int temp1, temp2, temp3, temp4;
  temp1 = temp2 = temp3 = temp4 = 0;
  command = 0;
        
  if (param1 == -1) yyerror("Label not found");

  if (typ == j_type) { 
    temp1 = temp1 | opcode;
    temp1 = temp1 << 27;
       
    temp2 = temp2 | param1;
               
    command = command | temp1;
    command = command | temp2;
  }

  if (typ == i_type) {
    temp1 = temp1 | opcode;
    temp1 = temp1 << 27;
               
    temp2 = temp2 | param1;
    temp2 = temp2 << 22;
               
    temp3 = temp3 | param2;
               
    command = command | temp1;
    command = command | temp2;
    command = command | temp3;
  }
 
  if (typ == r_type) {
    temp1 = temp1 | opcode;
    temp1 = temp1 << 27;
               
    temp2 = temp2 | param1;
    temp2 = temp2 << 22;
               
    temp3 = temp3 | param2;
    temp3 = temp3 << 17;
               
    temp4 = temp4 | sc;
               
    command = command | temp1;
    command = command | temp2;
    command = command | temp3;
    command = command | temp4;
  }
  
  if (typ == v_type) {
    temp1 = temp1 | opcode;
    temp1 = temp1 << 27;
               
    temp2 = temp2 | param1;
    temp2 = temp2 << 22;
               
    temp4 = temp4 | sc;
               
    command = command | temp1;
    command = command | temp2;
    command = command | temp4;
  }

  if (typ == d_type) {
    cmd_cntr+=param2;
    command = opcode;
  }

  for (i = 0; i < 4; i++) fprintf(ausgabe, "%c", (command >> (3-i)*8));
  cmd_cntr++;
}


int yyerror(char* s) {
  fprintf(stderr, "Error in Zeile %i : %s \n", zeile, s);
}



int main(int argc,char** argv) {
  memset(&my_labelarray, 0, sizeof(label_array));
  
  if (argc != 3) {
    printf("Usage %s outputfile inputfile \n", argv[0]);
    exit(1);
  }
  ausgabe = fopen(argv[1], "wb+");
  if (!ausgabe) {
    printf("Cant open %s\n", argv[1]);
    exit(1);
  }
  yyin = fopen(argv[2], "r");
  if (!yyin) {
    printf("%s, File not Found\n", argv[2]);
    exit(1);
  }
  x = collectLabels(yyin, &my_labelarray);
  printf("found %i Label(s) \n", x);
  fseek(yyin, 0, 0);

  errno = yyparse();
  fclose(ausgabe);

  //for debug only
  printf("%d commands found!\n",cmd_cntr);
  //debug end
  return errno;
}