From 37a4e740133f8e4d669cafc8468dd13107a4810a Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Mon, 21 Oct 2024 12:27:18 -0400 Subject: [PATCH] save dev state --- include/mips32r6.h | 338 ++++++++++++++++++-- lib/mips32r6.c | 673 ++++++++++++++++++++++++++++++++++++---- masm/gen.c | 661 +-------------------------------------- masm/gen.h | 93 ++++-- masm/gen/grammer.c | 643 ++++++++++++++++++++++++++++++++++++++ masm/gen/log.c | 28 ++ masm/gen/section.c | 156 ++++++++++ masm/{ => tab}/reftab.c | 2 +- masm/{ => tab}/symtab.c | 3 +- 9 files changed, 1834 insertions(+), 763 deletions(-) create mode 100644 masm/gen/grammer.c create mode 100644 masm/gen/log.c create mode 100644 masm/gen/section.c rename masm/{ => tab}/reftab.c (97%) rename masm/{ => tab}/symtab.c (98%) diff --git a/include/mips32r6.h b/include/mips32r6.h index 88eda4d..c6c1d59 100644 --- a/include/mips32r6.h +++ b/include/mips32r6.h @@ -7,6 +7,97 @@ #include #include +// TODO: +// balc + +// TODO: [add] +// align +// aluipc +// aui +// auipc +// bal real ins +// balc +// bc +// bc1eqz +// bc1nez +// bc2eqz +// bc2nez +// b{le,ge,gt,lt,eq,ne}ZALC +// bc +// bitswap +// bovc +// bnvc +// crc32{b,h,w} +// c2c32c{b,h,w} +// div, mod, divu, modu +// dvp +// eretnc +// evp +// gnvi +// ginvt +// jialc +// jic +// jr assembly idiom +// llwp +// llwpe +// lsa +// lwpc +// mfhc0 +// mthc0 +// mul muh mulu muhu +// nal +// scwp +// scwpe +// seleqz selnez +// sigrie + +// TODO: [remove] +// bc1f +// bc1fl +// bc1tl +// bc1tl +// bc2f +// bc2fl +// bc2t +// bc2tl +// all branch likely +// div +// divu +// jr +// ldxc1 +// lui +// luxc1 +// lwl +// lwr +// lwxc1 +// madd +// maddu +// mfhi +// mflo +// movf +// movn +// movt +// movz +// msub +// msubu +// mthi +// mtlo +// mul +// mult +// multu +// prefx +// sdxc1 +// suxc1 +// swl +// swr +// swxc1 +// teqi +// tgei +// tgeiu +// tlti +// tltiu +// tnei + /* mips instructions */ enum mips32r6_instruction_type { MIPS32R6_INS_ADD, @@ -15,39 +106,110 @@ enum mips32r6_instruction_type { MIPS32R6_INS_ADDU, MIPS32R6_INS_AND, MIPS32R6_INS_ANDI, - MIPS32R6_INS_BAL, - MIPS32R6_INS_BALC, - MIPS32R6_INS_BC, + MIPS32R6_INS_BC1F, + MIPS32R6_INS_BC1FL, + MIPS32R6_INS_BC1T, + MIPS32R6_INS_BC1TL, + MIPS32R6_INS_BC2F, + MIPS32R6_INS_BC2FL, + MIPS32R6_INS_BC2T, + MIPS32R6_INS_BC2TL, MIPS32R6_INS_BEQ, + MIPS32R6_INS_BEQL, MIPS32R6_INS_BGEZ, MIPS32R6_INS_BGEZAL, + MIPS32R6_INS_BGEZALL, + MIPS32R6_INS_BGEZL, MIPS32R6_INS_BGTZ, + MIPS32R6_INS_BGTZL, MIPS32R6_INS_BLEZ, + MIPS32R6_INS_BLEZL, MIPS32R6_INS_BLTZ, MIPS32R6_INS_BLTZAL, + MIPS32R6_INS_BLTZALL, + MIPS32R6_INS_BLTZL, MIPS32R6_INS_BNE, + MIPS32R6_INS_BNEL, + MIPS32R6_INS_BREAK, + MIPS32R6_INS_CACHE, + MIPS32R6_INS_CFC1, + MIPS32R6_INS_CFC2, + MIPS32R6_INS_CLO, + MIPS32R6_INS_CLZ, + MIPS32R6_INS_COP2, + MIPS32R6_INS_CTC1, + MIPS32R6_INS_CTC2, + MIPS32R6_INS_DERET, + MIPS32R6_INS_DI, MIPS32R6_INS_DIV, - MIPS32R6_INS_MOD, MIPS32R6_INS_DIVU, - MIPS32R6_INS_MODU, + MIPS32R6_INS_EI, + MIPS32R6_INS_ERET, + MIPS32R6_INS_EXT, + MIPS32R6_INS_INS, MIPS32R6_INS_J, MIPS32R6_INS_JAL, MIPS32R6_INS_JALR, - MIPS32R6_INS_JALX, MIPS32R6_INS_JR, MIPS32R6_INS_LB, MIPS32R6_INS_LBU, + MIPS32R6_INS_LDC1, + MIPS32R6_INS_LDC2, + MIPS32R6_INS_LDXC1, MIPS32R6_INS_LH, MIPS32R6_INS_LHU, + MIPS32R6_INS_LL, MIPS32R6_INS_LUI, + MIPS32R6_INS_LUXC1, MIPS32R6_INS_LW, + MIPS32R6_INS_LWC1, + MIPS32R6_INS_LWC2, + MIPS32R6_INS_LWL, + MIPS32R6_INS_LWR, + MIPS32R6_INS_LWXC1, + MIPS32R6_INS_MADD, + MIPS32R6_INS_MADDU, + MIPS32R6_INS_MFC0, + MIPS32R6_INS_MFC1, + MIPS32R6_INS_MFC2, + MIPS32R6_INS_MFHC1, + MIPS32R6_INS_MFHC2, + MIPS32R6_INS_MFHI, + MIPS32R6_INS_MFLO, + MIPS32R6_INS_MOVF, + MIPS32R6_INS_MOVN, + MIPS32R6_INS_MOVT, + MIPS32R6_INS_MOVZ, + MIPS32R6_INS_MSUB, + MIPS32R6_INS_MSUBU, + MIPS32R6_INS_MTC0, + MIPS32R6_INS_MTC1, + MIPS32R6_INS_MTC2, + MIPS32R6_INS_MTHC1, + MIPS32R6_INS_MTHC2, + MIPS32R6_INS_MTHI, + MIPS32R6_INS_MTLO, MIPS32R6_INS_MUL, - MIPS32R6_INS_MUH, - MIPS32R6_INS_MULU, - MIPS32R6_INS_MUHU, + MIPS32R6_INS_MULT, + MIPS32R6_INS_MULTU, + MIPS32R6_INS_NOR, + MIPS32R6_INS_OR, + MIPS32R6_INS_ORI, + MIPS32R6_INS_PREF, + MIPS32R6_INS_PREFX, + MIPS32R6_INS_RDHWR, + MIPS32R6_INS_RDPGPR, + MIPS32R6_INS_ROTR, + MIPS32R6_INS_ROTRV, MIPS32R6_INS_SB, + MIPS32R6_INS_SC, + MIPS32R6_INS_SDBBP, + MIPS32R6_INS_SDC1, + MIPS32R6_INS_SDC2, + MIPS32R6_INS_SDXC1, + MIPS32R6_INS_SEB, + MIPS32R6_INS_SEH, MIPS32R6_INS_SH, - MIPS32R6_INS_SW, MIPS32R6_INS_SLL, MIPS32R6_INS_SLLV, MIPS32R6_INS_SLT, @@ -60,21 +222,54 @@ enum mips32r6_instruction_type { MIPS32R6_INS_SRLV, MIPS32R6_INS_SUB, MIPS32R6_INS_SUBU, + MIPS32R6_INS_SUXC1, + MIPS32R6_INS_SW, + MIPS32R6_INS_SWC1, + MIPS32R6_INS_SWC2, + MIPS32R6_INS_SWL, + MIPS32R6_INS_SWR, + MIPS32R6_INS_SWXC1, + MIPS32R6_INS_SYNC, + MIPS32R6_INS_SYNCI, MIPS32R6_INS_SYSCALL, - MIPS32R6_INS_OR, - MIPS32R6_INS_ORI, - MIPS32R6_INS_NOR, + MIPS32R6_INS_TEQ, + MIPS32R6_INS_TEQI, + MIPS32R6_INS_TGE, + MIPS32R6_INS_TGEI, + MIPS32R6_INS_TGEIU, + MIPS32R6_INS_TGEU, + MIPS32R6_INS_TLBP, + MIPS32R6_INS_TLBR, + MIPS32R6_INS_TLBWI, + MIPS32R6_INS_TLBWR, + MIPS32R6_INS_TLT, + MIPS32R6_INS_TLTI, + MIPS32R6_INS_TLTIU, + MIPS32R6_INS_TLTU, + MIPS32R6_INS_TNE, + MIPS32R6_INS_TNEI, + MIPS32R6_INS_WAIT, + MIPS32R6_INS_WRPGPR, + MIPS32R6_INS_WSBH, MIPS32R6_INS_XOR, MIPS32R6_INS_XORI, __MIPS32R6_INS_NULL, }; +// op code groups #define MIPS32R6_OP_SPECIAL 0b000000 +#define MIPS32R6_OP_SPECIAL2 0b011100 +#define MIPS32R6_OP_SPECIAL3 0b011111 +#define MIPS32R6_OP_REGIMM 0b000001 +#define MIPS32R6_OP_COP0 0b010000 +#define MIPS32R6_OP_COP1 0b010001 +#define MIPS32R6_OP_COP2 0b010010 +#define MIPS32R6_OP_COP1X 0b010011 + +// op codes #define MIPS32R6_OP_ADDI 0b001000 #define MIPS32R6_OP_ADDIU 0b001001 #define MIPS32R6_OP_ANDI 0b001100 -#define MIPS32R6_OP_REGIMM 0b000001 -#define MIPS32R6_OP_BALC 0b111010 #define MIPS32R6_OP_BC 0b110010 #define MIPS32R6_OP_BEQ 0b000100 #define MIPS32R6_OP_BEQL 0b010100 @@ -84,36 +279,59 @@ enum mips32r6_instruction_type { #define MIPS32R6_OP_BLEZL 0b010110 #define MIPS32R6_OP_BNE 0b000101 #define MIPS32R6_OP_BNEL 0b010101 +#define MIPS32R6_OP_CACHE 0b101111 #define MIPS32R6_OP_J 0b000010 #define MIPS32R6_OP_JAL 0b000011 #define MIPS32R6_OP_JALX 0b011101 #define MIPS32R6_OP_LB 0b100000 #define MIPS32R6_OP_LBU 0b100100 +#define MIPS32R6_OP_LDC1 0b110101 +#define MIPS32R6_OP_LDC2 0b110110 #define MIPS32R6_OP_LH 0b100001 #define MIPS32R6_OP_LHU 0b100101 +#define MIPS32R6_OP_LL 0b110000 #define MIPS32R6_OP_LUI 0b001111 #define MIPS32R6_OP_LW 0b100011 +#define MIPS32R6_OP_LWC1 0b110001 +#define MIPS32R6_OP_LWC2 0b110010 +#define MIPS32R6_OP_LWL 0b100010 +#define MIPS32R6_OP_LWR 0b100110 +#define MIPS32R6_OP_ORI 0b001101 +#define MIPS32R6_OP_PREF 0b110011 #define MIPS32R6_OP_SB 0b101000 +#define MIPS32R6_OP_SC 0b111000 +#define MIPS32R6_OP_SDC1 0b111101 +#define MIPS32R6_OP_SDC2 0b111110 #define MIPS32R6_OP_SH 0b101001 -#define MIPS32R6_OP_SW 0b101011 #define MIPS32R6_OP_SLTI 0b001010 #define MIPS32R6_OP_SLTIU 0b001011 -#define MIPS32R6_OP_ORI 0b001101 +#define MIPS32R6_OP_SW 0b101011 +#define MIPS32R6_OP_SWC1 0b111001 +#define MIPS32R6_OP_SWC2 0b111010 +#define MIPS32R6_OP_SWL 0b101010 +#define MIPS32R6_OP_SWR 0b101110 #define MIPS32R6_OP_XORI 0b001110 +// op special #define MIPS32R6_FUNCT_ADD 0b100000 #define MIPS32R6_FUNCT_ADDU 0b100001 #define MIPS32R6_FUNCT_AND 0b100100 -#define MIPS32R6_FUNCT_SOP32 0b011010 -#define MIPS32R6_FUNCT_SOP33 0b011011 +#define MIPS32R6_FUNCT_BREAK 0b001101 +#define MIPS32R6_FUNCT_DIV 0b000011 +#define MIPS32R6_FUNCT_DIVU 0b011011 #define MIPS32R6_FUNCT_JALR 0b001001 #define MIPS32R6_FUNCT_JR 0b001000 #define MIPS32R6_FUNCT_MFHI 0b010000 #define MIPS32R6_FUNCT_MFLO 0b010010 +#define MIPS32R6_FUNCT_MOVCL 0b000001 +#define MIPS32R6_FUNCT_MOVN 0b001011 +#define MIPS32R6_FUNCT_MOVZ 0b001010 #define MIPS32R6_FUNCT_MTHI 0b010001 #define MIPS32R6_FUNCT_MTLO 0b010011 -#define MIPS32R6_FUNCT_SOP30 0b011000 -#define MIPS32R6_FUNCT_SOP31 0b011001 +#define MIPS32R6_FUNCT_MULT 0b011000 +#define MIPS32R6_FUNCT_MULTU 0b011001 +#define MIPS32R6_FUNCT_NOR 0b100111 +#define MIPS32R6_FUNCT_OR 0b100101 #define MIPS32R6_FUNCT_SLL 0b000000 #define MIPS32R6_FUNCT_SLLV 0b000100 #define MIPS32R6_FUNCT_SLT 0b101010 @@ -124,12 +342,38 @@ enum mips32r6_instruction_type { #define MIPS32R6_FUNCT_SRLV 0b000110 #define MIPS32R6_FUNCT_SUB 0b100010 #define MIPS32R6_FUNCT_SUBU 0b100011 +#define MIPS32R6_FUNCT_SYNC 0b001111 #define MIPS32R6_FUNCT_SYSCALL 0b001100 -#define MIPS32R6_FUNCT_OR 0b100101 -#define MIPS32R6_FUNCT_NOR 0b100111 +#define MIPS32R6_FUNCT_TEQ 0b110100 +#define MIPS32R6_FUNCT_TGE 0b110000 +#define MIPS32R6_FUNCT_TGEU 0b110001 +#define MIPS32R6_FUNCT_TLT 0b110010 +#define MIPS32R6_FUNCT_TLTU 0b110011 +#define MIPS32R6_FUNCT_TNE 0b110110 #define MIPS32R6_FUNCT_XOR 0b100110 -#define MIPS32R6_FUNCT_BAL 0b10001 +// op special2 +#define MIPS32R6_FUNCT_CLO 0b100001 +#define MIPS32R6_FUNCT_CLZ 0b100000 +#define MIPS32R6_FUNCT_MADD 0b000000 +#define MIPS32R6_FUNCT_MADDU 0b000001 +#define MIPS32R6_FUNCT_MSUB 0b000100 +#define MIPS32R6_FUNCT_MSUBU 0b000101 +#define MIPS32R6_FUNCT_MUL 0b000010 +#define MIPS32R6_FUNCT_SDBBP 0b111111 + +// op special 3 +#define MIPS32R6_FUNCT_EXT 0b000000 +#define MIPS32R6_FUNCT_INS 0b000100 +#define MIPS32R6_FUNCT_RDHWR 0b111011 +#define MIPS32R6_FUNCT_BSHFL 0b100000 + +// op bshfl +#define MIPS32R6_FUNCT_SEB 0b10000 +#define MIPS32R6_FUNCT_SEH 0b11000 +#define MIPS32R6_FUNCT_WSBH 0b00010 + +// op regimm #define MIPS32R6_FUNCT_BGEZ 0b00001 #define MIPS32R6_FUNCT_BGEZAL 0b10001 #define MIPS32R6_FUNCT_BGEZALL 0b10011 @@ -138,18 +382,46 @@ enum mips32r6_instruction_type { #define MIPS32R6_FUNCT_BLTZAL 0b10000 #define MIPS32R6_FUNCT_BLTZALL 0b10010 #define MIPS32R6_FUNCT_BLTZL 0b00010 +#define MIPS32R6_FUNCT_SYNCI 0b11111 +#define MIPS32R6_FUNCT_TEQI 0b01100 +#define MIPS32R6_FUNCT_TGEI 0b01000 +#define MIPS32R6_FUNCT_TGEIU 0b01001 +#define MIPS32R6_FUNCT_TLTI 0b01010 +#define MIPS32R6_FUNCT_TLTIU 0b01011 +#define MIPS32R6_FUNCT_TNEI 0b01110 -#define MIPS32R6_SOP30_MUL 0b00010 -#define MIPS32R6_SOP30_MUH 0b00011 -#define MIPS32R6_SOP31_MULU 0b00010 -#define MIPS32R6_SOP31_MUHU 0b00011 -#define MIPS32R6_SOP32_DIV 0b00010 -#define MIPS32R6_SOP32_MOD 0b00011 -#define MIPS32R6_SOP33_DIVU 0b00010 -#define MIPS32R6_SOP33_MODU 0b00011 +// op cop cfunct +#define MIPS32R6_FUNCT_BC 0b01000 +#define MIPS32R6_FUNCT_CF 0b00010 +#define MIPS32R6_FUNCT_CT 0b00110 +#define MIPS32R6_FUNCT_MF 0b00000 +#define MIPS32R6_FUNCT_MFH 0b00011 +#define MIPS32R6_FUNCT_MT 0b00100 +#define MIPS32R6_FUNCT_MTH 0b00111 +#define MIPS32R6_FUNCT_MFMC0 0b01011 +#define MIPS32R6_FUNCT_RDPGPR 0b01010 +#define MIPS32R6_FUNCT_WRPGPR 0b01110 + +// op cop funct +#define MIPS32R6_FUNCT_DERET 0b011111 +#define MIPS32R6_FUNCT_ERET 0b011000 +#define MIPS32R6_FUNCT_TLBP 0b001000 +#define MIPS32R6_FUNCT_TLBR 0b000001 +#define MIPS32R6_FUNCT_TLBWI 0b000010 +#define MIPS32R6_FUNCT_TLBWR 0b000110 + +// op cop1x +#define MIPS32R6_FUNCT_LDXC1 0b000001 +#define MIPS32R6_FUNCT_LUXC1 0b000101 +#define MIPS32R6_FUNCT_LWXC1 0b000000 +#define MIPS32R6_FUNCT_PREFX 0b001111 +#define MIPS32R6_FUNCT_SDXC1 0b001001 +#define MIPS32R6_FUNCT_SUXC1 0b001101 +#define MIPS32R6_FUNCT_SWXC1 0b001000 +#define MIPS32R6_FUNCT_WAIT 0b100000 #define __MIPS32R6_INS_LEN (__MIPS32R6_INS_NULL) -#define __MIPS32R6_PSEUDO_LEN (4) +#define __MIPS32R6_PSEUDO_LEN (38) #define __MIPS32R6_GRAMMER_LEN (__MIPS32R6_INS_LEN + __MIPS32R6_PSEUDO_LEN) extern struct mips32_grammer mips32r6_grammers[__MIPS32R6_GRAMMER_LEN]; diff --git a/lib/mips32r6.c b/lib/mips32r6.c index 1f1fe61..01b028e 100644 --- a/lib/mips32r6.c +++ b/lib/mips32r6.c @@ -24,40 +24,111 @@ struct mips32_grammer mips32r6_grammers[__MIPS32R6_GRAMMER_LEN] = { INS(ADDIU, ITYPE), INS(ADDU, RTYPE), INS(AND, RTYPE), - INS(ADDI, ITYPE), INS(ANDI, ITYPE), - INS(BAL, "offset"), - INS(BALC, "target"), - INS(BC, "target"), + INS(BC1F, "cc,offset"), + INS(BC1FL, "cc,offset"), + INS(BC1T, "cc,offset"), + INS(BC1TL, "cc,offset"), + INS(BC2F, "cc,offset"), + INS(BC2FL, "cc,offset"), + INS(BC2T, "cc,offset"), + INS(BC2TL, "cc,offset"), INS(BEQ, BRANCH), + INS(BEQL, BRANCH), INS(BGEZ, BRANCHZ), INS(BGEZAL, BRANCHZ), + INS(BGEZALL, BRANCHZ), + INS(BGEZL, BRANCHZ), INS(BGTZ, BRANCHZ), + INS(BGTZL, BRANCHZ), INS(BLEZ, BRANCHZ), + INS(BLEZL, BRANCHZ), INS(BLTZ, BRANCHZ), INS(BLTZAL, BRANCHZ), + INS(BLTZALL, BRANCHZ), + INS(BLTZL, BRANCHZ), INS(BNE, BRANCH), + INS(BNEL, BRANCH), + INS(BREAK, "code"), + INS(CACHE, "op,offset(base)"), + INS(CFC1, "rt,fs"), + INS(CFC2, "rt,rd"), + INS(CLO, "rd,rs"), + INS(CLZ, "rd,rs"), + INS(COP2, "func"), + INS(CTC1, "rt,fs"), + INS(CTC2, "rt,rd"), + INS(DERET, ""), + INS(DI, "rt"), INS(DIV, RTYPE), - INS(MOD, RTYPE), INS(DIVU, RTYPE), - INS(MODU, RTYPE), + INS(EI, "rt"), + INS(ERET, ""), + INS(EXT, "rt,rs,pos,size"), + INS(INS, "rt,rs,pos,size"), INS(J, JTYPE), INS(JAL, JTYPE), INS(JALR, "rs"), INS(JR, "rs"), INS(LB, LOAD), INS(LBU, LOAD), + INS(LDC1, "ft,offset(base)"), + INS(LDC2, LOAD), + INS(LDXC1, "fd,index(base)"), INS(LH, LOAD), INS(LHU, LOAD), + INS(LL, LOAD), INS(LUI, "rt,immd"), + INS(LUXC1, "fd,index(base)"), INS(LW, LOAD), + INS(LWC1, "ft,offset(base)"), + INS(LWC2, LOAD), + INS(LWL, LOAD), + INS(LWR, LOAD), + INS(LWXC1, "fd,index(base)"), + INS(MADD, "rs,rt"), + INS(MADDU, "rs,rt"), + INS(MFC0, "rt,rd"), + INS(MFC1, "rt,fs"), + INS(MFC2, "rt,rd"), + INS(MFHC1, "rt,fs"), + INS(MFHC2, "rt,rd"), + INS(MFHI, "rd"), + INS(MFLO, "rd"), + INS(MOVF, "rd,rs,cc"), + INS(MOVN, RTYPE), + INS(MOVT, "rd,rs,cc"), + INS(MOVZ, RTYPE), + INS(MSUB, "rs,rt"), + INS(MSUBU, "rs,rt"), + INS(MTC0, "rt,rd"), + INS(MTC1, "rt,fs"), + INS(MTC2, "rt,rd"), + INS(MTHC1, "rt,fs"), + INS(MTHC2, "rt,rd"), + INS(MTHI, "rs"), + INS(MTLO, "rs"), INS(MUL, RTYPE), - INS(MUH, RTYPE), - INS(MULU, RTYPE), - INS(MUHU, RTYPE), + INS(MULT, "rs,rt"), + INS(MULTU, "rs,rt"), + INS(NOR, RTYPE), + INS(OR, RTYPE), + INS(ORI, ITYPE), + INS(PREF, "hint,offset(base)"), + INS(PREFX, "hint,index(base)"), + INS(RDHWR, "rt,rd"), + INS(RDPGPR, "rd,rt"), + INS(ROTR, SHIFT), + INS(ROTRV, SHIFTV), INS(SB, LOAD), + INS(SC, LOAD), + INS(SDBBP, "code"), + INS(SDC1, "ft,offset(base)"), + INS(SDC2, LOAD), + INS(SDXC1, "fs,index(base)"), + INS(SEB, "rd,rt"), + INS(SEH, "rd,rt"), INS(SH, LOAD), - INS(SW, LOAD), INS(SLL, SHIFT), INS(SLLV, SHIFTV), INS(SLT, RTYPE), @@ -70,19 +141,206 @@ struct mips32_grammer mips32r6_grammers[__MIPS32R6_GRAMMER_LEN] = { INS(SRLV, SHIFT), INS(SUB, RTYPE), INS(SUBU, RTYPE), + INS(SUXC1, "fs,index(base)"), + INS(SW, LOAD), + INS(SWC1, "ft,offset(base)"), + INS(SWC2, LOAD), + INS(SWL, LOAD), + INS(SWR, LOAD), + INS(SWXC1, "fs,index(base)"), + INS(SYNC, ""), + INS(SYNCI, "offest(base)"), INS(SYSCALL, ""), - INS(OR, RTYPE), - INS(ORI, ITYPE), - INS(NOR, RTYPE), + INS(TEQ, "rs,rt"), + INS(TEQI, "rs,immd"), + INS(TGE, "rs,rt"), + INS(TGEI, "rs,immd"), + INS(TGEIU, "rs,immd"), + INS(TGEU, "rs,rt"), + INS(TLBP, ""), + INS(TLBR, ""), + INS(TLBWI, ""), + INS(TLBWR, ""), + INS(TLT, "rs,rt"), + INS(TLTI, "rs,immd"), + INS(TLTIU, "rs,immd"), + INS(TLTU, "rs,rt"), + INS(TNE, "rs,rt"), + INS(TNEI, "rs,immd"), + INS(WAIT, ""), + INS(WRPGPR, "rd,rt"), INS(XOR, RTYPE), INS(XORI, ITYPE), // pseudo instructions + PSEUDO("abs", "rd,rs", 3, { + {MIPS32R6_INS_SRA, "rd=$at,rt=rs,sa=31"}, + {MIPS32R6_INS_ADD, "rd,rs,rt=$at"}, + {MIPS32R6_INS_XOR, "rd,rs=rd,rt=$at"}, + }), + + PSEUDO("div", "rd,rt,rs", 2, { + {MIPS32R6_INS_DIV, "rt,rs"}, + {MIPS32R6_INS_MFLO, "rd"}, + }), + + PSEUDO("divu", "rd,rt,rs", 2, { + {MIPS32R6_INS_DIVU, "rt,rs"}, + {MIPS32R6_INS_MFLO, "rd"}, + }), + + PSEUDO("mulo", "rd,rt,rs", 2, { + {MIPS32R6_INS_MULT, "rt,rs"}, + {MIPS32R6_INS_MFLO, "rd"}, + }), + + PSEUDO("mulou", "rd,rt,rs", 2, { + {MIPS32R6_INS_MULTU, "rt,rs"}, + {MIPS32R6_INS_MFLO, "rd"}, + }), + + PSEUDO("neg", "rd,rt", 1, { + {MIPS32R6_INS_SUB, "rd,rs=$zero,rt"}, + }), + + PSEUDO("negu", "rd,rt", 1, { + {MIPS32R6_INS_SUBU, "rd,rs=$zero,rt"}, + }), + + PSEUDO("not", "rd,rt", 1, { + {MIPS32R6_INS_NOR, "rd,rs=$zero,rt"}, + }), + + PSEUDO("rem", "rd,rt,rs", 2, { + {MIPS32R6_INS_DIV, "rt,rs"}, + {MIPS32R6_INS_MFHI, "rd"}, + }), + + PSEUDO("remu", "rd,rt,rs", 2, { + {MIPS32R6_INS_DIVU, "rt,rs"}, + {MIPS32R6_INS_MFHI, "rd"}, + }), + + // TODO: rol + + // TODO: ror + + PSEUDO("subi", "rt,rs,immd", 1, { + {MIPS32R6_INS_ADDI, "rt,rs,-immd"}, + }), + PSEUDO("li", "rt,immd", 1, { {MIPS32R6_INS_ADDI, "rt,immd"} }), + PSEUDO("seq", "rd,rs,rt", 3, { + {MIPS32R6_INS_SLT, "rd,rs,rt"}, + {MIPS32R6_INS_SLT, "rd=$at,rs,rt"}, + {MIPS32R6_INS_NOR, "rd,rs=rd,rt=$at"}, + }), + + PSEUDO("sgt", "rd,rs,rt", 1, { + {MIPS32R6_INS_SLT, "rd,rs=rt,rt=rs"}, + }), + + PSEUDO("sgtu", "rd,rs,rt", 1, { + {MIPS32R6_INS_SLTU, "rd,rs=rt,rt=rs"}, + }), + + PSEUDO("sge", "rd,rs,rt", 2, { + {MIPS32R6_INS_SLT, "rd,rs,rt"}, + {MIPS32R6_INS_SLTI, "rt=rd,rs=rd,immd=1"}, + }), + + PSEUDO("sgeu", "rd,rs,rt", 2, { + {MIPS32R6_INS_SLTU, "rd,rs,rt"}, + {MIPS32R6_INS_SLTI, "rt=rd,rs=rd,immd=1"}, + }), + + PSEUDO("slte", "rd,rs,rt", 2, { + {MIPS32R6_INS_SLT, "rd,rs=rt,rt=rs"}, + {MIPS32R6_INS_SLTI, "rt=rd,rs=rd,immd=1"}, + }), + + PSEUDO("slteu", "rd,rs,rt", 2, { + {MIPS32R6_INS_SLTU, "rd,rs=rt,rt=rs"}, + {MIPS32R6_INS_SLTI, "rt=rd,rs=rd,immd=1"}, + }), + + PSEUDO("sne", "rd,rs,rt", 3, { + {MIPS32R6_INS_SLT, "rd,rs,rt"}, + {MIPS32R6_INS_SLT, "rd=$at,rs,rt"}, + {MIPS32R6_INS_OR, "rd,rs=rd,rt=$at"}, + }), + + PSEUDO("jalr.hb", "rs", 1, { + {MIPS32R6_INS_JALR, "rs,hb=1"} + }), + + PSEUDO("jr.hb", "rs", 1, { + {MIPS32R6_INS_JR, "rs,hb=1"} + }), + + + PSEUDO("b", "offset", 1, { + {MIPS32R6_INS_BEQ, "rs=$zero,rt=$zero,offset"}, + }), + + PSEUDO("beqz", "rs,offset", 1, { + {MIPS32R6_INS_BEQ, "rs,rt=$zero,offset"}, + }), + + PSEUDO("bge", "rs,rt,offset", 2, { + {MIPS32R6_INS_SLT, "rd=$at,rs,rt"}, + {MIPS32R6_INS_BNE, "rs=$at,rt=$zero,offset"}, + }), + + PSEUDO("bgeu", "rs,rt,offset", 2, { + {MIPS32R6_INS_SLTU, "rd=$at,rs,rt"}, + {MIPS32R6_INS_BNE, "rs=$at,rt=$zero,offset"}, + }), + + PSEUDO("bge", "rs,rt,offset", 2, { + {MIPS32R6_INS_SLT, "rd=$at,rs,rt"}, + {MIPS32R6_INS_BEQ, "rs=$at,rt=$zero,offset"}, + }), + + PSEUDO("bgeu", "rs,rt,offset", 2, { + {MIPS32R6_INS_SLTU, "rd=$at,rs,rt"}, + {MIPS32R6_INS_BEQ, "rs=$at,rt=$zero,offset"}, + }), + + PSEUDO("ble", "rs,rt,offset", 2, { + {MIPS32R6_INS_SLT, "rd=$at,rs=rt,rt=rs"}, + {MIPS32R6_INS_BEQ, "rs=$at,rt=$zero,offset"}, + }), + + PSEUDO("bleu", "rs,rt,offset", 2, { + {MIPS32R6_INS_SLT, "rd=$at,rs=rt,rt=rs"}, + {MIPS32R6_INS_BEQ, "rs=$at,rt=$zero,offset"}, + }), + + PSEUDO("blt", "rs,rt,offset", 2, { + {MIPS32R6_INS_SLT, "rd=$at,rs,rt"}, + {MIPS32R6_INS_BNE, "rs=$at,rt=$zero,offset"}, + }), + + PSEUDO("bltu", "rs,rt,offset", 2, { + {MIPS32R6_INS_SLTU, "rd=$at,rs,rt"}, + {MIPS32R6_INS_BNE, "rs=$at,rt=$zero,offset"}, + }), + + PSEUDO("bnez", "rs,offset", 1, { + {MIPS32R6_INS_BNE, "rs,rt=$zero,offset"}, + }), + + // TODO: ld + + // TODO: load unaligned + + // TODO: store unaligned + PSEUDO("la", "rt,target", 2, { {MIPS32R6_INS_LUI, "rt=$at,hi"}, {MIPS32R6_INS_ORI, "rt,rs=$at,lo"}, @@ -95,6 +353,14 @@ struct mips32_grammer mips32r6_grammers[__MIPS32R6_GRAMMER_LEN] = { PSEUDO("nop", "", 1, { {MIPS32R6_INS_SLL, ""}, }), + + PSEUDO("ssnop", "", 1, { + {MIPS32R6_INS_SLL, "sa=1"}, + }), + + PSEUDO("ehb", "", 1, { + {MIPS32R6_INS_SLL, "sa=3"} + }), }; #define MIPS_INS(ins, ...) \ @@ -119,54 +385,138 @@ MIPS_INS(AND, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_AND) /* ANDI - and immediate */ MIPS_INS(ANDI, .op = MIPS32R6_OP_ANDI) -/* BAL - branch and link */ -MIPS_INS(BAL, .op = MIPS32R6_OP_REGIMM, .bfunct = MIPS32R6_FUNCT_BAL) +/* BC1F - branch on cop1 false */ +MIPS_INS(BC1F, .op = MIPS32R6_OP_COP1, .cfunct = MIPS32R6_FUNCT_BC, + .nd = 0, .tf = 0) -/* BALC - branch and link, compact */ -MIPS_INS(BALC, .op = MIPS32R6_OP_BALC) +/* BC1FL - branch on cop1 false likely */ +MIPS_INS(BC1FL, .op = MIPS32R6_OP_COP1, .cfunct = MIPS32R6_FUNCT_BC, + .nd = 1, .tf = 0) -/* BC - branch, compact */ -MIPS_INS(BC, .op = MIPS32R6_OP_BC) +/* BC1T - branch on cop1 true */ +MIPS_INS(BC1T, .op = MIPS32R6_OP_COP1, .cfunct = MIPS32R6_FUNCT_BC, + .nd = 0, .tf = 1) + +/* BC1TL - branch on cop1 true likely */ +MIPS_INS(BC1TL, .op = MIPS32R6_OP_COP1, .cfunct = MIPS32R6_FUNCT_BC, + .nd = 1, .tf = 1) + +/* BC2F - branch on cop1 false */ +MIPS_INS(BC2F, .op = MIPS32R6_OP_COP2, .cfunct = MIPS32R6_FUNCT_BC, + .nd = 0, .tf = 0) + +/* BC2FL - branch on cop1 false likely */ +MIPS_INS(BC2FL, .op = MIPS32R6_OP_COP2, .cfunct = MIPS32R6_FUNCT_BC, + .nd = 1, .tf = 0) + +/* BC2T - branch on cop1 true */ +MIPS_INS(BC2T, .op = MIPS32R6_OP_COP2, .cfunct = MIPS32R6_FUNCT_BC, + .nd = 0, .tf = 1) + +/* BC2TL - branch on cop1 true likely */ +MIPS_INS(BC2TL, .op = MIPS32R6_OP_COP2, .cfunct = MIPS32R6_FUNCT_BC, + .nd = 1, .tf = 1) /* BEQ - branch on equal */ MIPS_INS(BEQ, .op = MIPS32R6_OP_BEQ) +/* BEQL - branch on equal likely */ +MIPS_INS(BEQL, .op = MIPS32R6_OP_BEQL) + /* BGEZ - branch on greater than or equal to zero */ MIPS_INS(BGEZ, .op = MIPS32R6_OP_REGIMM, .bfunct = MIPS32R6_FUNCT_BGEZ) /* BGEZAL - branch on greater than or equal to zero and link */ MIPS_INS(BGEZAL, .op = MIPS32R6_OP_REGIMM, .bfunct = MIPS32R6_FUNCT_BGEZAL) +/* BGEZALL - branch on greater than or equal to zero and link likely */ +MIPS_INS(BGEZALL, .op = MIPS32R6_OP_REGIMM, .bfunct = MIPS32R6_FUNCT_BGEZALL) + +/* BGEZL - branch on greater than or equal to zero likely */ +MIPS_INS(BGEZL, .op = MIPS32R6_OP_REGIMM, .bfunct = MIPS32R6_FUNCT_BGEZL) + /* BGTZ - branch on greater than zero */ MIPS_INS(BGTZ, .op = MIPS32R6_OP_BGTZ) +/* BGTZL - branch on greater than zero likely */ +MIPS_INS(BGTZL, .op = MIPS32R6_OP_BGTZL) + /* BLEZ - branch on less than or equal to zero */ MIPS_INS(BLEZ, .op = MIPS32R6_OP_BLEZ) +/* BLEZL - branch on less than or equal to zero likely */ +MIPS_INS(BLEZL, .op = MIPS32R6_OP_BLEZL) + /* BLTZ - branch on less than zero */ MIPS_INS(BLTZ, .op = MIPS32R6_OP_REGIMM, .bfunct = MIPS32R6_FUNCT_BLTZ) /* BLTZAL - branch on less than zero and link */ MIPS_INS(BLTZAL, .op = MIPS32R6_OP_REGIMM, .bfunct = MIPS32R6_FUNCT_BLTZAL) +/* BLTZALL - branch on less than zero and link likely */ +MIPS_INS(BLTZALL, .op = MIPS32R6_OP_REGIMM, .bfunct = MIPS32R6_FUNCT_BLTZALL) + +/* BLTZL - branch on less than zero likely */ +MIPS_INS(BLTZL, .op = MIPS32R6_OP_REGIMM, .bfunct = MIPS32R6_FUNCT_BLTZL) + /* BNE - branch on not equal */ MIPS_INS(BNE, .op = MIPS32R6_OP_BNE) -/* DIV - divide */ -MIPS_INS(DIV, .op = MIPS32R6_OP_SPECIAL, .shamt = MIPS32R6_SOP32_DIV, - .funct = MIPS32R6_FUNCT_SOP32) +/* BNEL - branch on not equal likely */ +MIPS_INS(BNEL, .op = MIPS32R6_OP_BNEL) -/* MOD - modulo */ -MIPS_INS(MOD, .op = MIPS32R6_OP_SPECIAL, .shamt = MIPS32R6_SOP32_MOD, - .funct = MIPS32R6_FUNCT_SOP32) +/* BREAK - breakpoint */ +MIPS_INS(BREAK, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_BREAK) + +/* CACHE - perform cache operation */ +MIPS_INS(CACHE, .op = MIPS32R6_OP_CACHE) + +/* CFC1 - move control word from floating point */ +MIPS_INS(CFC1, .op = MIPS32R6_OP_COP1, .cfunct = MIPS32R6_FUNCT_CF) + +/* CFC2 - move control word from coprocessor 2 */ +MIPS_INS(CFC2, .op = MIPS32R6_OP_COP2, .cfunct = MIPS32R6_FUNCT_CF) + +/* CLO - count leading ones */ +MIPS_INS(CLO, .op = MIPS32R6_OP_SPECIAL2, .funct = MIPS32R6_FUNCT_CLO) + +/* CLZ - count leading zeros */ +MIPS_INS(CLZ, .op = MIPS32R6_OP_SPECIAL2, .funct = MIPS32R6_FUNCT_CLZ) + +/* COP2 - coprocessor operation to coprocessor 2 */ +MIPS_INS(COP2, .op = MIPS32R6_OP_COP2, .c0 = 1) + +/* CTC1 - move control word to floating point */ +MIPS_INS(CTC1, .op = MIPS32R6_OP_COP1, .cfunct = MIPS32R6_FUNCT_CT) + +/* CTC2 - move control word to coprocessor 2 */ +MIPS_INS(CTC2, .op = MIPS32R6_OP_COP2, .cfunct = MIPS32R6_FUNCT_CT) + +/* DERET - debug exception return */ +MIPS_INS(DERET, .op = MIPS32R6_OP_COP0, .c0 = 1, .funct = MIPS32R6_FUNCT_DERET) + +/* DI - disable interupts */ +MIPS_INS(DI, .op = MIPS32R6_OP_COP0, .cfunct = MIPS32R6_FUNCT_MFMC0, + .rd = 12, .sc = 0) + +/* DIV - divide */ +MIPS_INS(DIV, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_DIV) /* DIVU - divide unsigned */ -MIPS_INS(DIVU, .op = MIPS32R6_OP_SPECIAL, .shamt = MIPS32R6_SOP33_DIVU, - .funct = MIPS32R6_FUNCT_SOP33) +MIPS_INS(DIVU, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_DIVU) -/* MODU - modulo unsigned */ -MIPS_INS(MODU, .op = MIPS32R6_OP_SPECIAL, .shamt = MIPS32R6_SOP33_MODU, - .funct = MIPS32R6_FUNCT_SOP33) +/* EI - enable interupts */ +MIPS_INS(EI, .op = MIPS32R6_OP_COP0, .cfunct = MIPS32R6_FUNCT_MFMC0, + .rd = 12, .sc = 1) + +/* ERET - exception return */ +MIPS_INS(ERET, .op = MIPS32R6_OP_COP0, .c0 = 1, .funct = MIPS32R6_FUNCT_ERET) + +/* ERT - extract bit field */ +MIPS_INS(EXT, .op = MIPS32R6_OP_SPECIAL3, .funct = MIPS32R6_FUNCT_EXT) + +/* INS - insert bit field */ +MIPS_INS(INS, .op = MIPS32R6_OP_SPECIAL3, .funct = MIPS32R6_FUNCT_INS) /* J - jump */ MIPS_INS(J, .op = MIPS32R6_OP_J) @@ -178,9 +528,6 @@ MIPS_INS(JAL, .op = MIPS32R6_OP_JAL) MIPS_INS(JALR, .rd = MIPS32_REG_RA, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_JALR) -/* JALX - jump and link exchange */ -MIPS_INS(JALX, .op = MIPS32R6_OP_JALX) - /* JR - jump register */ MIPS_INS(JR, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_JR) @@ -190,43 +537,182 @@ MIPS_INS(LB, .op = MIPS32R6_OP_LB) /* LBU - load byte unsigned */ MIPS_INS(LBU, .op = MIPS32R6_OP_LBU) +/* LDC1 - load doubleword floating point */ +MIPS_INS(LDC1, .op = MIPS32R6_OP_LDC1) + +/* LDC2 - load doubleword cop2 */ +MIPS_INS(LDC2, .op = MIPS32R6_OP_LDC2) + +/* LDXC1 - load doubleword indexed to floating point */ +MIPS_INS(LDXC1, .op = MIPS32R6_OP_COP1X, .funct = MIPS32R6_FUNCT_LDXC1) + /* LH - load half */ MIPS_INS(LH, .op = MIPS32R6_OP_LH) /* LHU - load half unsigned */ MIPS_INS(LHU, .op = MIPS32R6_OP_LHU) +/* LK - load linked */ +MIPS_INS(LL, .op = MIPS32R6_OP_LL) + /* LUI - load upper immediate */ MIPS_INS(LUI, .op = MIPS32R6_OP_LUI) +/* LUXC1 - load doubleword indexed unaligned to floating point */ +MIPS_INS(LUXC1, .op = MIPS32R6_OP_COP1X, .funct = MIPS32R6_FUNCT_LUXC1) + /* LW - load word */ MIPS_INS(LW, .op = MIPS32R6_OP_LW) -/* MUL - multiply low word */ -MIPS_INS(MUL, .op = MIPS32R6_OP_SPECIAL, .shamt = MIPS32R6_SOP30_MUL, - .funct = MIPS32R6_FUNCT_SOP30) +/* LDC1 - load word floating point */ +MIPS_INS(LWC1, .op = MIPS32R6_OP_LWC1) -/* MUH - multiply high word */ -MIPS_INS(MUH, .op = MIPS32R6_OP_SPECIAL, .shamt = MIPS32R6_SOP30_MUH, - .funct = MIPS32R6_FUNCT_SOP30) +/* LDC2 - load eword cop2 */ +MIPS_INS(LWC2, .op = MIPS32R6_OP_LWC2) -/* MULU - multiply low word unsigned */ -MIPS_INS(MULU, .op = MIPS32R6_OP_SPECIAL, .shamt = MIPS32R6_SOP31_MULU, - .funct = MIPS32R6_FUNCT_SOP31) +/* LWL - load word left */ +MIPS_INS(LWL, .op = MIPS32R6_OP_LWL) -/* MUHU - multiply high word unsgined */ -MIPS_INS(MUHU, .op = MIPS32R6_OP_SPECIAL, .shamt = MIPS32R6_SOP31_MUHU, - .funct = MIPS32R6_FUNCT_SOP31) +/* LWR - load word right */ +MIPS_INS(LWR, .op = MIPS32R6_OP_LWR) + +/* LWXC1 - load word indexed to floating point */ +MIPS_INS(LWXC1, .op = MIPS32R6_OP_COP1X, .funct = MIPS32R6_FUNCT_LWXC1) + +/* MADD - multiply and add words to hi,lo */ +MIPS_INS(MADD, .op = MIPS32R6_OP_SPECIAL2, .funct = MIPS32R6_FUNCT_MADD) + +/* MADDU - multiply and add unsigned words to hi,lo */ +MIPS_INS(MADDU, .op = MIPS32R6_OP_SPECIAL2, .funct = MIPS32R6_FUNCT_MADDU) + +/* MFC0 - move from cop0 */ +MIPS_INS(MFC0, .op = MIPS32R6_OP_COP0, .cfunct = MIPS32R6_FUNCT_MF) + +/* MFC1 - move from floating point */ +MIPS_INS(MFC1, .op = MIPS32R6_OP_COP1, .cfunct = MIPS32R6_FUNCT_MF) + +/* MFC2 - move from cop2 */ +MIPS_INS(MFC2, .op = MIPS32R6_OP_COP0, .cfunct = MIPS32R6_FUNCT_MF) + +/* MFHC1 - move word from high half of floating point register */ +MIPS_INS(MFHC1, .op = MIPS32R6_OP_COP1, .cfunct = MIPS32R6_FUNCT_MFH) + +/* MFHC2 - move word from high half of cop2 */ +MIPS_INS(MFHC2, .op = MIPS32R6_OP_COP2, .cfunct = MIPS32R6_FUNCT_MFH) + +/* MFHI - move from hi register */ +MIPS_INS(MFHI, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_MFHI) + +/* MFLO - move from lo register */ +MIPS_INS(MFLO, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_MFLO) + +/* MOVF - move on floating point false */ +MIPS_INS(MOVF, .op = MIPS32R6_OP_SPECIAL, .tf = 0, + .funct = MIPS32R6_FUNCT_MOVCL) + +/* MOVN - move conditional on non zero */ +MIPS_INS(MOVN, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_MOVN) + +/* MOVT - move on floating point true */ +MIPS_INS(MOVT, .op = MIPS32R6_OP_SPECIAL, .tf = 1, + .funct = MIPS32R6_FUNCT_MOVCL) + +/* MOVZ - move conditional on zero */ +MIPS_INS(MOVZ, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_MOVZ) + +/* MSUB - multiply and add words to hi,lo */ +MIPS_INS(MSUB, .op = MIPS32R6_OP_SPECIAL2, .funct = MIPS32R6_FUNCT_MSUB) + +/* MSUBU - multiply and add unsigned words to hi,lo */ +MIPS_INS(MSUBU, .op = MIPS32R6_OP_SPECIAL2, .funct = MIPS32R6_FUNCT_MSUBU) + +/* MTC0 - move to cop0 */ +MIPS_INS(MTC0, .op = MIPS32R6_OP_COP0, .cfunct = MIPS32R6_FUNCT_MT) + +/* MTC1 - move to floating point */ +MIPS_INS(MTC1, .op = MIPS32R6_OP_COP1, .cfunct = MIPS32R6_FUNCT_MT) + +/* MTC2 - move to cop2 */ +MIPS_INS(MTC2, .op = MIPS32R6_OP_COP0, .cfunct = MIPS32R6_FUNCT_MT) + +/* MTHC1 - move word to high half of floating point register */ +MIPS_INS(MTHC1, .op = MIPS32R6_OP_COP1, .cfunct = MIPS32R6_FUNCT_MTH) + +/* MTHC2 - move word to high half of cop2 */ +MIPS_INS(MTHC2, .op = MIPS32R6_OP_COP2, .cfunct = MIPS32R6_FUNCT_MTH) + +/* MTHI - move to hi register */ +MIPS_INS(MTHI, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_MTHI) + +/* MTLO - move to lo register */ +MIPS_INS(MTLO, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_MTLO) + +/* MUL - multiply word to GPR */ +MIPS_INS(MUL, .op = MIPS32R6_OP_SPECIAL2, .funct = MIPS32R6_FUNCT_MUL) + +/* MULT - multiply word */ +MIPS_INS(MULT, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_MULT) + +/* MULTU - multiply unsigned word */ +MIPS_INS(MULTU, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_MULTU) + +/* NOR - not or */ +MIPS_INS(NOR, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_NOR) + +/* OR - or */ +MIPS_INS(OR, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_OR) + +/* ORI - or imemdiate */ +MIPS_INS(ORI, .op = MIPS32R6_OP_ORI) + +/* PREF - prefetch */ +MIPS_INS(PREF, .op = MIPS32R6_OP_PREF) + +/* PREFX - prefetch indexed */ +MIPS_INS(PREFX, .op = MIPS32R6_OP_COP1X, .funct = MIPS32R6_FUNCT_PREFX) + +/* RDHWR - read hardware register */ +MIPS_INS(RDHWR, .op = MIPS32R6_OP_SPECIAL3, .funct = MIPS32R6_FUNCT_RDHWR) + +/* RDPGPR - read gpr from previous shadow set */ +MIPS_INS(RDPGPR, .op = MIPS32R6_OP_COP0, .cfunct = MIPS32R6_FUNCT_RDPGPR) + +/* ROTR - rotate word right */ +MIPS_INS(ROTR, .op = MIPS32R6_OP_SPECIAL, .r = 1, .funct = MIPS32R6_FUNCT_SRL) + +/* ROTRV - rotate word right variable */ +MIPS_INS(ROTRV, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_SRLV, + .rv = 1) /* SB - store byte */ MIPS_INS(SB, .op = MIPS32R6_OP_SB) +/* SC - store conditional word */ +MIPS_INS(SC, .op = MIPS32R6_OP_SC) + +/* SDBBP - software debug breakpoint */ +MIPS_INS(SDBBP, .op = MIPS32R6_OP_SPECIAL2, .funct = MIPS32R6_FUNCT_SDBBP) + +/* SDC1 - store doubleword floating point */ +MIPS_INS(SDC1, .op = MIPS32R6_OP_SDC1) + +/* SDC2 - store doubleword cop2 */ +MIPS_INS(SDC2, .op = MIPS32R6_OP_SDC2) + +/* SDXC1 - store doubleword indexed from floating point */ +MIPS_INS(SDXC1, .op = MIPS32R6_OP_COP1X, .funct = MIPS32R6_FUNCT_SDXC1) + +/* SEB - sign extend byte */ +MIPS_INS(SEB, .op = MIPS32R6_OP_SPECIAL3, .shamt = MIPS32R6_FUNCT_SEB, + .funct = MIPS32R6_FUNCT_BSHFL) + +/* SEH - sign extend halfword */ +MIPS_INS(SEH, .op = MIPS32R6_OP_SPECIAL3, .shamt = MIPS32R6_FUNCT_SEH, + .funct = MIPS32R6_FUNCT_BSHFL) + /* SH - store half */ MIPS_INS(SH, .op = MIPS32R6_OP_SH) -/* SW - store word */ -MIPS_INS(SW, .op = MIPS32R6_OP_SW) - /* SLL - shift left logical */ MIPS_INS(SLL, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_SLL) @@ -263,17 +749,93 @@ MIPS_INS(SUB, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_SUB) /* SUBU - subtract unsigned */ MIPS_INS(SUBU, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_SUBU) +/* SUXC1 - store doubleword indexed unaligned from floating point */ +MIPS_INS(SUXC1, .op = MIPS32R6_OP_COP1X, .funct = MIPS32R6_FUNCT_SUXC1) + +/* SW - store word */ +MIPS_INS(SW, .op = MIPS32R6_OP_SW) + +/* SWC1 - store word floating point */ +MIPS_INS(SWC1, .op = MIPS32R6_OP_SWC1) + +/* SWC2 - store eword cop2 */ +MIPS_INS(SWC2, .op = MIPS32R6_OP_SWC2) + +/* SWL - store word left */ +MIPS_INS(SWL, .op = MIPS32R6_OP_SWL) + +/* SWR - store word right */ +MIPS_INS(SWR, .op = MIPS32R6_OP_SWR) + +/* SWXC1 - store word indexed from floating point */ +MIPS_INS(SWXC1, .op = MIPS32R6_OP_COP1X, .funct = MIPS32R6_FUNCT_SWXC1) + +/* SYNC - synchronize shared memory */ +MIPS_INS(SYNC, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_SYNC) + +/* SYNCI - synchronize caches to make instruction writes effective */ +MIPS_INS(SYNCI, .op = MIPS32R6_OP_REGIMM, .bfunct = MIPS32R6_FUNCT_SYNCI) + /* SYSCALL - syscall */ MIPS_INS(SYSCALL, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_SYSCALL) -/* OR - or */ -MIPS_INS(OR, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_OR) +/* TEQ - trap if equal */ +MIPS_INS(TEQ, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_TEQ) -/* ORI - or imemdiate */ -MIPS_INS(ORI, .op = MIPS32R6_OP_ORI) +/* TEQI - trap if equal immediate */ +MIPS_INS(TEQI, .op = MIPS32R6_OP_REGIMM, .bfunct = MIPS32R6_FUNCT_TEQI) -/* NOR - not or */ -MIPS_INS(NOR, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_NOR) +/* TGE - trap if greater or equal */ +MIPS_INS(TGE, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_TGE) + +/* TGEI - trap if greater or equal immediate */ +MIPS_INS(TGEI, .op = MIPS32R6_OP_REGIMM, .bfunct = MIPS32R6_FUNCT_TGEI) + +/* TGEIU - trap if greater or equal immediate unsigned */ +MIPS_INS(TGEIU, .op = MIPS32R6_OP_REGIMM, .bfunct = MIPS32R6_FUNCT_TGEIU) + +/* TGEU - trap if greater or equal unsigned */ +MIPS_INS(TGEU, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_TGEU) + +/* TLBP - probe TLB for matching entry */ +MIPS_INS(TLBP, .op = MIPS32R6_OP_COP0, .c0 = 1, .funct = MIPS32R6_FUNCT_TLBP) + +/* TLBR - read indexed TLB entry */ +MIPS_INS(TLBR, .op = MIPS32R6_OP_COP0, .c0 = 1, .funct = MIPS32R6_FUNCT_TLBR) + +/* TLBWI - write indexed TLB entry */ +MIPS_INS(TLBWI, .op = MIPS32R6_OP_COP0, .c0 = 1, .funct = MIPS32R6_FUNCT_TLBWI) + +/* TLBWR - write random TLB entry */ +MIPS_INS(TLBWR, .op = MIPS32R6_OP_COP0, .c0 = 1, .funct = MIPS32R6_FUNCT_TLBWR) + +/* TLT - trap if less then */ +MIPS_INS(TLT, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_TLT) + +/* TLTI - trap if less then immediate */ +MIPS_INS(TLTI, .op = MIPS32R6_OP_REGIMM, .bfunct = MIPS32R6_FUNCT_TLTI) + +/* TLTIU - trap if less then immediate unsigned */ +MIPS_INS(TLTIU, .op = MIPS32R6_OP_REGIMM, .bfunct = MIPS32R6_FUNCT_TLTIU) + +/* TLTU - trap if less then unsigned */ +MIPS_INS(TLTU, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_TLTU) + +/* TNE - trap if not equal */ +MIPS_INS(TNE, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_TNE) + +/* TNEI - trap if not equal immediate */ +MIPS_INS(TNEI, .op = MIPS32R6_OP_REGIMM, .bfunct = MIPS32R6_FUNCT_TNEI) + +/* WAIT - enter standby mode */ +MIPS_INS(WAIT, .op = MIPS32R6_OP_COP0, .c0 = 1, .funct = MIPS32R6_FUNCT_WAIT) + +/* WRPGRP - write to GPR in previous shadow set */ +MIPS_INS(WRPGPR, .op = MIPS32R6_OP_COP0, .cfunct = MIPS32R6_FUNCT_WRPGPR) + +/* WSBH - word swap bytes within halfwords */ +MIPS_INS(WSBH, .op = MIPS32R6_OP_SPECIAL3, .funct = MIPS32R6_FUNCT_BSHFL, + .shamt = MIPS32R6_FUNCT_WSBH) /* XOR - exclusive or */ MIPS_INS(XOR, .op = MIPS32R6_OP_SPECIAL, .funct = MIPS32R6_FUNCT_XOR) @@ -284,3 +846,6 @@ MIPS_INS(XORI, .op = MIPS32R6_OP_XORI) #undef MIPS_INS + + + diff --git a/masm/gen.c b/masm/gen.c index c4a15a0..74d30d2 100644 --- a/masm/gen.c +++ b/masm/gen.c @@ -10,179 +10,10 @@ #include "gen.h" #include "parse.h" -/// -/// section table -/// - -static void section_get_default_perm(struct section *sec, const char *name) -{ - #define __LEN 7 - static const struct perms { - char *name; - bool read; - bool write; - bool execute; - int alignment; - } defaults[__LEN] = { - {".text", true, false, true, 4}, - {".code", true, false, true, 4}, - {".data", true, true, false, 1}, - {".stack", true, true, false, 1}, - {".rodata", true, false, false, 1}, - {".bss", true, true, false, 1}, - {".robss", true, false, false, 1}, - }; - - for (int i = 0; i < __LEN; i++) { - const struct perms *p = &defaults[i]; - if (strcasecmp(name, p->name) != 0) - continue; - sec->read = p->read; - sec->write = p->write; - sec->execute = p->execute; - sec->align = p->alignment; - break; - } - -} - -static int section_get(struct generator *gen, struct section **res, - const struct string *const name) -{ - /// find the section if it exists - for (size_t i = 0; i < gen->sections_len; i++) { - struct section *sec = &gen->sections[i]; - if (sec->name.len != name->len) - continue; - if (strcmp(sec->name.str, name->str) != 0) - continue; - *res = sec; - return M_SUCCESS; - } - - /// allocate a new one if it doesnt - size_t size = gen->sections_size ? gen->sections_size * 2 : 8; - void *new = realloc(gen->sections, size * sizeof(struct section)); - if (new == NULL) { - PERROR("cannot realloc"); - return M_ERROR; - } - - gen->sections_size = size; - gen->sections = new; - - struct section *sec = &gen->sections[gen->sections_len++]; - - // alloc reftab - if (reftab_init(&sec->reftab)) - return M_ERROR; - - // copy name - if (string_clone(&sec->name, name)) - return M_ERROR; - - // set defaults - sec->len = 0; - sec->size = 0; - sec->align = 1; - sec->data = NULL; - sec->read = true; - sec->write = true; - sec->execute = false; - section_get_default_perm(sec, name->str); - - *res = sec; - return M_SUCCESS; -} - -static int section_extend(struct section *section, size_t space) -{ - size_t newlen = section->len + space; - if (newlen < section->size) - return M_SUCCESS; - - size_t size = section->size ? section->size * 2 + newlen : newlen * 2; - void *new = realloc(section->data, size); - if (new == NULL) { - PERROR("cannot realloc"); - return M_ERROR; - } - section->size = size; - section->data = new; - - return M_SUCCESS; -} - -static int section_push(struct section *section, void *data, size_t len) -{ - size_t newlen = section->len + len; - size_t zeros = newlen % section->align; - if (zeros) - zeros = section->align - zeros; - - if (section_extend(section, len + zeros)) - return M_ERROR; - - memset(section->data + section->len, 0, zeros); - memcpy(section->data + section->len + zeros, data, len); - section->len += len + zeros; - - return M_SUCCESS; -} - -static int section_zero(struct section *section, size_t len) -{ - size_t zeros = section->len % section->align; - if (zeros) - zeros = section->align - zeros; - - if (section_extend(section, len + zeros)) - return M_ERROR; - - memset(section->data + section->len, 0, len + zeros); - section->len += len + zeros; - - return M_SUCCESS; -} - -void section_free(struct section *section) -{ - reftab_free(§ion->reftab); - string_free(§ion->name); - free(section->data); -} - /// /// generation functions /// -static void print_curr_line(struct generator *gen, - const struct expr *const expr) -{ - int line = expr->line_no, - len = expr->byte_end - expr->byte_start, - nl = true, - c = EOF; - FILE *file = gen->parser.lexer.file; - - fseek(file, expr->byte_start, SEEK_SET); - - while (len--) { - c = getc(file); - if (c == EOF || c == '\0') - break; - if (nl) { - fprintf(stderr, "\t%d | ", line); - line++; - nl = false; - } - if (c == '\n') - nl = true; - putc(c, stderr); - } - -} - static int gen_directive_whb(struct generator *gen, const void *data, uint32_t count, uint32_t len) { @@ -265,488 +96,6 @@ static int gen_constant(struct generator *gen, struct expr_const *const expr) return M_ERROR; } -static int parse_register(enum mips32_register *reg, struct string *name) -{ - int len = name->len; - int c0 = len > 0 ? name->str[0] : '\0', - c1 = len > 1 ? name->str[1] : '\0', - c2 = len > 2 ? name->str[2] : '\0', - c3 = len > 3 ? name->str[3] : '\0'; - - // $zero - if (c0 == 'z') { - if (c1 == 'e' && c2 == 'r' && c3 == 'o') { - *reg = MIPS32_REG_ZERO; - return M_SUCCESS; - } - } - - // $a0-a3 $at - else if (c0 == 'a') { - if (c1 == 't') { - *reg = MIPS32_REG_AT; - return M_SUCCESS; - } - if (c1 >= '0' && c1 <= '3') { - *reg = MIPS32_REG_A0; - *reg += c1 - '0'; - return M_SUCCESS; - } - } - - // $v0-v1 - else if (c0 == 'v') { - if (c1 >= '0' && c1 <= '1') { - *reg = MIPS32_REG_V0; - *reg += c1 - '0'; - return M_SUCCESS; - } - } - - // $t0-t9 - else if (c0 == 't') { - if (c1 >= '0' && c1 <= '7') { - *reg = MIPS32_REG_T0; - *reg += c1 - '0'; - return M_SUCCESS; - } - // reg T8-T9 are not in order with T0-T7 - if (c1 >= '8' && c1 <= '9') { - *reg = MIPS32_REG_T8; - *reg += c1 - '8'; - return M_SUCCESS; - } - } - - // $s0-s7 $sp - else if (c0 == 's') { - if (c1 >= '0' && c1 <= '7') { - *reg = MIPS32_REG_S0; - *reg += c1 - '0'; - return M_SUCCESS; - } - if (c1 == 'p') { - *reg = MIPS32_REG_SP; - return M_SUCCESS; - } - } - - // $k0-k1 - else if (c0 == 'k') { - if (c1 >= '0' && c1 <= '1') { - *reg = MIPS32_REG_K0; - *reg += c1 - '0'; - return M_SUCCESS; - } - } - - // $gp - else if (c0 == 'g') { - if (c1 == 'p') { - *reg = MIPS32_REG_GP; - return M_SUCCESS; - } - } - - // $fp - else if (c0 == 'f') { - if (c1 == 'p') { - *reg = MIPS32_REG_FP; - return M_SUCCESS; - } - } - - // $rp - else if (c0 == 'r') { - if (c1 == 'a') { - *reg = MIPS32_REG_RA; - return M_SUCCESS; - } - } - - // $0-31 (non aliased register names) - else if (c0 >= '0' && c0 <= '9') { - int i = c0 - '0'; - if (c1 >= '0' && c1 <= '9') { - i *= 10; - i += c1 - '0'; - } - if (i <= 31) { - *reg = i; - return M_SUCCESS; - } - } - - ERROR("unknown register $%.*s", name->len, name->str); - return M_ERROR; -} - -static int parse_fp_register(enum mips32_fp_register *reg, struct string *name) -{ - int len = name->len; - int c0 = len > 0 ? name->str[0] : '\0', - c1 = len > 1 ? name->str[1] : '\0', - c2 = len > 2 ? name->str[2] : '\0'; - - *reg = 0; - - if (c0 != 'f') - goto error; - - if (c1 < '0' || c1 > '9') - goto error; - - *reg += c1 - '0'; - - if (c1 == '\0') - return M_SUCCESS; - - if (c2 < '0' || c2 > '9') - goto error; - - *reg *= 10; - *reg += c2 - '0'; - - return M_SUCCESS; - -error: - ERROR("unknown fp register $%.*s", name->len, name->str); - return M_ERROR; - -} - -static enum grammer_type get_gmr_type(const char *name, size_t *len) -{ - #define CHK(part, str) { \ - if (strncasecmp(str, name, strlen(str)) == 0) { \ - *len = strlen(str); \ - return GMR_ ##part; \ - }} \ - - CHK(RD, "rd") - CHK(RS, "rs") - CHK(RT, "rt") - CHK(FS, "fs") - CHK(FT, "ft") - CHK(FD, "fd") - CHK(IMMD, "immd") - CHK(CC, "cc") - CHK(CODE, "code") - CHK(POS, "pos") - CHK(SIZE, "size") - CHK(HB, "hb") - CHK(HINT, "hint") - CHK(OFFSET_BASE, "offset(base)") - CHK(INDEX_BASE, "index(base)") - CHK(OFFSET, "offset") - CHK(TARGET, "target") - CHK(HI, "hi") - CHK(LO, "lo") - - #undef CHK - - BUG("invalid grammer key: %s", name); - exit(1); -} - -static int get_gmr_hc(struct gen_ins_state *state, - struct gen_ins_override *over, - char *value) -{ - int vlen = 0; - int res = M_SUCCESS; - - /* get length of value */ - for (const char *ptr = value; - *ptr != '\0' && *ptr != ','; - ptr++, vlen++); - - /* must be at least of length 1 */ - if (vlen < 1) - return M_ERROR; - - #define VAL(v) if (strncmp(v, value, vlen) == 0) - /* register to register mapping */ - VAL("rd") - over->reg = state->rd; - else VAL("rs") - over->reg = state->rs; - else VAL("rt") - { - over->reg = state->rt; - } - else VAL("fs") - over->fpreg = state->fs; - else VAL("ft") - over->fpreg = state->ft; - else VAL("fd") - over->fpreg = state->fd; - else VAL("immd") - over->immd = state->immd; - else VAL("-immd") - over->immd = -state->immd; - /* hardcoded register */ - else if (*value == '$') { - // register - if (vlen < 2) - return M_ERROR; - struct string name; - name.str = value + 1; - name.len = vlen - 1; - if (*name.str == 'f') - res = parse_fp_register(&over->fpreg, &name); - else - res = parse_register(&over->reg, &name); - /* hardcoded immediate */ - } else { - // immediate - char c; - int immd = 0; - while (c = *(value++), c != ',' && c != '\0') { - if (c < '0' || c > '9') - return M_ERROR; - immd *= 10; - immd += c - '0'; - } - over->immd = immd; - } - - #undef KEY - - return res; -} - -static int gen_ins_read_state(struct generator *gen, - struct expr *const expr, - struct gen_ins_state *state, - struct mips32_grammer *grammer) -{ - char *ptr = grammer->grammer; - uint32_t argi = 0; - - // read values into state - while (*ptr != '\0') { - - if (argi >= expr->instruction.args_len) { - ERROR("not enough arguments passed"); - print_curr_line(gen, expr); - return M_ERROR; - } - struct expr_ins_arg *arg = &expr->instruction.args[argi++]; - - size_t skip; - switch (get_gmr_type(ptr, &skip)) { - case GMR_RD: - // rd - if (arg->type != EXPR_INS_ARG_REGISTER) { - ERROR("expected a register"); - print_curr_line(gen, expr); - return M_ERROR; - } - if (parse_register(&state->rd, &arg->reg)) { - print_curr_line(gen, expr); - return M_ERROR; - } - break; - case GMR_RS: - // rs - if (arg->type != EXPR_INS_ARG_REGISTER) { - ERROR("expected a register"); - print_curr_line(gen, expr); - return M_ERROR; - } - if (parse_register(&state->rs, &arg->reg)) { - print_curr_line(gen, expr); - return M_ERROR; - } - break; - case GMR_RT: - // rt - if (arg->type != EXPR_INS_ARG_REGISTER) { - ERROR("expected a register"); - print_curr_line(gen, expr); - return M_ERROR; - } - if (parse_register(&state->rt, &arg->reg)) { - print_curr_line(gen, expr); - return M_ERROR; - } - break; - case GMR_FS: - // fs - if (arg->type != EXPR_INS_ARG_REGISTER) { - ERROR("expected a register"); - print_curr_line(gen, expr); - return M_ERROR; - } - if (parse_fp_register(&state->fs, &arg->reg)) { - print_curr_line(gen, expr); - return M_ERROR; - } - break; - case GMR_FT: - // ft - if (arg->type != EXPR_INS_ARG_REGISTER) { - ERROR("expected a register"); - print_curr_line(gen, expr); - return M_ERROR; - } - if (parse_fp_register(&state->ft, &arg->reg)) { - print_curr_line(gen, expr); - return M_ERROR; - } - break; - case GMR_FD: - // fd - if (arg->type != EXPR_INS_ARG_REGISTER) { - ERROR("expected a register"); - print_curr_line(gen, expr); - return M_ERROR; - } - if (parse_fp_register(&state->fd, &arg->reg)) { - print_curr_line(gen, expr); - return M_ERROR; - } - break; - case GMR_IMMD: - // immd - if (arg->type != EXPR_INS_ARG_IMMEDIATE) { - ERROR("expected an immediate"); - print_curr_line(gen, expr); - return M_ERROR; - } - state->immd = arg->immd; - break; - case GMR_CC: - // cc - if (arg->type != EXPR_INS_ARG_IMMEDIATE) { - ERROR("expected an immediate"); - print_curr_line(gen, expr); - return M_ERROR; - } - state->cc = arg->immd; - break; - case GMR_CODE: - // code - if (arg->type != EXPR_INS_ARG_IMMEDIATE) { - ERROR("expected an immediate"); - print_curr_line(gen, expr); - return M_ERROR; - } - state->code = arg->immd; - break; - case GMR_POS: - // pos - if (arg->type != EXPR_INS_ARG_IMMEDIATE) { - ERROR("expected an immediate"); - print_curr_line(gen, expr); - return M_ERROR; - } - state->pos = arg->immd; - break; - case GMR_SIZE: - // size - if (arg->type != EXPR_INS_ARG_IMMEDIATE) { - ERROR("expected an immediate"); - print_curr_line(gen, expr); - return M_ERROR; - } - // TODO: check valid size - state->size = arg->immd; - break; - case GMR_HB: - // hb - if (arg->type != EXPR_INS_ARG_IMMEDIATE) { - ERROR("expected an immediate"); - print_curr_line(gen, expr); - return M_ERROR; - } - state->hb = !!(arg->immd); - break; - case GMR_HINT: - // hint - if (arg->type != EXPR_INS_ARG_IMMEDIATE) { - ERROR("expected an immediate"); - print_curr_line(gen, expr); - return M_ERROR; - } - state->hint = arg-> immd; - break; - case GMR_OFFSET: - // offset - state->offset = 0; - if (arg->type == EXPR_INS_ARG_IMMEDIATE) - state->offset = arg->immd; - else if (arg->type == EXPR_INS_ARG_LABEL) - state->label = &arg->label; - else { - ERROR("invalid instruction"); - print_curr_line(gen, expr); - return M_ERROR; - } - break; - case GMR_OFFSET_BASE: - // offset(base) - if (arg->type != EXPR_INS_ARG_OFFSET) { - ERROR("expected an offset($base)"); - print_curr_line(gen, expr); - return M_ERROR; - } - state->offset = arg->offset.immd; - if (parse_register(&state->base, &arg->offset.reg)) { - print_curr_line(gen, expr); - return M_ERROR; - } - break; - case GMR_INDEX_BASE: - // index(base) - if (arg->type != EXPR_INS_ARG_OFFSET) { - ERROR("expected an index($base)"); - print_curr_line(gen, expr); - return M_ERROR; - } - state->index = arg->offset.immd; - if (parse_register(&state->base, &arg->offset.reg)) { - print_curr_line(gen, expr); - return M_ERROR; - } - break; - case GMR_TARGET: - // target - state->target = 0; - if (arg->type == EXPR_INS_ARG_IMMEDIATE) - state->target = arg->immd; - else if (arg->type == EXPR_INS_ARG_LABEL) - state->label = &arg->label; - else { - ERROR("invalid instruction"); - print_curr_line(gen, expr); - return M_ERROR; - } - break; - default: - break; - } - - // skip entry - ptr += skip; - - // skip comma - if (*ptr == ',') { - ptr++; - continue; - } else if (*ptr == '\0') { - break; - } else { - BUG("invalid grammer '%s'", grammer); - exit(1); - } - - } - - return M_SUCCESS; -} - static int gen_ins_write_state( struct generator *gen, union mips32_instruction ins, // the instruction to modify @@ -1037,6 +386,12 @@ static int generate(struct generator *gen) return M_SUCCESS; } +// +// the following functions set default generator +// state values for different versions of the mips +// isa +// + /* run codegen with the mips32r6 specification */ int generate_mips32r6(struct generator *gen) { @@ -1067,6 +422,10 @@ int generate_mips1(struct generator *gen) return generate(gen); } +// +// constructors and deconstructors +// + int generator_init(const char *file, struct generator *gen) { if (parser_init(file, &gen->parser)) diff --git a/masm/gen.h b/masm/gen.h index 42fbf50..ed35750 100644 --- a/masm/gen.h +++ b/masm/gen.h @@ -37,8 +37,26 @@ struct section { struct reference_table reftab; }; +/* get a section from the generator by name, and return it into res. if the + * section does not exist, one will be created. */ +int gen_get_section(struct generator *gen, struct section **res, + struct string *name); + +/* initalize a section */ +int section_init(struct section *section, struct string *name); + +/* free a section */ void section_free(struct section *section); +/* extend a section by space bytes plus alignment */ +int section_extend(struct section *section, size_t space); + +/* push data into a section */ +int section_push(struct section *section, void *data, size_t len); + +/* push zeros (empty space) to a section */ +int section_zero(struct section *section, size_t len); + /// /// instruction generation state /// @@ -55,36 +73,35 @@ struct gen_ins_state { enum mips32_fp_register fd; // immd - uint16_t immd; // 16 bit + uint16_t immd; // cc - uint16_t cc; // 3 bit + uint16_t cc; // code - uint32_t code; // 5 bit + uint32_t code; // pos - uint32_t pos; // 5 bit + uint32_t pos; // size - uint32_t size; // 5 bit - 1 - - // hb - bool hb; // 1 bit - 1 - - // index - uint32_t index; + uint32_t size; // hint uint32_t hint; - // offset(base) - uint16_t offset; // 16 bit - enum mips32_register base; + // hazard barrier + bool hb; // 1 bit - 1 // target uint32_t target; + // index(base) + // offset(base) + uint32_t index; + uint16_t offset; + enum mips32_register base; + // current referencd label struct string *label; }; @@ -95,16 +112,11 @@ struct gen_ins_override { uint32_t immd; }; -/// -/// grammer type -/// - enum grammer_type { // registers GMR_RD, GMR_RS, GMR_RT, - GMR_INDEX_BASE, // fp registers GMR_FS, GMR_FT, @@ -118,13 +130,47 @@ enum grammer_type { GMR_HB, GMR_HINT, // addresses - GMR_OFFSET, - GMR_OFFSET_BASE, - GMR_TARGET, GMR_HI, GMR_LO, + GMR_TARGET, + GMR_OFFSET, + GMR_INDEX_BASE, + GMR_OFFSET_BASE, + // len + __GMR_LEN }; +/* Parses the input string and matches it to a grammer type. Returns + * the number of characters consumed, or -1 on error. + */ +int gen_parse_grammer_type(const char *name, enum grammer_type *res); + +/* Parses a register name, returing 0 on success, 1 on error*/ +int gen_parse_register(enum mips32_register *reg, struct string *name); + +/* Parses a floating point register name, returing 0 on success, 1 on error*/ +int gen_parse_fp_register(enum mips32_fp_register *reg, struct string *name); + +/* Parses the overide expression (after the =) in the dsl for the grammer. + * returns the number of characters consumed, or -1 on error. */ +int gen_parse_grammer_overide(struct gen_ins_state *state, + struct gen_ins_override *over, char *value); + +/* Given a grammer for an instruction, read all args as values into the + * instruction generator state. */ +int gen_read_grammer_state(struct generator *gen, + struct expr *const expr, + struct gen_ins_state *state, + struct mips32_grammer *grammer); + +/* Given a grammer for an instruction, and a read state, output multiple + * instructions into the current section in the generator. note: + * this write_grammer is different from the read grammer such that + * it supports paramater reassignment and overides. */ +int gen_write_grammer_state(struct generator *gen, + struct gen_ins_state *state, + char *write_grammer); + /// /// generates assembley /// from a parser stream @@ -152,6 +198,9 @@ struct generator { struct symbol_table symtab; }; +/* output the source code lines for a provided expression */ +void gen_output_expr(struct generator *gen, struct expr *expr); + /* generate the input as mips32r6 */ int generate_mips32r6(struct generator *gen); /* run codegen with the mips32r2 specification */ diff --git a/masm/gen/grammer.c b/masm/gen/grammer.c new file mode 100644 index 0000000..d7327da --- /dev/null +++ b/masm/gen/grammer.c @@ -0,0 +1,643 @@ +#include +#include +#include + +#include "../gen.h" +#include "mips.h" + +struct grammer_mapping { + char *name; + int name_len; + enum grammer_type type; +}; + +#define MAPPING(name, enum) {name, sizeof(name), GMR_ ##enum} + +static const struct grammer_mapping grammer_mappings[__GMR_LEN] = { + // registers + MAPPING("rd", RD), + MAPPING("rs", RS), + MAPPING("rt", RT), + // fp registers + MAPPING("fs", FS), + MAPPING("ft", FT), + MAPPING("fd", FD), + // numberic fileds + MAPPING("immd", IMMD), + MAPPING("cc", CC), + MAPPING("code", CODE), + MAPPING("pos", POS), + MAPPING("size", SIZE), + MAPPING("hb", HB), + MAPPING("hint", HINT), + // addresses + MAPPING("hi", HI), + MAPPING("lo", LO), + MAPPING("target", TARGET), + MAPPING("offset", OFFSET), + MAPPING("offset(base)", OFFSET_BASE), + MAPPING("index(base)", INDEX_BASE) +}; + +/* Parses the input string and matches it to a grammer type. Returns + * the number of characters consumed, or -1 on error. + */ +int gen_parse_grammer_type(const char *name, enum grammer_type *res) +{ + for (int i = 0; i < __GMR_LEN; i++) { + const struct grammer_mapping *mapping = &grammer_mappings[i]; + if (strncasecmp(name, mapping->name, mapping->name_len) != 0) + continue; + if (res != NULL) + *res = mapping->type; + return mapping->name_len; + } + + return -1; +} + +/* Parses a register name, returing 0 on success, 1 on error*/ +int gen_parse_register(enum mips32_register *reg, struct string *name) +{ + int len = name->len; + int c0 = len > 0 ? name->str[0] : '\0', + c1 = len > 1 ? name->str[1] : '\0', + c2 = len > 2 ? name->str[2] : '\0', + c3 = len > 3 ? name->str[3] : '\0'; + + // $zero + if (c0 == 'z') { + if (c1 == 'e' && c2 == 'r' && c3 == 'o') { + *reg = MIPS32_REG_ZERO; + return M_SUCCESS; + } + } + + // $a0-a3 $at + else if (c0 == 'a') { + if (c1 == 't') { + *reg = MIPS32_REG_AT; + return M_SUCCESS; + } + if (c1 >= '0' && c1 <= '3') { + *reg = MIPS32_REG_A0; + *reg += c1 - '0'; + return M_SUCCESS; + } + } + + // $v0-v1 + else if (c0 == 'v') { + if (c1 >= '0' && c1 <= '1') { + *reg = MIPS32_REG_V0; + *reg += c1 - '0'; + return M_SUCCESS; + } + } + + // $t0-t9 + else if (c0 == 't') { + if (c1 >= '0' && c1 <= '7') { + *reg = MIPS32_REG_T0; + *reg += c1 - '0'; + return M_SUCCESS; + } + // reg T8-T9 are not in order with T0-T7 + if (c1 >= '8' && c1 <= '9') { + *reg = MIPS32_REG_T8; + *reg += c1 - '8'; + return M_SUCCESS; + } + } + + // $s0-s7 $sp + else if (c0 == 's') { + if (c1 >= '0' && c1 <= '7') { + *reg = MIPS32_REG_S0; + *reg += c1 - '0'; + return M_SUCCESS; + } + if (c1 == 'p') { + *reg = MIPS32_REG_SP; + return M_SUCCESS; + } + } + + // $k0-k1 + else if (c0 == 'k') { + if (c1 >= '0' && c1 <= '1') { + *reg = MIPS32_REG_K0; + *reg += c1 - '0'; + return M_SUCCESS; + } + } + + // $gp + else if (c0 == 'g') { + if (c1 == 'p') { + *reg = MIPS32_REG_GP; + return M_SUCCESS; + } + } + + // $fp + else if (c0 == 'f') { + if (c1 == 'p') { + *reg = MIPS32_REG_FP; + return M_SUCCESS; + } + } + + // $rp + else if (c0 == 'r') { + if (c1 == 'a') { + *reg = MIPS32_REG_RA; + return M_SUCCESS; + } + } + + // $0-31 (non aliased register names) + else if (c0 >= '0' && c0 <= '9') { + int i = c0 - '0'; + if (c1 >= '0' && c1 <= '9') { + i *= 10; + i += c1 - '0'; + } + if (i <= 31) { + *reg = i; + return M_SUCCESS; + } + } + + ERROR("unknown register $%.*s", name->len, name->str); + return 1; +} + +/* Parses a floating point register name, returing 0 on success, 1 on error*/ +int gen_parse_fp_register(enum mips32_fp_register *reg, struct string *name) +{ + int len = name->len; + int c0 = len > 0 ? name->str[0] : '\0', + c1 = len > 1 ? name->str[1] : '\0', + c2 = len > 2 ? name->str[2] : '\0'; + + *reg = 0; + + if (c0 != 'f') + goto error; + + if (c1 < '0' || c1 > '9') + goto error; + + *reg += c1 - '0'; + + if (c1 == '\0') + return M_SUCCESS; + + if (c2 < '0' || c2 > '9') + goto error; + + *reg *= 10; + *reg += c2 - '0'; + + return M_SUCCESS; + +error: + ERROR("unknown fp register $%.*s", name->len, name->str); + return 1; + +} + +/* convert string to number with int len max length */ +static int antoi(char *str, int len) +{ + char c; + int num = 0; + + while (c = *str++, len--) { + if (c < '0' || c > '9') + break; + num *= 10; + num += c - '0'; + } + + return num; +} + +/* Parses the override expression (after the =) in the dsl for the grammer. + * returns the number of characters consumed, or -1 on error. */ +int gen_parse_grammer_override(struct gen_ins_state *state, + struct gen_ins_override *over, char *value) +{ + int value_len = 0; + + /* get length of value */ + for (const char *ptr = value; + *ptr != '\0' && *ptr != ','; + ptr++, value_len++); + + // rd + if (strncmp("rd", value, value_len)) + over->reg = state->rd; + // rs + else if (strncmp("rs", value, value_len)) + over->reg = state->rs; + // rt + else if (strncmp("rt", value, value_len)) + over->reg = state->rt; + + // fd + else if (strncmp("fd", value, value_len)) + over->fpreg = state->fd; + // fs + else if (strncmp("fs", value, value_len)) + over->fpreg = state->fs; + // ft + else if (strncmp("ft", value, value_len)) + over->fpreg = state->ft; + + // immd + else if (strncmp("immd", value, value_len)) + over->immd = state->immd; + // -immd + else if (strncmp("-immd", value, value_len)) + over->immd = -state->immd; + + // floating point register + else if (value_len > 2 && value[0] == '$' && value[1] == 'f') { + struct string temp = { + .str = value + 1, + .len = value_len - 1 + }; + if (gen_parse_fp_register(&over->fpreg, &temp)) + return -1; + } + + // register + else if (value_len > 1 && value[0] == '$') { + struct string temp = { + .str = value + 1, + .len = value_len - 1 + }; + if (gen_parse_register(&over->reg, &temp)) + return -1; + } + + // number + else + over->immd = antoi(value, value_len); + + return value_len; +} + +static int read_next_state(struct expr_ins_arg *arg, + struct gen_ins_state *state, + enum grammer_type type) +{ + switch (type) { + case GMR_RD: + // rd + if (arg->type != EXPR_INS_ARG_REGISTER) { + ERROR("expected a register"); + return 1; + } + if (gen_parse_register(&state->rd, &arg->reg)) + return 1; + break; + case GMR_RS: + // rs + if (arg->type != EXPR_INS_ARG_REGISTER) { + ERROR("expected a register"); + return 1; + } + if (gen_parse_register(&state->rs, &arg->reg)) + return 1; + break; + case GMR_RT: + // rt + if (arg->type != EXPR_INS_ARG_REGISTER) { + ERROR("expected a register"); + return 1; + } + if (gen_parse_register(&state->rt, &arg->reg)) + return 1; + break; + case GMR_FS: + // fs + if (arg->type != EXPR_INS_ARG_REGISTER) { + ERROR("expected a register"); + return 1; + } + if (gen_parse_fp_register(&state->fs, &arg->reg)) + return 1; + break; + case GMR_FT: + // ft + if (arg->type != EXPR_INS_ARG_REGISTER) { + ERROR("expected a register"); + return 1; + } + if (gen_parse_fp_register(&state->ft, &arg->reg)) + return 1; + break; + case GMR_FD: + // fd + if (arg->type != EXPR_INS_ARG_REGISTER) { + ERROR("expected a register"); + return 1; + } + if (gen_parse_fp_register(&state->fd, &arg->reg)) + return 1; + break; + case GMR_IMMD: + // immd + if (arg->type != EXPR_INS_ARG_IMMEDIATE) { + ERROR("expected an immediate"); + return 1; + } + state->immd = arg->immd; + break; + case GMR_CC: + // cc + if (arg->type != EXPR_INS_ARG_IMMEDIATE) { + ERROR("expected an immediate"); + return 1; + } + state->cc = arg->immd; + break; + case GMR_CODE: + // code + if (arg->type != EXPR_INS_ARG_IMMEDIATE) { + ERROR("expected an immediate"); + return 1; + } + state->code = arg->immd; + break; + case GMR_POS: + // pos + if (arg->type != EXPR_INS_ARG_IMMEDIATE) { + ERROR("expected an immediate"); + return 1; + } + state->pos = arg->immd; + break; + case GMR_SIZE: + // size + if (arg->type != EXPR_INS_ARG_IMMEDIATE) { + ERROR("expected an immediate"); + return 1; + } + // TODO: check valid size + state->size = arg->immd; + break; + case GMR_HB: + // hb + if (arg->type != EXPR_INS_ARG_IMMEDIATE) { + ERROR("expected an immediate"); + return 1; + } + state->hb = !!(arg->immd); + break; + case GMR_HINT: + // hint + if (arg->type != EXPR_INS_ARG_IMMEDIATE) { + ERROR("expected an immediate"); + return 1; + } + state->hint = arg-> immd; + break; + case GMR_OFFSET: + // offset + state->offset = 0; + if (arg->type == EXPR_INS_ARG_IMMEDIATE) + state->offset = arg->immd; + else if (arg->type == EXPR_INS_ARG_LABEL) + state->label = &arg->label; + else { + ERROR("invalid instruction"); + return 1; + } + break; + case GMR_OFFSET_BASE: + // offset(base) + if (arg->type != EXPR_INS_ARG_OFFSET) { + ERROR("expected an offset($base)"); + return 1; + } + state->offset = arg->offset.immd; + if (gen_parse_register(&state->base, &arg->offset.reg)) + return 1; + break; + case GMR_INDEX_BASE: + // index(base) + if (arg->type != EXPR_INS_ARG_OFFSET) { + ERROR("expected an index($base)"); + return 1; + } + state->index = arg->offset.immd; + if (gen_parse_register(&state->base, &arg->offset.reg)) + return 1; + break; + case GMR_TARGET: + // target + state->target = 0; + if (arg->type == EXPR_INS_ARG_IMMEDIATE) + state->target = arg->immd; + else if (arg->type == EXPR_INS_ARG_LABEL) + state->label = &arg->label; + else { + ERROR("invalid instruction"); + return 1; + } + break; + default: + break; + } + + return 0; +} + +int gen_read_grammer_state(struct generator *gen, + struct expr *const expr, + struct gen_ins_state *state, + struct mips32_grammer *grammer) +{ + + char *ptr = grammer->grammer; + uint32_t argi = 0; + + // read values into state + while (*ptr != '\0') { + struct expr_ins_arg *arg; + enum grammer_type type; + size_t consumed; + + if (argi >= expr->instruction.args_len) { + ERROR("not enough arguments passed"); + gen_output_expr(gen, expr); + return 1; + } + + arg = &expr->instruction.args[argi++]; + consumed = gen_parse_grammer_type(ptr, &type); + + if (consumed < 0) { + BUG("invalid grammer: %s", grammer); + return 1; + } + + if (read_next_state(arg, state, type)) { + gen_output_expr(gen, expr); + return 1; + } + + ptr += consumed; + + if (*ptr == ',') { + ptr++; + continue; + } + + if (*ptr != '\0') { + BUG("invalid grammer: %s", grammer); + return 1; + } + } + + return 0; +} + +static int write_next_state(struct gen_ins_state *state, + struct gen_ins_override *over, + union mips32_instruction *ins, + enum reference_type *reftype, + char *ptr) +{ + enum grammer_type type; + size_t consumed; + bool hc = false; + + consumed = gen_parse_grammer_type(ptr, &type); + + if (consumed < 0) { + BUG("invalid grammer: %s", ptr); + return -1; + } + + if (*(ptr + consumed) == '=') { + hc = true; + consumed += gen_parse_grammer_override(state, over, ptr); + + if (consumed < 0) { + BUG("invalid grammer: %s", ptr); + return -1; + } + } + + switch (type) { + case GMR_RD: + ins->rd = hc ? over->reg : state->rd; + break; + case GMR_RS: + ins->rs = hc ? over->reg : state->rs; + break; + case GMR_RT: + ins->rt = hc ? over->reg : state->rt; + break; + case GMR_FS: + ins->fs = hc ? over->fpreg : state->fs; + break; + case GMR_FT: + ins->ft = hc ? over->fpreg : state->ft; + break; + case GMR_FD: + ins->fd = hc ? over->fpreg : state->fd; + break; + case GMR_IMMD: + ins->immd = hc ? over->immd : state->immd; + break; + case GMR_CC: + ins->cc = state->cc; + break; + case GMR_CODE: + ins->code = state->code; + break; + case GMR_POS: + ins->shamt = state->pos; + break; + case GMR_SIZE: + ins->rd = state->size ? state->size - 1 : 0; + break; + case GMR_HB: + ins->hb = hc ? over->immd : state->hb; + break; + case GMR_HINT: + ins->rt = state->hint; + break; + case GMR_OFFSET: + ins->offset = state->offset; + *reftype = REF_MIPS_PC16; + break; + case GMR_OFFSET_BASE: + ins->offset = state->offset; + ins->rs = state->base; + *reftype = REF_MIPS_16; + break; + case GMR_INDEX_BASE: + ins->rt = state->index; + ins->rs = state->base; + break; + case GMR_TARGET: + ins->target = state->target; + *reftype = REF_MIPS_26; + break; + case GMR_HI: + ins->immd = state->target >> 16; + *reftype = REF_MIPS_HI16; + break; + case GMR_LO: + ins->immd = state->target & 0x0000FFFF; + *reftype = REF_MIPS_LO16; + break; + default: + break; + } + + return consumed; +} + + +int gen_write_grammer_state(struct generator *gen, + struct gen_ins_state *state, + char *grammer) +{ + enum reference_type reftype = REF_NONE; + struct gen_ins_override over; + char *ptr = grammer; + + union mips32_instruction ins; + + while (*ptr != '\0') { + int consumed; + + consumed = write_next_state(state, &over, + &ins, &reftype, ptr); + + if (consumed < 0) + return 1; + + ptr += consumed; + + if (*ptr == ',') { + ptr++; + continue; + } + + if (*ptr != '\0') { + BUG("invalid grammer: %s", grammer); + return 1; + } + } + + +} diff --git a/masm/gen/log.c b/masm/gen/log.c new file mode 100644 index 0000000..2df455b --- /dev/null +++ b/masm/gen/log.c @@ -0,0 +1,28 @@ +#include "../gen.h" + +void gen_output_expr(struct generator *gen, struct expr *expr) +{ + int line = expr->line_no, + len = expr->byte_end - expr->byte_start, + nl = true, + c = EOF; + FILE *file = gen->parser.lexer.file; + + fseek(file, expr->byte_start, SEEK_SET); + + while (len--) { + c = getc(file); + if (c == EOF || c == '\0') + break; + if (nl) { + fprintf(stderr, "\t%d | ", line); + line++; + nl = false; + } + if (c == '\n') + nl = true; + putc(c, stderr); + } + +} + diff --git a/masm/gen/section.c b/masm/gen/section.c new file mode 100644 index 0000000..44f83f8 --- /dev/null +++ b/masm/gen/section.c @@ -0,0 +1,156 @@ +#include "../gen.h" + +#include +#include +#include +#include + +struct section_default { + char *name; + int name_len; + + bool read; + bool write; + bool execute; + int alignment; +}; + +#define SECTION_DEFAULTS_LEN 7 +#define MAPPING(name, ...) {name, sizeof(name), __VA_ARGS__} +static const struct section_default section_defaults[SECTION_DEFAULTS_LEN] = { + MAPPING(".text", true, false, true, 4), + MAPPING(".code", true, false, true, 4), + MAPPING(".data", true, true, false, 1), + MAPPING(".stack", true, true, false, 1), + MAPPING(".rodata", true, false, false, 1), + MAPPING(".bss", true, true, false, 1), + MAPPING(".robss", true, false, false, 1), +}; + +static void section_get_default_perm(struct section *sec, const char *name) +{ + for (int i = 0; i < SECTION_DEFAULTS_LEN; i++) { + const struct section_default *defaults = §ion_defaults[i]; + if (strncasecmp(name, defaults->name, defaults->name_len)) + continue; + sec->read = defaults->read; + sec->write = defaults->write; + sec->execute = defaults->execute; + sec->align = defaults->alignment; + break; + } +} + +int gen_get_section(struct generator *gen, struct section **res, + struct string *name) +{ + /// find the section if it exists + for (size_t i = 0; i < gen->sections_len; i++) { + struct section *sec = &gen->sections[i]; + if (sec->name.len != name->len) + continue; + if (strcmp(sec->name.str, name->str) != 0) + continue; + *res = sec; + return 0; + } + + /// allocate a new one if it doesnt + size_t size = gen->sections_size ? gen->sections_size * 2 : 8; + void *new = realloc(gen->sections, size * sizeof(struct section)); + if (new == NULL) { + PERROR("cannot realloc"); + return 1; + } + + gen->sections_size = size; + gen->sections = new; + + struct section *sec = &gen->sections[gen->sections_len++]; + if (section_init(sec, name)) + return 1; + + *res = sec; + return 0; +} + +int section_init(struct section *sec, struct string *name) +{ + sec->len = 0; + sec->size = 0; + sec->align = 1; + sec->data = NULL; + sec->read = true; + sec->write = true; + sec->execute = false; + + // set defaults + section_get_default_perm(sec, name->str); + + // alloc reftab + if (reftab_init(&sec->reftab)) + return 1; + + // copy name + if (string_clone(&sec->name, name)) + return 1; + + return 0; +} + +int section_extend(struct section *section, size_t space) +{ + size_t newlen = section->len + space; + if (newlen < section->size) + return M_SUCCESS; + + size_t size = section->size ? section->size * 2 + newlen : newlen * 2; + void *new = realloc(section->data, size); + if (new == NULL) { + PERROR("cannot realloc"); + return M_ERROR; + } + section->size = size; + section->data = new; + + return M_SUCCESS; +} + +int section_push(struct section *section, void *data, size_t len) +{ + size_t newlen = section->len + len; + size_t zeros = newlen % section->align; + if (zeros) + zeros = section->align - zeros; + + if (section_extend(section, len + zeros)) + return M_ERROR; + + memset(section->data + section->len, 0, zeros); + memcpy(section->data + section->len + zeros, data, len); + section->len += len + zeros; + + return M_SUCCESS; +} + +int section_zero(struct section *section, size_t len) +{ + size_t zeros = section->len % section->align; + if (zeros) + zeros = section->align - zeros; + + if (section_extend(section, len + zeros)) + return M_ERROR; + + memset(section->data + section->len, 0, len + zeros); + section->len += len + zeros; + + return M_SUCCESS; +} + +void section_free(struct section *section) +{ + reftab_free(§ion->reftab); + string_free(§ion->name); + free(section->data); +} diff --git a/masm/reftab.c b/masm/tab/reftab.c similarity index 97% rename from masm/reftab.c rename to masm/tab/reftab.c index f8793e1..3eddc50 100644 --- a/masm/reftab.c +++ b/masm/tab/reftab.c @@ -1,7 +1,7 @@ #include #include -#include "tab.h" +#include "../tab.h" #define REFTAB_INIT_LEN 8 diff --git a/masm/symtab.c b/masm/tab/symtab.c similarity index 98% rename from masm/symtab.c rename to masm/tab/symtab.c index 990be46..a2aa1ea 100644 --- a/masm/symtab.c +++ b/masm/tab/symtab.c @@ -5,8 +5,7 @@ #include #include -#include "lex.h" -#include "tab.h" +#include "../tab.h" #define SYMTBL_INIT_LEN 24