diff --git a/mips/mips_codegen.h b/mips/mips_codegen.h index 671586e..36f6e27 100644 --- a/mips/mips_codegen.h +++ b/mips/mips_codegen.h @@ -19,38 +19,38 @@ typedef enum { - mips_reg_zero, - mips_reg_at, - mips_reg_v0, - mips_reg_v1, - mips_reg_a0, - mips_reg_a1, - mips_reg_a2, - mips_reg_a3, - mips_reg_t0, - mips_reg_t1, - mips_reg_t2, - mips_reg_t3, - mips_reg_t4, - mips_reg_t5, - mips_reg_t6, - mips_reg_t7, - mips_reg_s0, - mips_reg_s1, - mips_reg_s2, - mips_reg_s3, - mips_reg_s4, - mips_reg_s5, - mips_reg_s6, - mips_reg_s7, - mips_reg_t8, - mips_reg_t9, - mips_reg_k0, - mips_reg_k1, - mips_reg_gp, - mips_reg_sp, - mips_reg_fp, - mips_reg_ra + mips_reg_zero = 0, + mips_reg_at = 1, + mips_reg_v0 = 2, + mips_reg_v1 = 3, + mips_reg_a0 = 4, + mips_reg_a1 = 5, + mips_reg_a2 = 6, + mips_reg_a3 = 7, + mips_reg_t0 = 8, + mips_reg_t1 = 9, + mips_reg_t2 = 10, + mips_reg_t3 = 11, + mips_reg_t4 = 12, + mips_reg_t5 = 13, + mips_reg_t6 = 14, + mips_reg_t7 = 15, + mips_reg_s0 = 16, + mips_reg_s1 = 17, + mips_reg_s2 = 18, + mips_reg_s3 = 19, + mips_reg_s4 = 20, + mips_reg_s5 = 21, + mips_reg_s6 = 22, + mips_reg_s7 = 23, + mips_reg_t8 = 24, + mips_reg_t9 = 25, + mips_reg_k0 = 26, + mips_reg_k1 = 27, + mips_reg_gp = 28, + mips_reg_sp = 29, + mips_reg_fp = 30, + mips_reg_ra = 31 } mips_reg_number; typedef enum @@ -216,12 +216,6 @@ typedef enum #define mips_emit_xor(rd, rs, rt) \ mips_emit_special(xor, rs, rt, rd, 0) \ -#define mips_emit_add(rd, rs, rt) \ - mips_emit_special(and, rs, rt, rd, 0) \ - -#define mips_emit_sub(rd, rs, rt) \ - mips_emit_special(sub, rs, rt, rd, 0) \ - #define mips_emit_and(rd, rs, rt) \ mips_emit_special(and, rs, rt, rd, 0) \ @@ -359,10 +353,10 @@ typedef enum #define mips_emit_ins(rt, rs, pos, size) \ mips_emit_special3(ins, rs, rt, (pos + size - 1), pos) \ -#define mips_emit_seb(rt, rd) \ +#define mips_emit_seb(rd, rt) \ mips_emit_special3(bshfl, 0, rt, rd, mips_bshfl_seb) \ -#define mips_emit_seh(rt, rd) \ +#define mips_emit_seh(rd, rt) \ mips_emit_special3(bshfl, 0, rt, rd, mips_bshfl_seh) \ @@ -407,6 +401,6 @@ typedef enum mips_emit_regimm(bltz, rs, offset) \ #define mips_emit_nop() \ - mips_emit_sll(reg_zero, reg_zero, 0) \ + mips_emit_sll(mips_reg_zero, mips_reg_zero, 0) \ diff --git a/mips/mips_emit.h b/mips/mips_emit.h index b98a0d8..585edac 100644 --- a/mips/mips_emit.h +++ b/mips/mips_emit.h @@ -1904,8 +1904,8 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 address) #define extract_bits(rt, rs, pos, size) \ mips_emit_ext(rt, rs, pos, size) // Extends signed byte to u32 - #define extend_byte_signed(rt, rs) \ - mips_emit_seb(rt, rs) + #define extend_byte_signed(rd, rs) \ + mips_emit_seb(rd, rs) // Rotates a word using a temp reg if necessary #define rotate_right(rdest, rsrc, rtemp, amount) \ mips_emit_rotr(rdest, rsrc, amount); @@ -1933,9 +1933,9 @@ u32 execute_store_cpsr_body(u32 _cpsr, u32 address) mips_emit_sll(rt, rs, 32 - ((pos) + (size))); \ mips_emit_srl(rt, rt, 32 - (size)) // Extends signed byte to u32 - #define extend_byte_signed(rt, rs) \ - mips_emit_sll(rt, rs, 24); \ - mips_emit_sra(rt, rt, 24) + #define extend_byte_signed(rd, rs) \ + mips_emit_sll(rd, rs, 24); \ + mips_emit_sra(rd, rd, 24) // Rotates a word (uses temp reg) #define rotate_right(rdest, rsrc, rtemp, amount) \ mips_emit_sll(rtemp, rsrc, 32 - (amount)); \ diff --git a/tests/Makefile b/tests/Makefile index 20a92d9..fa790fb 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -1,5 +1,6 @@ ARMV8PFX=/opt/buildroot-armv8el-uclibc/bin/aarch64-buildroot-linux-uclibc +MIPS32PFX=/opt/buildroot-mipsel32-o32-uclibc/bin/mipsel-buildroot-linux-uclibc all: gcc -o arm64gen arm64gen.c -ggdb -I../arm/ @@ -8,5 +9,11 @@ all: $(ARMV8PFX)-objcopy -O binary bytecoderef.o bytecoderef.bin @ cmp bytecoderef.bin bytecode.bin || echo "Bytecode mismatch" @ cmp bytecoderef.bin bytecode.bin && echo "Test passed!" + gcc -o mipsgen mipsgen.c -ggdb -I../mips/ + ./mipsgen > bytecode.bin + $(MIPS32PFX)-as -EL -o bytecoderef.o mipsgen.S + $(MIPS32PFX)-objcopy -j .text -O binary bytecoderef.o bytecoderef.bin + @ cmp bytecoderef.bin bytecode.bin || echo "Bytecode mismatch" + @ cmp bytecoderef.bin bytecode.bin && echo "Test passed!" diff --git a/tests/mipsgen.S b/tests/mipsgen.S new file mode 100644 index 0000000..8a8d716 --- /dev/null +++ b/tests/mipsgen.S @@ -0,0 +1,180 @@ + +.set mips32r2 +.set noreorder + +.text + +nop +nop + +# Generic MIPS insts +addu $4, $5, $6 +addu $29, $31, $20 +subu $4, $5, $6 +subu $29, $31, $20 +xor $4, $5, $6 +xor $29, $31, $20 +and $4, $5, $6 +and $29, $31, $20 +or $4, $5, $6 +or $29, $31, $20 +nor $4, $5, $6 +nor $29, $31, $20 + +slt $4, $5, $6 +slt $29, $31, $20 +sltu $4, $5, $6 +sltu $29, $31, $20 + +sllv $4, $5, $6 +sllv $29, $31, $20 +srlv $4, $5, $6 +srlv $29, $31, $20 +srav $4, $5, $6 +srav $29, $31, $20 +rotrv $4, $5, $6 +rotrv $29, $31, $20 + +sll $4, $5, 0 +srl $4, $5, 0 +sra $4, $5, 0 +rotr $4, $5, 0 +sll $4, $5, 1 +srl $4, $5, 1 +sra $4, $5, 1 +rotr $4, $5, 1 +sll $4, $5, 30 +srl $4, $5, 30 +sra $4, $5, 30 +rotr $4, $5, 30 +sll $4, $5, 31 +srl $4, $5, 31 +sra $4, $5, 31 +rotr $4, $5, 31 + +lui $4, 0xFFFF +lui $4, 0x8000 +lui $4, 0 +lui $4, 1 + +addiu $4, $22, -1 +xori $4, $22, 0xFFFF +ori $4, $22, 0xFFFF +andi $4, $22, 0xFFFF +slti $4, $22, -1 +sltiu $4, $22, -1 +addiu $4, $22, 0 +xori $4, $22, 0 +ori $4, $22, 0 +andi $4, $22, 0 +slti $4, $22, 0 +sltiu $4, $22, 0 +addiu $4, $22, 1 +xori $4, $22, 1 +ori $4, $22, 1 +andi $4, $22, 1 +slti $4, $22, 1 +sltiu $4, $22, 1 +addiu $4, $22, 0x8000 +xori $4, $22, 0x8000 +ori $4, $22, 0x8000 +andi $4, $22, 0x8000 +slti $4, $22, 0x8000 +sltiu $4, $22, 0x8000 +addiu $4, $22, 0x7FFF +xori $4, $22, 0x7FFF +ori $4, $22, 0x7FFF +andi $4, $22, 0x7FFF +slti $4, $22, 0x7FFF +sltiu $4, $22, 0x7FFF + +mflo $7 +mflo $30 +mfhi $7 +mfhi $30 +mtlo $7 +mtlo $30 +mthi $7 +mthi $30 + +mult $6, $7 +mult $18, $20 +multu $6, $7 +multu $18, $20 +div $0, $6, $7 +div $0, $18, $20 +divu $0, $6, $7 +divu $0, $18, $20 + +jr $5 +jr $31 +jalr $5 +jalr $20 + +bltzal $4, 1f +bltzal $20, 1f +bgezal $4, 1f +bgezal $20, 1f +bltz $4, 1f +bltz $20, 1f +1: + +lb $4, ($5) +lbu $4, ($5) +lh $4, ($5) +lhu $4, ($5) +lw $4, ($5) +lb $4, 1($5) +lbu $4, 1($5) +lh $4, 1($5) +lhu $4, 1($5) +lw $4, 1($5) +lb $4, -1($5) +lbu $4, -1($5) +lh $4, -1($5) +lhu $4, -1($5) +lw $4, -1($5) +lb $4, 0x7FFF($5) +lbu $4, 0x7FFF($5) +lh $4, 0x7FFF($5) +lhu $4, 0x7FFF($5) +lw $4, 0x7FFF($5) +lb $4, -0x8000($5) +lbu $4, -0x8000($5) +lh $4, -0x8000($5) +lhu $4, -0x8000($5) +lw $4, -0x8000($5) + +sb $4, ($5) +sh $4, ($5) +sw $4, ($5) +sb $4, 1($5) +sh $4, 1($5) +sw $4, 1($5) +sb $4, -1($5) +sh $4, -1($5) +sw $4, -1($5) +sb $4, 0x7FFF($5) +sh $4, 0x7FFF($5) +sw $4, 0x7FFF($5) +sb $4, -0x8000($5) +sh $4, -0x8000($5) +sw $4, -0x8000($5) + +# MIPS32r2/PSP instructions + +ext $2, $5, 20, 4 +ext $15, $20, 3, 9 +ins $2, $5, 20, 4 +ins $15, $20, 3, 9 + +seb $7, $9 +seh $7, $9 + +# PSP specific stuff +# max $4, $28, $15 +# min $4, $28, $15 +# movz $4, $5, $6 +# movn $4, $5, $6 + + diff --git a/tests/mipsgen.c b/tests/mipsgen.c new file mode 100644 index 0000000..b7ab3f8 --- /dev/null +++ b/tests/mipsgen.c @@ -0,0 +1,121 @@ + +#define u32 uint32_t +#define u8 uint8_t + +#include +#include +#include "mips_codegen.h" + +int main() { + u32 buffer[1024]; + u8 *translation_ptr = (u8*)&buffer[0]; + + mips_emit_nop(); + mips_emit_nop(); + + mips_emit_addu(mips_reg_a0, mips_reg_a1, mips_reg_a2); + mips_emit_addu(mips_reg_sp, mips_reg_ra, mips_reg_s4); + mips_emit_subu(mips_reg_a0, mips_reg_a1, mips_reg_a2); + mips_emit_subu(mips_reg_sp, mips_reg_ra, mips_reg_s4); + mips_emit_xor(mips_reg_a0, mips_reg_a1, mips_reg_a2); + mips_emit_xor(mips_reg_sp, mips_reg_ra, mips_reg_s4); + mips_emit_and(mips_reg_a0, mips_reg_a1, mips_reg_a2); + mips_emit_and(mips_reg_sp, mips_reg_ra, mips_reg_s4); + mips_emit_or(mips_reg_a0, mips_reg_a1, mips_reg_a2); + mips_emit_or(mips_reg_sp, mips_reg_ra, mips_reg_s4); + mips_emit_nor(mips_reg_a0, mips_reg_a1, mips_reg_a2); + mips_emit_nor(mips_reg_sp, mips_reg_ra, mips_reg_s4); + + mips_emit_slt(mips_reg_a0, mips_reg_a1, mips_reg_a2); + mips_emit_slt(mips_reg_sp, mips_reg_ra, mips_reg_s4); + mips_emit_sltu(mips_reg_a0, mips_reg_a1, mips_reg_a2); + mips_emit_sltu(mips_reg_sp, mips_reg_ra, mips_reg_s4); + + mips_emit_sllv(mips_reg_a0, mips_reg_a1, mips_reg_a2); + mips_emit_sllv(mips_reg_sp, mips_reg_ra, mips_reg_s4); + mips_emit_srlv(mips_reg_a0, mips_reg_a1, mips_reg_a2); + mips_emit_srlv(mips_reg_sp, mips_reg_ra, mips_reg_s4); + mips_emit_srav(mips_reg_a0, mips_reg_a1, mips_reg_a2); + mips_emit_srav(mips_reg_sp, mips_reg_ra, mips_reg_s4); + mips_emit_rotrv(mips_reg_a0, mips_reg_a1, mips_reg_a2); + mips_emit_rotrv(mips_reg_sp, mips_reg_ra, mips_reg_s4); + + for (unsigned i = 0; i < 4; i++) { + mips_emit_sll(mips_reg_a0, mips_reg_a1, (i & 1) + (i >> 1) * 30); + mips_emit_srl(mips_reg_a0, mips_reg_a1, (i & 1) + (i >> 1) * 30); + mips_emit_sra(mips_reg_a0, mips_reg_a1, (i & 1) + (i >> 1) * 30); + mips_emit_rotr(mips_reg_a0, mips_reg_a1, (i & 1) + (i >> 1) * 30); + } + + mips_emit_lui(mips_reg_a0, 0xFFFF); + mips_emit_lui(mips_reg_a0, 0x8000); + mips_emit_lui(mips_reg_a0, 0); + mips_emit_lui(mips_reg_a0, 1); + + const int imm[] = {-1, 0, 1, 0x8000, 0x7FFF}; + for (unsigned i = 0; i < 5; i++) { + mips_emit_addiu(mips_reg_a0, mips_reg_s6, imm[i]); + mips_emit_xori(mips_reg_a0, mips_reg_s6, imm[i]); + mips_emit_ori(mips_reg_a0, mips_reg_s6, imm[i]); + mips_emit_andi(mips_reg_a0, mips_reg_s6, imm[i]); + mips_emit_slti(mips_reg_a0, mips_reg_s6, imm[i]); + mips_emit_sltiu(mips_reg_a0, mips_reg_s6, imm[i]); + } + + mips_emit_mflo(mips_reg_a3); + mips_emit_mflo(mips_reg_fp); + mips_emit_mfhi(mips_reg_a3); + mips_emit_mfhi(mips_reg_fp); + mips_emit_mtlo(mips_reg_a3); + mips_emit_mtlo(mips_reg_fp); + mips_emit_mthi(mips_reg_a3); + mips_emit_mthi(mips_reg_fp); + + mips_emit_mult(mips_reg_a2, mips_reg_a3); + mips_emit_mult(mips_reg_s2, mips_reg_s4); + mips_emit_multu(mips_reg_a2, mips_reg_a3); + mips_emit_multu(mips_reg_s2, mips_reg_s4); + mips_emit_div(mips_reg_a2, mips_reg_a3); + mips_emit_div(mips_reg_s2, mips_reg_s4); + mips_emit_divu(mips_reg_a2, mips_reg_a3); + mips_emit_divu(mips_reg_s2, mips_reg_s4); + + mips_emit_jr(mips_reg_a1); + mips_emit_jr(mips_reg_ra); + mips_emit_jalr(mips_reg_a1); + mips_emit_jalr(mips_reg_s4); + + mips_emit_bltzal(mips_reg_a0, 5); + mips_emit_bltzal(mips_reg_s4, 4); + mips_emit_bgezal(mips_reg_a0, 3); + mips_emit_bgezal(mips_reg_s4, 2); + mips_emit_bltz(mips_reg_a0, 1); + mips_emit_bltz(mips_reg_s4, 0); + + const int off[] = {0, 1, -1, 0x7FFF, -0x8000}; + for (unsigned i = 0; i < 5; i++) { + mips_emit_lb(mips_reg_a0, mips_reg_a1, off[i]); + mips_emit_lbu(mips_reg_a0, mips_reg_a1, off[i]); + mips_emit_lh(mips_reg_a0, mips_reg_a1, off[i]); + mips_emit_lhu(mips_reg_a0, mips_reg_a1, off[i]); + mips_emit_lw(mips_reg_a0, mips_reg_a1, off[i]); + } + for (unsigned i = 0; i < 5; i++) { + mips_emit_sb(mips_reg_a0, mips_reg_a1, off[i]); + mips_emit_sh(mips_reg_a0, mips_reg_a1, off[i]); + mips_emit_sw(mips_reg_a0, mips_reg_a1, off[i]); + } + + // MIPS32r2/PSP instructions + mips_emit_ext(mips_reg_v0, mips_reg_a1, 20, 4); + mips_emit_ext(mips_reg_t7, mips_reg_s4, 3, 9); + mips_emit_ins(mips_reg_v0, mips_reg_a1, 20, 4); + mips_emit_ins(mips_reg_t7, mips_reg_s4, 3, 9); + + mips_emit_seb(mips_reg_a3, mips_reg_t1); + mips_emit_seh(mips_reg_a3, mips_reg_t1); + + fwrite(buffer, 1, translation_ptr-(u8*)buffer, stdout); +} + +