diff --git a/A5/encoding.txt b/A5/encoding.txt new file mode 100644 index 0000000..7d1457b --- /dev/null +++ b/A5/encoding.txt @@ -0,0 +1,95 @@ +x86prime instructions and encoding +---------------------------------- + +Encoding: Assembler Operation + +00000000 00000000 stop stop the machine +00000001 0000ssss ret s return from function call +0001aaaa ddddssss op s,d reg/reg arithmetic (see below) +00100001 ddddssss movq s,d reg->reg copy +00110001 ddddssss movq (s),d load (memory -> reg copy) +00111001 ddddssss movq d,(s) store (reg -> memory copy) +- +0100cccc ddddssss pp...32...pp cb s,d,p compare and continue at p if... (see below) +01001110 dddd0000 pp...32...pp call p,d function call +01001111 00000000 pp...32...pp jmp p continue at p +0101aaaa dddd0000 ii...32...ii op $i,d constant/reg arithmethic(see below) +01100100 dddd0000 ii...32...ii movq $i,d constant -> register +01110101 ddddssss ii...32...ii movq i(s),d load (memory -> reg copy) +01111101 ddddssss ii...32...ii movq d,i(s) store (reg -> memory copy) +- +10000001 ddddssss leaq (s),d s -> d +10010010 dddd0000 zzzzvvvv leaq (,z,v),d z*v -> d +10010011 ddddssss zzzzvvvv leaq (s,z,v),d s+z*v -> d +10100100 dddd0000 ii...32...ii leaq i,d i -> d +10100101 ddddssss ii...32...ii leaq i(s),d i+s -> d +10110110 dddd0000 zzzzvvvv ii...32...ii leaq i(,z,v),d i+z*v -> d +10110111 ddddssss zzzzvvvv ii...32...ii leaq i(s,z,v),d i+s+z*v -> d +- +1111cccc dddd0000 ii...32...ii pp...32...pp cb $i,d,p compare and continue at p if... (see below) + +Note: first 4 bits are called the "major opcode", next 4 bits are called the "minor opcode". + +Explanations: + +aaaa indicates the kind of arithmetic operation. All operate on full 64 bits: + +0000 add addition +0001 sub subtraction +0010 and bitwise and +0011 or bitwise or +0100 xor bitwise xor +0101 mul unsigned multiplication +0110 sar shift arithmetic right (preserve topmost bit) +0111 sal shift arithmetic left (zero into lsb, do not preserve topmost bit) +1000 shr shift (logical) right (zero into topmost bit) +1001 imul signed multiplication + +d,s and z are registers: + +0000 %rax 1000 %r8 +0001 %rbx 1001 %r9 +0010 %rcx 1010 %r10 +0011 %rdx 1011 %r11 +0100 %rbp 1100 %r12 +0101 %rsi 1101 %r13 +0110 %rdi 1110 %r14 +0111 %rsp 1111 %r15 + +v is a scale factor encoded into the field vvvv in the form of a shift amount as follows: + +vvvv v +0000 1 +0001 2 +0010 4 +0011 8 + +ii...32...ii is a 32 bit signed immediate +pp...32...pp is a 32 bit target address + + is a condition mnemonic used in compare-and-branch. The compare-and-branch +instruction cb is not part of the original x86 instruction set, but the +conditions in x86prime carry the same meaning as for x86. + +Example: cble %rdi,%rbp,target = if %rdi <= %rbp (signed) then jump to target + +Encoding Semantic +0000 e Equal +0001 ne Not equal +0010 +0011 +0100 l less (signed) +0101 le less or equal (signed) +0110 g greater (signed) +0111 ge greater or equal (signed) +1000 a above (unsigned) +1001 ae above or equal (unsigned) +1010 b below (unsigned) +1011 be below or equal (unsigned) +11xx + +Note that signed and unsigned comparisons are different. + +call places the return address in a register instead of pushing it onto the stack. +ret returns to the address in a register instead of popping it from the stack. +returning to address 0 or to a negative address (bit 64 set) stops the machine. diff --git a/A5/main.c b/A5/main.c index 146cbae..95e60e6 100644 --- a/A5/main.c +++ b/A5/main.c @@ -105,6 +105,7 @@ int main(int argc, char* argv[]) { val reg_s = pick_bits(0, 4, inst_bytes[1]); val reg_z = pick_bits(4, 4, inst_bytes[2]); val shamt = pick_bits(0, 4, inst_bytes[2]); + val target = pick_bits(0, 8, inst_bytes[2]); // decode instruction type from major operation code bool is_return_or_stop = is(RETURN_STOP, major_op); @@ -122,9 +123,24 @@ int main(int argc, char* argv[]) { bool is_imm_cbranch = is(IMM_CBRANCH, major_op); // Right now, we can only execute instructions with a size of 2. - // TODO 2021: // from info above determine the instruction size - val ins_size = from_int(2); + bool size_is_2 = (is_return_or_stop || is_reg_arithmetic || is_reg_movq || is_reg_movq_mem || is_leaq2); + val size_2 = use_if(size_is_2, from_int(2)); + bool size_is_3 = (is_leaq3); + val size_3 = use_if(size_is_3, from_int(3)); + bool size_is_6 = (is_cflow || is_imm_arithmetic || is_imm_movq || is_imm_movq_mem || is_leaq6); + val size_6 = use_if(size_is_6, from_int(6)); + bool size_is_7 = (is_leaq7); + val size_7 = use_if(size_is_7, from_int(7)); + bool size_is_10 = (is_imm_cbranch); + val size_10 = use_if(size_is_10, from_int(10)); + + val add_1 = add(size_2, size_3); + val add_2 = add(add_1, size_6); + val add_3 = add(add_2, size_7); + val add_4 = add(add_3, size_10); + + val ins_size = add_4; // broad categorization of the instruction bool is_leaq = is_leaq2 || is_leaq3 || is_leaq6 || is_leaq7; @@ -139,9 +155,9 @@ int main(int argc, char* argv[]) { bool imm_p_pos6 = is_imm_cbranch; /* all other at position 2 */ // unimplemented control signals: - bool is_load = false; // TODO 2021: Detect when we're executing a load - bool is_store = false; // TODO 2021: Detect when we're executing a store - bool is_conditional = false; // TODO 2021: Detect if we are executing a conditional flow change + bool is_load = (is_mem_access && !pick_one(3,minor_op)); + bool is_store = (is_mem_access && pick_one(3,minor_op)); + bool is_conditional = (is_cflow || is_imm_cbranch) && !(is(0xE, minor_op) || is(0xF, minor_op)); // TODO 2021: Add additional control signals you may need below.... @@ -214,8 +230,11 @@ int main(int argc, char* argv[]) { val pc_incremented = add(pc, ins_size); // determine the next position of the program counter - // TODO 2021: Add any additional sources for the next PC (for call, ret, jmp and conditional branch) - val pc_next = pc_incremented; + bool is_jump = is_cflow && (is(0xF,minor_op) || (is_conditional && !reduce_or(compute_result))); + val pc_next_if_not_control = use_if(!is_jump, pc_incremented); + val pc_next_if_jump = use_if(is_jump, target); + val pc_next_if_return = use_if(is_return, reg_out_b); + val pc_next = add(add(pc_next_if_not_control, pc_next_if_jump), pc_next_if_return); /*** MEMORY ***/ // read from memory if needed @@ -232,6 +251,7 @@ int main(int argc, char* argv[]) { reg_write(regs, reg_d, datapath_result, reg_wr_enable); // write to memory if needed + printf("%i\n",is_store); memory_write(mem, agen_result, reg_out_a, is_store); // update program counter diff --git a/A5/sim b/A5/sim new file mode 100755 index 0000000..de17651 Binary files /dev/null and b/A5/sim differ diff --git a/A5/test_runs/test1.hex b/A5/test_runs/test1.hex new file mode 100644 index 0000000..87ffdbe --- /dev/null +++ b/A5/test_runs/test1.hex @@ -0,0 +1,17 @@ +00000000 : # test: +00000000 : A45030000000 # leaq data, %rsi +00000006 : 640000000000 # movq $0, %rax +0000000c : 644000000000 # movq $0, %rbp +00000012 : 93B503 # leaq (%rsi, %rax, 8), %r11 +00000015 : 313B # movq (%r11), %rdx +00000017 : 500001000000 # addq $1, %rax +0000001d : 1043 # addq %rdx, %rbp +0000001f : 93B503 # leaq (%rsi, %rax, 8), %r11 +00000022 : 313B # movq (%r11), %rdx +00000024 : 500001000000 # addq $1, %rax +0000002a : 1043 # addq %rdx, %rbp +0000002c : 0000 # stop +00000030 : # .align 8 +00000030 : # data: +00000030 : 2a00000000000000 # .quad 42 +00000038 : 1500000000000000 # .quad 21 diff --git a/A5/test_runs/test1.out b/A5/test_runs/test1.out new file mode 100644 index 0000000..359d574 --- /dev/null +++ b/A5/test_runs/test1.out @@ -0,0 +1,25 @@ +1 0 +0 +2 6 +0 +3 c +0 +4 12 +0 +5 15 +0 +6 17 +0 +7 1d +0 +8 1f +0 +9 22 +0 +10 24 +0 +11 2a +0 +12 2c +0 +Done diff --git a/A5/test_runs/test1.sym b/A5/test_runs/test1.sym new file mode 100644 index 0000000..691f6da --- /dev/null +++ b/A5/test_runs/test1.sym @@ -0,0 +1,2 @@ +data : 00000030 +test : 00000000 diff --git a/A5/test_runs/test1.trc b/A5/test_runs/test1.trc new file mode 100644 index 0000000..67346fa --- /dev/null +++ b/A5/test_runs/test1.trc @@ -0,0 +1,24 @@ +P 0 0 +R 5 30 +P 0 6 +R 0 0 +P 0 c +R 4 0 +P 0 12 +R b 30 +P 0 15 +R 3 2a +P 0 17 +R 0 1 +P 0 1d +R 4 2a +P 0 1f +R b 38 +P 0 22 +R 3 15 +P 0 24 +R 0 2 +P 0 2a +R 4 3f +P 0 2c +P 0 2e diff --git a/A5/test_runs/test2.hex b/A5/test_runs/test2.hex new file mode 100644 index 0000000..e4b3238 --- /dev/null +++ b/A5/test_runs/test2.hex @@ -0,0 +1,22 @@ +00000000 : # test: +00000000 : 517008000000 # subq $8, %rsp +00000006 : 39B7 # movq %r11, (%rsp) +00000008 : 938623 # leaq (%rdi, %rcx, 8), %r8 +0000000b : 4F0025000000 # jmp .L6 +00000011 : # .L7: +00000011 : 3906 # movq %rax, (%rdi) +00000013 : # .L8: +00000013 : 506008000000 # addq $8, %rdi +00000019 : 505008000000 # addq $8, %rsi +0000001f : 503008000000 # addq $8, %rdx +00000025 : # .L6: +00000025 : 4B683d000000 # cbbe %r8, %rdi, .L10 +0000002b : 3125 # movq (%rsi), %rcx +0000002d : 3103 # movq (%rdx), %rax +0000002f : 472011000000 # cbge %rax, %rcx, .L7 +00000035 : 3926 # movq %rcx, (%rdi) +00000037 : 4F0013000000 # jmp .L8 +0000003d : # .L10: +0000003d : 31B7 # movq (%rsp), %r11 +0000003f : 507008000000 # addq $8, %rsp +00000045 : 010B # ret %r11 diff --git a/A5/test_runs/test2.out b/A5/test_runs/test2.out new file mode 100644 index 0000000..9101694 --- /dev/null +++ b/A5/test_runs/test2.out @@ -0,0 +1,18 @@ +1 0 +0 +2 6 +1 +3 8 +0 +4 b +0 +5 25 +0 +6 3d +0 +7 3f +0 +8 45 +0 + -- value mismatch, access 'P' 0 + -- with value 47, but tracefile expected 0 diff --git a/A5/test_runs/test2.sym b/A5/test_runs/test2.sym new file mode 100644 index 0000000..3e2246d --- /dev/null +++ b/A5/test_runs/test2.sym @@ -0,0 +1,5 @@ +.L10 : 0000003d +.L6 : 00000025 +.L8 : 00000013 +.L7 : 00000011 +test : 00000000 diff --git a/A5/test_runs/test2.trc b/A5/test_runs/test2.trc new file mode 100644 index 0000000..e83599d --- /dev/null +++ b/A5/test_runs/test2.trc @@ -0,0 +1,14 @@ +P 0 0 +R 7 fffffffffffffff8 +P 0 6 +M fffffffffffffff8 0 +P 0 8 +R 8 0 +P 0 b +P 0 25 +P 0 3d +R b 0 +P 0 3f +R 7 0 +P 0 45 +P 0 0 diff --git a/A5/tests/test1.prime b/A5/tests/test1.prime new file mode 100644 index 0000000..7f93143 --- /dev/null +++ b/A5/tests/test1.prime @@ -0,0 +1,18 @@ +test: + leaq data,%rsi + movq $0,%rax + movq $0,%rbp + leaq (%rsi, %rax, 8),%r11 + movq (%r11),%rdx + addq $1,%rax + addq %rdx,%rbp + leaq (%rsi, %rax, 8), %r11 + movq (%r11), %rdx + addq $1, %rax + addq %rdx,%rbp + stop + +.align 8 +data: + .quad 42 + .quad 21 \ No newline at end of file diff --git a/A5/tests/test2.prime b/A5/tests/test2.prime new file mode 100644 index 0000000..acc5a5a --- /dev/null +++ b/A5/tests/test2.prime @@ -0,0 +1,22 @@ +test: + subq $8, %rsp + movq %r11, (%rsp) + leaq (%rdi, %rcx, 8), %r8 + jmp .L6 +.L7: + movq %rax, (%rdi) +.L8: + addq $8, %rdi + addq $8, %rsi + addq $8, %rdx +.L6: + cbbe %r8, %rdi, .L10 + movq (%rsi), %rcx + movq (%rdx), %rax + cbge %rax, %rcx, .L7 + movq %rcx, (%rdi) + jmp .L8 +.L10: + movq (%rsp), %r11 + addq $8, %rsp + ret %r11 \ No newline at end of file