diff --git a/decode1.vhdl b/decode1.vhdl index 4cd195f..5eedbab 100644 --- a/decode1.vhdl +++ b/decode1.vhdl @@ -106,8 +106,8 @@ architecture behaviour of decode1 is -- op in out A out in out len ext pipe -- mcrf; and cr logical ops 2#000# => (ALU, OP_CROP, NONE, NONE, NONE, NONE, '1', '1', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '0', '0'), - -- addpcis not implemented yet - 2#001# => (ALU, OP_ILLEGAL, NONE, NONE, NONE, NONE, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '1'), + -- addpcis + 2#001# => (ALU, OP_ADDPCIS, NONE, CONST_DX_HI, NONE, RT, '0', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', RC, '0', '0'), -- bclr, bcctr, bctar 2#100# => (ALU, OP_BCREG, SPR, SPR, NONE, SPR, '1', '0', '0', '0', ZERO, '0', NONE, '0', '0', '0', '0', '0', '0', NONE, '1', '0'), -- isync diff --git a/decode2.vhdl b/decode2.vhdl index b239392..da0bdff 100644 --- a/decode2.vhdl +++ b/decode2.vhdl @@ -100,6 +100,8 @@ architecture behaviour of decode2 is ret := ('0', (others => '0'), std_ulogic_vector(resize(signed(insn_bd(insn_in)) & "00", 64))); when CONST_DS => ret := ('0', (others => '0'), std_ulogic_vector(resize(signed(insn_ds(insn_in)) & "00", 64))); + when CONST_DX_HI => + ret := ('0', (others => '0'), std_ulogic_vector(resize(signed(insn_dx(insn_in)) & x"0000", 64))); when CONST_M1 => ret := ('0', (others => '0'), x"FFFFFFFFFFFFFFFF"); when CONST_SH => diff --git a/decode_types.vhdl b/decode_types.vhdl index 8f000a0..bd16507 100644 --- a/decode_types.vhdl +++ b/decode_types.vhdl @@ -21,7 +21,7 @@ package decode_types is OP_FETCH_FAILED ); type input_reg_a_t is (NONE, RA, RA_OR_ZERO, SPR); - type input_reg_b_t is (NONE, RB, CONST_UI, CONST_SI, CONST_SI_HI, CONST_UI_HI, CONST_LI, CONST_BD, CONST_DS, CONST_M1, CONST_SH, CONST_SH32, SPR); + type input_reg_b_t is (NONE, RB, CONST_UI, CONST_SI, CONST_SI_HI, CONST_UI_HI, CONST_LI, CONST_BD, CONST_DX_HI, CONST_DS, CONST_M1, CONST_SH, CONST_SH32, SPR); type input_reg_c_t is (NONE, RS); type output_reg_a_t is (NONE, RT, RA, SPR); type rc_t is (NONE, ONE, RC); diff --git a/execute1.vhdl b/execute1.vhdl index cac8e8a..3207958 100644 --- a/execute1.vhdl +++ b/execute1.vhdl @@ -528,6 +528,9 @@ begin end if; when OP_NOP => -- Do nothing + when OP_ADDPCIS => + result := ppc_adde(next_nia, b_in, '0')(63 downto 0); + result_en := '1'; when OP_ADD | OP_CMP | OP_TRAP => if e_in.invert_a = '0' then a_inv := a_in; diff --git a/insn_helpers.vhdl b/insn_helpers.vhdl index 8812044..acd2f72 100644 --- a/insn_helpers.vhdl +++ b/insn_helpers.vhdl @@ -30,6 +30,7 @@ package insn_helpers is function insn_bh (insn_in : std_ulogic_vector) return std_ulogic_vector; function insn_d (insn_in : std_ulogic_vector) return std_ulogic_vector; function insn_ds (insn_in : std_ulogic_vector) return std_ulogic_vector; + function insn_dx (insn_in : std_ulogic_vector) return std_ulogic_vector; function insn_to (insn_in : std_ulogic_vector) return std_ulogic_vector; function insn_bc (insn_in : std_ulogic_vector) return std_ulogic_vector; function insn_sh (insn_in : std_ulogic_vector) return std_ulogic_vector; @@ -178,6 +179,11 @@ package body insn_helpers is return insn_in(15 downto 2); end; + function insn_dx (insn_in : std_ulogic_vector) return std_ulogic_vector is + begin + return insn_in(15 downto 6) & insn_in(20 downto 16) & insn_in(0); + end; + function insn_to (insn_in : std_ulogic_vector) return std_ulogic_vector is begin return insn_in(25 downto 21); diff --git a/tests/misc/Makefile b/tests/misc/Makefile new file mode 100644 index 0000000..3f92384 --- /dev/null +++ b/tests/misc/Makefile @@ -0,0 +1,3 @@ +TEST=misc + +include ../Makefile.test diff --git a/tests/misc/head.S b/tests/misc/head.S new file mode 100644 index 0000000..9eb752c --- /dev/null +++ b/tests/misc/head.S @@ -0,0 +1,102 @@ +/* Copyright 2013-2014 IBM Corp. + * Copyrignt 2020 Shawn Anastasio + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define STACK_TOP 0x2000 + +/* Load an immediate 64-bit value into a register */ +#define LOAD_IMM64(r, e) \ + lis r,(e)@highest; \ + ori r,r,(e)@higher; \ + rldicr r,r, 32, 31; \ + oris r,r, (e)@h; \ + ori r,r, (e)@l; + + .section ".head","ax" + + /* + * Microwatt currently enters in LE mode at 0x0, so we don't need to + * do any endian fix ups + */ + . = 0 +.global _start +_start: + b boot_entry + +.global boot_entry +boot_entry: + /* setup stack */ + LOAD_IMM64(%r1, STACK_TOP - 0x100) + LOAD_IMM64(%r12, main) + mtctr %r12 + bctrl + attn // terminate on exit + b . + + +/* Test addpcis with an immediate operand of 0 (min) */ +.global test_addpcis_1 +test_addpcis_1: + mflr %r0 + std %r0, 16(%r1) + stdu %r1, -32(%r1) + + /* get address of 1 */ + bl 1f + 1: mflr %r4 + addpcis %r5, 0 + + /* + * At this point, r5 should equal r4 + 2*4 + * return 0 if they're equal. + */ + addi %r4, %r4, 8 + + sub %r3, %r4, %r5 + + addi %r1, %r1, 32 + ld %r0, 16(%r1) + mtlr %r0 + + blr + +/* Test addpcis with an immediate operand of 0xFFFF (max) */ +.global test_addpcis_2 +test_addpcis_2: + mflr %r0 + std %r0, 16(%r1) + stdu %r1, -32(%r1) + + /* get address of 1 */ + bl 1f + 1: mflr %r4 + addpcis %r5, 0xFFFF + + /* + * Add 8 to r4 to bring it in line with addpcis' NIA. + * Then add 0xFFFF shifted and compare. + */ + addi %r4, %r4, 8 + addis %r4, %r4, 0xFFFF + + sub %r3, %r4, %r5 + + addi %r1, %r1, 32 + ld %r0, 16(%r1) + mtlr %r0 + + blr + diff --git a/tests/misc/misc.c b/tests/misc/misc.c new file mode 100644 index 0000000..0b9079c --- /dev/null +++ b/tests/misc/misc.c @@ -0,0 +1,44 @@ +#include +#include +#include + +#include "console.h" + +#define TEST "Test " +#define PASS "PASS\n" +#define FAIL "FAIL\n" + +extern long test_addpcis_1(void); +extern long test_addpcis_2(void); + +// i < 100 +void print_test_number(int i) +{ + puts(TEST); + putchar(48 + i/10); + putchar(48 + i%10); + putchar(':'); +} + +int main(void) +{ + int fail = 0; + + potato_uart_init(); + + print_test_number(1); + if (test_addpcis_1() != 0) { + fail = 1; + puts(FAIL); + } else + puts(PASS); + + print_test_number(2); + if (test_addpcis_2() != 0) { + fail = 1; + puts(FAIL); + } else + puts(PASS); + + return fail; +} diff --git a/tests/misc/powerpc.lds b/tests/misc/powerpc.lds new file mode 100644 index 0000000..0b65470 --- /dev/null +++ b/tests/misc/powerpc.lds @@ -0,0 +1,13 @@ +SECTIONS +{ + _start = .; + . = 0; + .head : { + KEEP(*(.head)) + } + . = 0x1000; + .text : { *(.text) } + . = 0x2000; + .data : { *(.data) } + .bss : { *(.bss) } +} diff --git a/tests/test_misc.bin b/tests/test_misc.bin new file mode 100755 index 0000000..a32d52c Binary files /dev/null and b/tests/test_misc.bin differ diff --git a/tests/test_misc.console_out b/tests/test_misc.console_out new file mode 100644 index 0000000..9b718c5 --- /dev/null +++ b/tests/test_misc.console_out @@ -0,0 +1,2 @@ +Test 01:PASS +Test 02:PASS diff --git a/tests/update_console_tests b/tests/update_console_tests index d8fb44e..57ac0b0 100755 --- a/tests/update_console_tests +++ b/tests/update_console_tests @@ -3,7 +3,7 @@ # Script to update console related tests from source # -for i in sc illegal decrementer xics privileged mmu ; do +for i in sc illegal decrementer xics privileged mmu misc ; do cd $i make cd -