Advertisement
Guest User

Untitled

a guest
Feb 23rd, 2018
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 15.84 KB | None | 0 0
  1. #include <stdio.h> // for stderr
  2. #include <stdlib.h> // for exit()
  3. #include "types.h"
  4. #include "utils.h"
  5. #include "riscv.h"
  6.  
  7. void execute_rtype(Instruction, Processor *);
  8. void execute_itype_except_load(Instruction, Processor *);
  9. void execute_branch(Instruction, Processor *);
  10. void execute_jal(Instruction, Processor *);
  11. void execute_load(Instruction, Processor *, Byte *);
  12. void execute_store(Instruction, Processor *, Byte *);
  13. void execute_ecall(Processor *, Byte *);
  14. void execute_lui(Instruction, Processor *);
  15.  
  16. void execute_instruction(uint32_t instruction_bits, Processor *processor,Byte *memory) {    
  17.     Instruction instruction = parse_instruction(instruction_bits);
  18.     switch(instruction.opcode) {
  19.         case 0x33:
  20.             execute_rtype(instruction, processor);
  21.             break;
  22.         case 0x13:
  23.             execute_itype_except_load(instruction, processor);
  24.             break;
  25.         case 0x73:
  26.             execute_ecall(processor, memory);
  27.             break;
  28.         case 0x63:
  29.             execute_branch(instruction, processor);
  30.             break;
  31.         case 0x6F:
  32.             execute_jal(instruction, processor);
  33.             break;
  34.         case 0x23:
  35.             execute_store(instruction, processor, memory);
  36.             break;
  37.         case 0x03:
  38.             execute_load(instruction, processor, memory);
  39.             break;
  40.         case 0x37:
  41.             execute_lui(instruction, processor);
  42.             break;
  43.         default: // undefined opcode
  44.             handle_invalid_instruction(instruction);
  45.             exit(-1);
  46.             break;
  47.     }
  48. }
  49.  
  50. void execute_rtype(Instruction instruction, Processor *processor) {
  51.     sWord rs1_value, rs2_value;
  52.     sByte msb;
  53.     Word ones, immediate;
  54.     sDouble rd_value, rs1_double, rs2_double;
  55.  
  56.     switch (instruction.rtype.funct3){
  57.         case 0x0:
  58.             switch (instruction.rtype.funct7) {
  59.                 case 0x0:
  60.                     // Add
  61.                     processor->R[instruction.rtype.rd] = processor->R[instruction.rtype.rs1] + processor->R[instruction.rtype.rs2];
  62.                     processor->PC = processor->PC+4;
  63.                     break;
  64.                 case 0x1:
  65.                     //Mul
  66.                     rs1_value = processor->R[instruction.rtype.rs1];
  67.                     rs2_value = processor->R[instruction.rtype.rs2];
  68.                     rd_value = (sDouble) rs1_value * (sDouble) rs2_value;
  69.                     processor->R[instruction.rtype.rd] = (Register) (rd_value & 0xFFFFFFFF);
  70.                     processor->PC = processor->PC+4;
  71.                     break;
  72.                 case 0x20:
  73.                     //Sub
  74.                     processor->R[instruction.rtype.rd] = (Register) (processor->R[instruction.rtype.rs1] - processor->R[instruction.rtype.rs2]);
  75.                     processor->PC = processor->PC+4;
  76.                     break;
  77.                 default:
  78.                     handle_invalid_instruction(instruction);
  79.                     exit(-1);
  80.                     break;
  81.             }
  82.             break;
  83.         case 0x1:
  84.             switch (instruction.rtype.funct7) {
  85.                 case 0x0:
  86.                     // SLL
  87.                     processor->R[instruction.rtype.rd] = processor->R[instruction.rtype.rs1] << processor->R[instruction.rtype.rs2];
  88.                     processor->PC = processor->PC+4;
  89.                     break;
  90.                 case 0x1:
  91.                     // MULH
  92.                     processor->R[instruction.rtype.rd] = (((sDouble) (sWord) processor->R[instruction.rtype.rs1] * (sDouble) (sWord) processor->R[instruction.rtype.rs2]) >> 32);
  93.                     processor->PC = processor->PC+4;
  94.                     break;
  95.             }
  96.             break;
  97.         case 0x2:
  98.             // SLT
  99.             if((sWord) processor->R[instruction.rtype.rs1] < (sWord) processor->R[instruction.rtype.rs2])
  100.                 processor->R[instruction.rtype.rd] = 1;
  101.             else
  102.                 processor->R[instruction.rtype.rd] = 0;
  103.             processor->PC = processor->PC+4;
  104.             break;
  105.         case 0x4:
  106.             switch (instruction.rtype.funct7) {
  107.                 case 0x0:
  108.                     // XOR
  109.                     processor->R[instruction.rtype.rd] = processor->R[instruction.rtype.rs1] ^ processor->R[instruction.rtype.rs2];
  110.                     processor->PC = processor->PC+4;
  111.                     break;
  112.                 case 0x1:
  113.                     // DIV
  114.                     processor->R[instruction.rtype.rd] = (Register) ((sDouble) ((sWord) processor->R[instruction.rtype.rs1]) / (sDouble) ((sWord) processor->R[instruction.rtype.rs2]));
  115.                     processor->PC = processor->PC+4;
  116.                     break;
  117.                 default:
  118.                     handle_invalid_instruction(instruction);
  119.                     exit(-1);
  120.                     break;
  121.             }
  122.             break;
  123.         case 0x5:
  124.             switch (instruction.rtype.funct7) {
  125.                 case 0x0:
  126.                     // SRL
  127.                     processor->R[instruction.rtype.rd] = processor->R[instruction.rtype.rs1] >> (processor->R[instruction.rtype.rs2] & 0x1f);
  128.                     processor->PC = processor->PC+4;
  129.                     break;
  130.                 case 0x20:
  131.                     // SRA
  132.                     immediate = processor->R[instruction.rtype.rs2] & 0x1f;
  133.                     msb = processor->R[instruction.rtype.rs2];
  134.                     msb = msb >> 31;
  135.                     if ((msb & 1) & immediate != 0){
  136.                         ones = (0xFFFFFFFF) << (32 - immediate);
  137.                         processor->R[instruction.rtype.rd] = (Register) processor->R[instruction.rtype.rs1] >> (processor->R[instruction.rtype.rs2] & 0x1f);
  138.                         processor->R[instruction.rtype.rd] = (Register) processor->R[instruction.rtype.rd] | ones;
  139.                     }
  140.                     else if (immediate == 0){
  141.                         processor->R[instruction.rtype.rd] = (Register) processor->R[instruction.rtype.rs1];
  142.                     }
  143.                     else {
  144.                         processor->R[instruction.rtype.rd] = (Register) processor->R[instruction.rtype.rs1] >> (Register) (processor->R[instruction.rtype.rs2] & 0x1f);
  145.                     }
  146.                     processor->PC = processor->PC+4;
  147.                     break;
  148.                 default:
  149.                     handle_invalid_instruction(instruction);
  150.                     exit(-1);
  151.                 break;
  152.             }
  153.             break;
  154.         case 0x6:
  155.             switch (instruction.rtype.funct7) {
  156.                 case 0x0:
  157.                     // OR
  158.                     processor->R[instruction.rtype.rd] = (Register) (processor->R[instruction.rtype.rs1] | processor->R[instruction.rtype.rs2]);
  159.                     processor->PC = processor->PC+4;
  160.                     break;
  161.                 case 0x1:
  162.                     // REM
  163.                     processor->R[instruction.rtype.rd] = (Register) ((sDouble) ((sWord) processor->R[instruction.rtype.rs1]) % ((sWord) processor->R[instruction.rtype.rs2]));
  164.                     processor->PC = processor->PC+4;
  165.                     break;
  166.                 default:
  167.                     handle_invalid_instruction(instruction);
  168.                     exit(-1);
  169.                     break;
  170.             }
  171.             break;
  172.         case 0x7:
  173.             // AND
  174.             processor->R[instruction.rtype.rd] = (Register) (processor->R[instruction.rtype.rs1] & processor->R[instruction.rtype.rs2]);
  175.             processor->PC = processor->PC+4;
  176.             break;
  177.         default:
  178.             handle_invalid_instruction(instruction);
  179.             exit(-1);
  180.             break;
  181.     }
  182. }
  183.  
  184. void execute_itype_except_load(Instruction instruction, Processor *processor) {
  185.     Word ones, check_bit, immediate;
  186.     switch (instruction.itype.funct3) {
  187.         case 0x0:
  188.             // ADDI
  189.             processor->R[instruction.itype.rd] = processor->R[instruction.itype.rs1] + sign_extend_number(instruction.itype.imm, 12);
  190.             processor->PC = processor->PC+4;
  191.             break;
  192.         case 0x1:
  193.             // SLLI
  194.             processor->R[instruction.itype.rd] = processor->R[instruction.itype.rs1] << (instruction.itype.imm & 0x1F);
  195.             processor->PC = processor->PC+4;
  196.             break;
  197.         case 0x2:
  198.             // STLI
  199.             if ((sWord) processor->R[instruction.itype.rs1] < sign_extend_number(instruction.itype.imm, 12))
  200.                 processor->R[instruction.itype.rd] = 1;
  201.             else
  202.                 processor->R[instruction.itype.rd] = 0;
  203.             processor->PC = processor->PC+4;
  204.             break;
  205.         case 0x4:
  206.             // XORI
  207.             processor->R[instruction.itype.rd] = processor->R[instruction.itype.rs1]^ sign_extend_number(instruction.itype.imm, 12);
  208.             processor->PC = processor->PC+4;
  209.             break;
  210.         case 0x5:
  211.             // Shift Right (You must handle both logical and arithmetic)
  212.             immediate = instruction.itype.imm & 0x1f;
  213.             check_bit = instruction.itype.imm >> 10;
  214.             if (!(check_bit & 1) & (immediate != 0)) {                    //Logical
  215.                 processor->R[instruction.itype.rd] =
  216.                         processor->R[instruction.itype.rs1] >> immediate;
  217.             }
  218.             else if ((check_bit & 1) & (immediate != 0)){                   //Arithmetic
  219.                 if (processor->R[instruction.itype.rs1] & 0x80000000){ //Ones shift
  220.                     ones = (0xFFFFFFFF) << (32 - immediate);
  221.                     processor->R[instruction.itype.rd] =
  222.                             processor->R[instruction.itype.rs1] >> immediate;
  223.                     processor->R[instruction.itype.rd] = processor->R[instruction.itype.rd] | ones;
  224.                 }
  225.                 else { //Zeroes shift
  226.                     processor->R[instruction.itype.rd] =
  227.                             processor->R[instruction.itype.rs1] >> immediate;
  228.                 }
  229.             }
  230.             else if (immediate == 0){
  231.                 processor->R[instruction.itype.rd] =
  232.                         processor->R[instruction.itype.rs1];
  233.             }
  234.             processor->PC = processor->PC+4;
  235.             break;
  236.         case 0x6:
  237.             // ORI
  238.             processor->R[instruction.itype.rd] = processor->R[instruction.itype.rs1] | sign_extend_number(instruction.itype.imm, 12);
  239.             processor->PC = processor->PC+4;
  240.             break;
  241.         case 0x7:
  242.             // ANDI
  243.             processor->R[instruction.itype.rd] = processor->R[instruction.itype.rs1] & sign_extend_number(instruction.itype.imm, 12);
  244.             processor->PC = processor->PC+4;
  245.             break;
  246.         default:
  247.             handle_invalid_instruction(instruction);
  248.             break;
  249.     }
  250. }
  251.  
  252. void execute_ecall(Processor *p, Byte *memory) {
  253.     Register i;
  254.    
  255.     // syscall number is given by a0 (x10)
  256.     // argument is given by a1
  257.     switch(p->R[10]) {
  258.         case 1: // print an integer
  259.             printf("%d",p->R[11]);
  260.             p->PC = p->PC+4;
  261.             break;
  262.         case 4: // print a string
  263.             for(i=p->R[11];i<MEMORY_SPACE && load(memory,i,LENGTH_BYTE);i++) {
  264.                 printf("%c",load(memory,i,LENGTH_BYTE));
  265.             }
  266.             p->PC = p->PC+4;
  267.             break;
  268.         case 10: // exit
  269.             printf("exiting the simulator\n");
  270.             p->PC = p->PC+4;
  271.             exit(0);
  272.             break;
  273.         case 11: // print a character
  274.             printf("%c",p->R[11]);
  275.             p->PC = p->PC+4;
  276.             break;
  277.         default: // undefined ecall
  278.             printf("Illegal ecall number %d\n", p->R[10]);
  279.             p->PC = p->PC+4;
  280.             exit(-1);
  281.             break;
  282.     }
  283. }
  284.  
  285. void execute_branch(Instruction instruction, Processor *processor) {
  286.     sWord offset = get_branch_offset(instruction);
  287.     switch (instruction.sbtype.funct3) {
  288.         case 0x0:
  289.             // BEQ
  290.             if (processor->R[instruction.sbtype.rs1] == processor->R[instruction.sbtype.rs2]){
  291.                 processor->PC = processor->PC + offset;
  292.             }
  293.             else
  294.                 processor->PC = processor->PC+4;
  295.             break;
  296.         case 0x1:
  297.             // BNE
  298.             if (processor->R[instruction.sbtype.rs1] != processor->R[instruction.sbtype.rs2]){
  299.                 processor->PC = processor->PC + offset;
  300.             }
  301.             else
  302.                 processor->PC = processor->PC+4;
  303.             break;
  304.         default:
  305.             handle_invalid_instruction(instruction);
  306.             exit(-1);
  307.             break;
  308.     }
  309. }
  310.  
  311. void execute_load(Instruction instruction, Processor *processor, Byte *memory) {
  312.     switch (instruction.itype.funct3) {
  313.         case 0x0:
  314.             // LB
  315.             processor->R[instruction.itype.rd] = (Register) sign_extend_number(load(memory, processor->R[instruction.itype.rs1] + sign_extend_number(instruction.itype.imm, 12), LENGTH_BYTE), 8);
  316.             processor->PC = processor->PC+4;
  317.             break;
  318.         case 0x1:
  319.             // LH
  320.             processor->R[instruction.itype.rd] = (Register) sign_extend_number(load(memory, processor->R[instruction.itype.rs1] + sign_extend_number(instruction.itype.imm, 12), LENGTH_HALF_WORD), 16);
  321.             processor->PC = processor->PC+4;
  322.             break;
  323.         case 0x2:
  324.             // LW
  325.             processor->R[instruction.itype.rd] = load(memory, processor->R[instruction.itype.rs1] + sign_extend_number(instruction.itype.imm, 12), LENGTH_WORD);
  326.             processor->PC = processor->PC+4;
  327.             break;
  328.         default:
  329.             handle_invalid_instruction(instruction);
  330.             break;
  331.     }
  332. }
  333.  
  334. void execute_store(Instruction instruction, Processor *processor, Byte *memory) {
  335.     sWord offset;
  336.     switch (instruction.stype.funct3) {
  337.         case 0x0:
  338.             // SB
  339.             offset = get_store_offset(instruction);
  340.             store(memory, processor->R[instruction.stype.rs1] + offset, LENGTH_BYTE, processor->R[instruction.stype.rs2]);
  341.             processor->PC = processor->PC+4;
  342.             break;
  343.         case 0x1:
  344.             // SH
  345.             offset = get_store_offset(instruction);
  346.             store(memory, processor->R[instruction.stype.rs1] + offset, LENGTH_HALF_WORD, processor->R[instruction.stype.rs2]);
  347.             processor->PC = processor->PC+4;
  348.             break;
  349.         case 0x2:
  350.             // SW
  351.             offset = get_store_offset(instruction);
  352.             store(memory, processor->R[instruction.stype.rs1] + offset, LENGTH_WORD, processor->R[instruction.stype.rs2]);
  353.             processor->PC = processor->PC+4;
  354.             break;
  355.         default:
  356.             handle_invalid_instruction(instruction);
  357.             exit(-1);
  358.             break;
  359.     }
  360. }
  361.  
  362. void execute_jal(Instruction instruction, Processor *processor) {
  363.     sWord offset = get_jump_offset(instruction);
  364.     processor->R[instruction.ujtype.rd] = processor->PC + 4;
  365.     processor->PC = processor->PC + offset;
  366. }
  367.  
  368. void execute_lui(Instruction instruction, Processor *processor) {
  369.     Word immediate = instruction.utype.imm<<12;
  370.     processor->R[instruction.utype.rd] = immediate;
  371.     processor->PC = processor->PC+4;
  372. }
  373.  
  374. void store(Byte *memory, Address address, Alignment alignment, Word value) {
  375.     Word intermediate;
  376.     for (int i = 0; i < alignment; i++){
  377.         intermediate = value >> (8*i);
  378.         *(memory + address + i) =  (Byte) (intermediate & 0xFF);
  379.     }
  380. }
  381.  
  382. Word load(Byte *memory, Address address, Alignment alignment) {
  383.     //MEMORY is a byte pointer pointing to the memory
  384.     //Address is where they want you to start
  385.     //Alignment is how many bytes they want you to pull.
  386.     //Oh and this is in Little Endian
  387.     Word result = 0;
  388.     for (int i = 0; i < alignment; i++)
  389.         result += *(memory + address + i)<<(8 * i);
  390.     return result;
  391. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement