diff options
| author | Xavi Del Campo <xavi.dcr@tutanota.com> | 2020-01-31 10:32:23 +0100 |
|---|---|---|
| committer | Xavi Del Campo <xavi.dcr@tutanota.com> | 2020-01-31 10:32:23 +0100 |
| commit | 7c24e9a9b02b04dcaf9507acb94091ea70a2c02d (patch) | |
| tree | c28d0748652ad4b4222309e46e6cfc82c0906220 /tools/spasm/opcode.c | |
| parent | a2b7b6bb1cc2f4a3258b7b2dbc92399d151f864d (diff) | |
| download | psxsdk-7c24e9a9b02b04dcaf9507acb94091ea70a2c02d.tar.gz | |
Imported pristine psxsdk-20190410 from official repo
Diffstat (limited to 'tools/spasm/opcode.c')
| -rw-r--r-- | tools/spasm/opcode.c | 2214 |
1 files changed, 2214 insertions, 0 deletions
diff --git a/tools/spasm/opcode.c b/tools/spasm/opcode.c new file mode 100644 index 0000000..a09c119 --- /dev/null +++ b/tools/spasm/opcode.c @@ -0,0 +1,2214 @@ +#include "spasm.h" + +struct +{ + char *name; + void (*func)(); +}instruction_table[] = +{ + {"add" ,INS_ADD}, + {"addi" ,INS_ADDI}, + {"addiu" ,INS_ADDIU}, + {"addu" ,INS_ADDU}, + {"and" ,INS_AND}, + {"andi" ,INS_ANDI}, + {"beq" ,INS_BEQ}, + {"bgez" ,INS_BGEZ}, + {"bgezal" ,INS_BGEZAL}, + {"bgtz" ,INS_BGTZ}, + {"blez" ,INS_BLEZ}, + {"bltz" ,INS_BLTZ}, + {"bltzal" ,INS_BLTZAL}, + {"bne" ,INS_BNE}, + {"break" ,INS_BREAK}, + {"cfc0" ,INS_CFC }, + {"cfc1" ,INS_CFC }, + {"cfc2" ,INS_CFC }, + {"cfc3" ,INS_CFC }, + {"cop0" ,INS_COP }, + {"cop1" ,INS_COP }, + {"cop2" ,INS_COP }, + {"cop3" ,INS_COP }, + {"ctc0" ,INS_CTC }, + {"ctc1" ,INS_CTC }, + {"ctc2" ,INS_CTC }, + {"ctc3" ,INS_CTC }, + {"div" ,INS_DIV}, + {"divu" ,INS_DIVU}, + {"j" ,INS_J}, + {"jal" ,INS_JAL}, + {"jalr" ,INS_JALR}, + {"jr" ,INS_JR}, + {"lb" ,INS_LB}, + {"lbu" ,INS_LBU}, + {"lh" ,INS_LH}, + {"lhu" ,INS_LHU}, + {"lui" ,INS_LUI}, + {"lw" ,INS_LW}, + {"lwc0" ,INS_LWC }, + {"lwc1" ,INS_LWC }, + {"lwc2" ,INS_LWC }, + {"lwc3" ,INS_LWC }, + {"lwl" ,INS_LWL}, + {"lwr" ,INS_LWR}, + {"mfc0" ,INS_MFC}, + {"mfc1" ,INS_MFC}, + {"mfc2" ,INS_MFC}, + {"mfc3" ,INS_MFC}, + {"mfhi" ,INS_MFHI}, + {"mflo" ,INS_MFLO}, + {"mtc0" ,INS_MTC }, + {"mtc1" ,INS_MTC }, + {"mtc2" ,INS_MTC }, + {"mtc3" ,INS_MTC }, + {"mthi" ,INS_MTHI}, + {"mtlo" ,INS_MTLO}, + {"mult" ,INS_MULT}, + {"multu" ,INS_MULTU}, + {"nor" ,INS_NOR}, + {"or" ,INS_OR}, + {"ori" ,INS_ORI}, + {"sb" ,INS_SB}, + {"sh" ,INS_SH}, + {"sll" ,INS_SLL}, + {"sllv" ,INS_SLLV}, + {"slt" ,INS_SLT}, + {"slti" ,INS_SLTI}, + {"sltiu" ,INS_SLTIU}, + {"sltu" ,INS_SLTU}, + {"sra" ,INS_SRA}, + {"srav" ,INS_SRAV}, + {"srl" ,INS_SRL}, + {"srlv" ,INS_SRLV}, + {"sub" ,INS_SUB}, + {"subu" ,INS_SUBU}, + {"sw" ,INS_SW}, + {"swc0" ,INS_SWC}, + {"swc1" ,INS_SWC}, + {"swc2" ,INS_SWC}, + {"swc3" ,INS_SWC}, + {"swl" ,INS_SWL}, + {"swr" ,INS_SWR}, + {"syscall" ,INS_SYSCALL}, + {"xor" ,INS_XOR}, + {"xori" ,INS_XORI}, + + {"b" ,INS_B}, + {"la" ,INS_LA}, + {"li" ,INS_LI}, + {"nop" ,INS_NOP}, + {"move" ,INS_MOVE}, + {"subi" ,INS_SUBI}, + {"subiu" ,INS_SUBIU}, + {"beqz" ,INS_BEQZ}, + {"bnez" ,INS_BNEZ}, + {"bal" ,INS_BAL}, + {"org" ,INS_ORG}, + {"include" ,INS_INCLUDE}, + {"incbin" ,INS_INCBIN}, + {"dcb" ,INS_DCB}, + {"db" ,INS_DB}, + {"dh" ,INS_DH}, + {"dw" ,INS_DW}, + {"align" ,INS_ALIGN}, + + {NULL}, +}; + +#define I_TYPE(op, rs, rt, imm) \ + ( (((op) & 63) << 26) | (((rs) & 31) << 21) | (((rt) & 31) << 16) | \ + ((imm) & 0xFFFF) ) + +#define J_TYPE(op, target) \ + ( (((op) & 63) << 26) | ((target) & 0x3FFFFFF) ) + +#define R_TYPE(op, rs, rt, rd, shamt, funct) \ + ( (((op) & 63) << 26) | (((rs) & 31) << 21) | (((rt) & 31) << 16) | \ + (((rd) & 31) << 11) | (((shamt) & 31) << 6) | \ + ((funct) & 63)) + +// copn = coprocessor number +// SET_DIS_CHECK() + +#define SET_DIS_CHECK() /* Argument type check. Placeholder, contains nothing for now. */ + +int set_delay_slot = 0; + +void OUTSEEK(unsigned int position) +{ + fseek(asmOut, position, SEEK_SET); +} + +void OUTBYTE(unsigned char b) +{ + if(curPass>0) + fputc(b, asmOut); + + curPc++; +} + +void OUTHALF(unsigned short h) +{ + if(curPass>0) + { + fputc(h&0xff, asmOut); + fputc(h>>8, asmOut); + } + + curPc += 2; +} + +void OUTWORD(unsigned int w) +{ + if(curPass>0) + { + fputc(w&0xff, asmOut); + fputc((w>>8)&0xff, asmOut); + fputc((w>>16)&0xff, asmOut); + fputc(w>>24, asmOut); + } + + curPc += 4; +} + +void OUTINS(unsigned int instruction) +{ + OUTWORD(instruction); + + if(set_delay_slot) + { + OUTWORD(0); + + set_delay_slot = 0; + } +} + + +void OUTSTRING(char *string) +{ + int stringt; + int esc=0; + + if(*string == '"') + stringt = 0; + else if(*string == '\'') + stringt = 1; + else + instruction_error("OUTSTRING <INTERNAL ERROR>. Not a string!"); + + string++; + + while(*string) + { + if(*string == '"') + { + if(stringt == 0 && !esc) + break; + + OUTBYTE('"'); + esc = 0; + } + else if(*string == '\'') + { + if(stringt == 1 && !esc) + break; + + OUTBYTE('\''); + esc = 0; + } + else if(*string == 'n') + { + if(esc) + OUTBYTE('\n'); + else + OUTBYTE('n'); + + esc = 0; + } + else if(*string == 't') + { + if(esc) + OUTBYTE('\t'); + else + OUTBYTE('t'); + + esc = 0; + } + else if(*string == 'r') + { + if(esc) + OUTBYTE('\r'); + else + OUTBYTE('r'); + + esc = 0; + } + else if(*string == '\\') + { + if(esc) + { + OUTBYTE('\\'); + esc = 0; + } + else + esc = 1; + } + else + { + if(esc) + instruction_error("Invalid escape sequence \\%c in string", *string); + + OUTBYTE(*string); + } + + string++; + } +} + +unsigned int OUTSIZE(void) +{ + int r; + int pos = ftell(asmOut); + fseek(asmOut, 0, SEEK_END); + r = ftell(asmOut); + fseek(asmOut, pos, SEEK_SET); + return r; +} + +unsigned short compute_branch(unsigned int imm) +{ + unsigned int off = imm - (curPc + 4); + //off >>= 2; + + if(curPass <= 0) + return 0; + + if(off >= 0x20000 && off < -0x20000) + instruction_error("Branch out of range. %04x", off); + + return (off>>2) & 0xFFFF; +} + +unsigned int compute_jump(unsigned int imm) +{ + if(curPass <= 0) + return 0; + + return (imm >> 2); +} + +struct +{ + int size; + int pos; + unsigned int *el; +}cannotPredict = {0, 0, NULL}; + +unsigned int compute_real_offset(unsigned int imm, unsigned int base, + unsigned int rt) +{ + int i, unpredictable=0; + unsigned short hipart; + unsigned short lopart; + + if(!find_label_ok()) + { + if(cannotPredict.size == cannotPredict.pos) + { + cannotPredict.size += 128; + cannotPredict.el = realloc(cannotPredict.el, cannotPredict.size * sizeof(int)); + } + + cannotPredict.el[cannotPredict.pos++] = curPc; + } + + for(i = 0; i < cannotPredict.pos; i++) + { + if(curPc == cannotPredict.el[i]) + { + unpredictable = 1; + break; + } + } + + if(!unpredictable && ((imm <= 0xFFFF) || (imm >= 0xFFFF8000 && imm <= 0xFFFFFFFF))) + return I_TYPE(0, base, rt, imm); + +//compute_real_offset_output_wide: + // li at, offset + // add at, at, base + // lw rt, 0(at) + hipart = (imm >> 16); + lopart = imm & 0xFFFF; + int t=(*curIns == 'l') ? rt : 1; + + // lw at, $CAFEBABE(zero) -> lui at, $CAFE, ori at, at, $BABE, lw at, 0(at) + // lw at, $CAFEBABE(v0) -> lui at, $CAFE, ori at, at, $BABE, lw at, 0(v0) + // sw at, $CAFEBABE -> + + if(base) + { + /*OUTINS( I_TYPE(15, 0, t, hipart)); // lui $t, (offset > 16) + + if(lopart || unpredictable) + OUTINS( I_TYPE (13, t, t, lopart)); // ori $t, $t, offset & 0xffff + + OUTINS( R_TYPE (0, t, base, t, 0, 33) ); // add $t, $t, base + return I_TYPE(0, t, rt, 0);*/ + +// SPASM is seriously broken regarding this.. + return I_TYPE(0, base, rt, imm); + } + + if(lopart >= 0x8000) + hipart++; + + OUTINS( I_TYPE(15, 0, t, hipart)); // lui $t, (offset > 16) + + return I_TYPE(0, t, rt, lopart); // XX rt, lopart(rt) +} + +void INS_ADD(void) +{ + unsigned int rd, rs, rt; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + // ADD rd, rs, rt -> rd = rs + rt + + if(insArgc == 2) + { + if(atoiT[1] == T_INTEGER) + return INS_ADDI(); + + rd = insArgv[0]; + rs = insArgv[0]; + rt = insArgv[1]; + } + else + { + if(atoiT[2] == T_INTEGER) + return INS_ADDI(); + + rd = insArgv[0]; + rs = insArgv[1]; + rt = insArgv[2]; + } + + OUTINS( R_TYPE (0, rs, rt, rd, 0, 32) ); +} + +void INS_ADDI(void) +{ + unsigned int rt, rs, imm; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + // ADDI rt, rs, imm -> rt = rs + imm; + + if(insArgc == 2) + { + rt = insArgv[0]; + rs = insArgv[0]; + imm = insArgv[1]; + } + else + { + rt = insArgv[0]; + rs = insArgv[1]; + imm = insArgv[2]; + } + + if(imm > 0x7FFF && imm < 0xFFFF0000) + instruction_warning("Immediate is possibly out of range."); + + OUTINS( I_TYPE (8, rs, rt, imm) ); +} + +void INS_ADDIU(void) +{ + unsigned int rt, rs, imm; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + // ADDIU rt, rs, imm -> rt = rs + imm; + + if(insArgc == 2) + { + rt = insArgv[0]; + rs = insArgv[0]; + imm = insArgv[1]; + } + else + { + rt = insArgv[0]; + rs = insArgv[1]; + imm = insArgv[2]; + } + + if(imm > 0x7FFF && imm < 0xFFFF0000) + instruction_warning("Immediate is possibly out of range."); + + OUTINS( I_TYPE (9, rs, rt, imm) ); +} + +void INS_ADDU(void) +{ + unsigned int rd, rs, rt; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + // ADDU rd, rs, rt -> rd = rs + rt + + if(insArgc == 2) + { + if(atoiT[1] == T_INTEGER) + return INS_ADDIU(); + + rd = insArgv[0]; + rs = insArgv[0]; + rt = insArgv[1]; + } + else + { + if(atoiT[2] == T_INTEGER) + return INS_ADDIU(); + + rd = insArgv[0]; + rs = insArgv[1]; + rt = insArgv[2]; + } + + OUTINS( R_TYPE (0, rs, rt, rd, 0, 33) ); +} + +void INS_AND(void) +{ + unsigned int rd, rs, rt; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + // AND rd, rs, rt -> rd = rs + rt + + if(insArgc == 2) + { + if(atoiT[1] == T_INTEGER) + return INS_ANDI(); + + rd = insArgv[0]; + rs = insArgv[0]; + rt = insArgv[1]; + } + else + { + if(atoiT[2] == T_INTEGER) + return INS_ANDI(); + + rd = insArgv[0]; + rs = insArgv[1]; + rt = insArgv[2]; + } + + OUTINS( R_TYPE (0, rs, rt, rd, 0, 36) ); +} + +void INS_ANDI(void) +{ + unsigned int rt, rs, imm; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + // ANDI rt, rs, imm -> rt = rs + imm; + + if(insArgc == 2) + { + rt = insArgv[0]; + rs = insArgv[0]; + imm = insArgv[1]; + } + else + { + rt = insArgv[0]; + rs = insArgv[1]; + imm = insArgv[2]; + } + + if(imm > 0xFFFF) + instruction_warning("Immediate is possibly out of range"); + + OUTINS( I_TYPE (12, rs, rt, imm) ); +} + +void INS_BEQ(void) +{ + unsigned int rt, rs, imm; + + if(insArgc != 3) + instruction_error("Wrong number of arguments"); + + rs = insArgv[0]; + rt = insArgv[1]; + imm = insArgv[2]; + + OUTINS( I_TYPE(4, rs, rt, compute_branch(imm)) ); +} + +void INS_BGEZ(void) +{ + unsigned int rs, imm; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + rs = insArgv[0]; + imm = insArgv[1]; + + OUTINS( I_TYPE(1, rs, 1, compute_branch(imm)) ); +} + +void INS_BGEZAL(void) +{ + unsigned int rs, imm; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + rs = insArgv[0]; + imm = insArgv[1]; + + OUTINS( I_TYPE(1, rs, 17, compute_branch(imm)) ); +} + +void INS_BGTZ(void) +{ + unsigned int rs, imm; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + rs = insArgv[0]; + imm = insArgv[1]; + + OUTINS( I_TYPE(7, rs, 0, compute_branch(imm)) ); +} + +void INS_BLEZ(void) +{ + unsigned int rs, imm; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + rs = insArgv[0]; + imm = insArgv[1]; + + OUTINS( I_TYPE(6, rs, 0, compute_branch(imm)) ); +} + +void INS_BLTZ(void) +{ + unsigned int rs, imm; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + rs = insArgv[0]; + imm = insArgv[1]; + + OUTINS( I_TYPE(1, rs, 0, compute_branch(imm)) ); +} + +void INS_BLTZAL(void) +{ + unsigned int rs, imm; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + rs = insArgv[0]; + imm = insArgv[1]; + + OUTINS( I_TYPE(1, rs, 16, compute_branch(imm)) ); +} + +void INS_BNE(void) +{ + unsigned int rt, rs, imm; + + if(insArgc != 3) + instruction_error("Wrong number of arguments"); + + rs = insArgv[0]; + rt = insArgv[1]; + imm = insArgv[2]; + + OUTINS( I_TYPE(5, rs, rt, compute_branch(imm)) ); +} + +void INS_BREAK(void) +{ + unsigned int imm = 0; + + if(insArgc > 1) + instruction_error("Too many arguments"); + + if(insArgc == 1) + imm = insArgv[0]; + + imm &= 0xFFFFF; + + OUTINS( (imm << 6) | 13 ); +} + +void INS_CFC(void) +{ + unsigned int rt, rd; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + rt = insArgv[0]; + rd = insArgv[1]; + + OUTINS ( R_TYPE(16 | copn, 2, rt, rd, 0, 0) ); +} + +void INS_COP(void) +{ + unsigned int cofun; + + if(insArgc != 1) + instruction_error("Wrong number of arguments"); + + cofun = insArgv[0]; + + OUTINS( ( (16 | copn) << 26) | (1<<25) | (cofun & 0x1FFFFFF)); +} + +void INS_CTC(void) +{ + unsigned int rt, rd; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + rt = insArgv[0]; + rd = insArgv[1]; + + OUTINS ( R_TYPE(16 | copn, 6, rt, rd, 0, 0) ); +} + +void INS_DIV(void) +{ + unsigned int rs, rt; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + rs = insArgv[0]; + rt = insArgv[1]; + + OUTINS ( R_TYPE(0, rs, rt, 0, 0, 26)); +} + +void INS_DIVU(void) +{ + unsigned int rs, rt; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + rs = insArgv[0]; + rt = insArgv[1]; + + OUTINS ( R_TYPE(0, rs, rt, 0, 0, 27)); +} + +void INS_J(void) +{ + if(insArgc != 1) + instruction_error("Wrong number of arguments"); + + OUTINS ( J_TYPE(2, compute_jump(insArgv[0]))); +} + +void INS_JAL(void) +{ + if(insArgc != 1) + instruction_error("Wrong number of arguments"); + + OUTINS ( J_TYPE(3, compute_jump(insArgv[0]))); +} + +void INS_JALR(void) +{ + unsigned int rd, rs; + + if(insArgc < 1) + instruction_error("Not enough arguments"); + if(insArgc > 2) + instruction_error("Too many arguments"); + + if(insArgc == 1) + { + rd = 31; // register ra + rs = insArgv[0]; + } + else + { + rd = insArgv[0]; + rs = insArgv[1]; + } + + OUTINS ( R_TYPE(0, rs, 0, rd, 0, 9)); +} + +void INS_JR(void) +{ + if(insArgc != 1) + instruction_error("Wrong number of arguments"); + + OUTINS ( R_TYPE(0, insArgv[0], 0, 0, 0, 8)); +} + +void INS_LB(void) +{ + unsigned int base, rt, offset; + + SET_DIS_CHECK(); + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rt = insArgv[0]; + offset = insArgv[1]; + base = 0; + } + else + { + rt = insArgv[0]; + offset = insArgv[1]; + base = insArgv[2]; + } + + OUTINS(R_TYPE(32, 0, 0, 0, 0, 0) | compute_real_offset(offset, base, rt)); +} + +void INS_LBU(void) +{ + unsigned int base, rt, offset; + + SET_DIS_CHECK(); + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rt = insArgv[0]; + offset = insArgv[1]; + base = 0; + } + else + { + rt = insArgv[0]; + offset = insArgv[1]; + base = insArgv[2]; + } + + OUTINS(R_TYPE(36, 0, 0, 0, 0, 0) | compute_real_offset(offset, base, rt)); +} + +void INS_LH(void) +{ + unsigned int base, rt, offset; + + SET_DIS_CHECK(); + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rt = insArgv[0]; + offset = insArgv[1]; + base = 0; + } + else + { + rt = insArgv[0]; + offset = insArgv[1]; + base = insArgv[2]; + } + + OUTINS(R_TYPE(33, 0, 0, 0, 0, 0) | compute_real_offset(offset, base, rt)); +} + +void INS_LHU(void) +{ + unsigned int base, rt, offset; + + SET_DIS_CHECK(); + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rt = insArgv[0]; + offset = insArgv[1]; + base = 0; + } + else + { + rt = insArgv[0]; + offset = insArgv[1]; + base = insArgv[2]; + } + + OUTINS(R_TYPE(37, 0, 0, 0, 0, 0) | compute_real_offset(offset, base, rt)); +} + +void INS_LUI(void) +{ + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + OUTINS(I_TYPE(15, 0, insArgv[0], insArgv[1])); +} + +void INS_LW(void) +{ + unsigned int base, rt, offset; + + SET_DIS_CHECK(); + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rt = insArgv[0]; + offset = insArgv[1]; + base = 0; + } + else + { + rt = insArgv[0]; + offset = insArgv[1]; + base = insArgv[2]; + } + + OUTINS(R_TYPE(35, 0, 0, 0, 0, 0) | compute_real_offset(offset, base, rt)); +} + +void INS_LWC(void) +{ + unsigned int base, rt, offset; + + SET_DIS_CHECK(); + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rt = insArgv[0]; + offset = insArgv[1]; + base = 0; + } + else + { + rt = insArgv[0]; + offset = insArgv[1]; + base = insArgv[2]; + } + + OUTINS(R_TYPE(48 | copn, 0, 0, 0, 0, 0) | compute_real_offset(offset, base, rt)); +} + +void INS_LWL(void) +{ + unsigned int base, rt, offset; + + SET_DIS_CHECK(); + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rt = insArgv[0]; + offset = insArgv[1]; + base = 0; + } + else + { + rt = insArgv[0]; + offset = insArgv[1]; + base = insArgv[2]; + } + + OUTINS(R_TYPE(34, 0, 0, 0, 0, 0) | compute_real_offset(offset, base, rt)); +} + +void INS_LWR(void) +{ + unsigned int base, rt, offset; + + SET_DIS_CHECK(); + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rt = insArgv[0]; + offset = insArgv[1]; + base = 0; + } + else + { + rt = insArgv[0]; + offset = insArgv[1]; + base = insArgv[2]; + } + + OUTINS(R_TYPE(38, 0, 0, 0, 0, 0) | compute_real_offset(offset, base, rt)); +} + +void INS_MFC(void) +{ + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + OUTINS(R_TYPE (16 | copn, 0, insArgv[0], insArgv[1], 0, 0)); +} + +void INS_MFHI(void) +{ + if(insArgc != 1) + instruction_error("Wrong number of arguments"); + + OUTINS(R_TYPE(0, 0, 0, insArgv[0], 0, 16)); +} + +void INS_MFLO(void) +{ + if(insArgc != 1) + instruction_error("Wrong number of arguments"); + + OUTINS(R_TYPE(0, 0, 0, insArgv[0], 0, 18)); +} + +void INS_MTC(void) +{ + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + OUTINS(R_TYPE (16 | copn, 4, insArgv[0], insArgv[1], 0, 0)); +} + +void INS_MTHI(void) +{ + if(insArgc != 1) + instruction_error("Wrong number of arguments"); + + OUTINS(R_TYPE(0, insArgv[0], 0, 0, 0, 17)); +} + +void INS_MTLO(void) +{ + if(insArgc != 1) + instruction_error("Wrong number of arguments"); + + OUTINS(R_TYPE(0, insArgv[0], 0, 0, 0, 19)); +} + +void INS_MULT(void) +{ + unsigned int rs, rt; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + rs = insArgv[0]; + rt = insArgv[1]; + + OUTINS(R_TYPE(0, rs, rt, 0, 0, 24)); +} + +void INS_MULTU(void) +{ + unsigned int rs, rt; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + rs = insArgv[0]; + rt = insArgv[1]; + + OUTINS(R_TYPE(0, rs, rt, 0, 0, 25)); +} + +void INS_NOR(void) +{ + unsigned int rd, rs, rt; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rd = insArgv[0]; + rs = insArgv[0]; + rt = insArgv[1]; + } + else + { + rd = insArgv[0]; + rs = insArgv[1]; + rt = insArgv[2]; + } + + OUTINS( R_TYPE (0, rs, rt, rd, 0, 39) ); +} + +void INS_OR(void) +{ + unsigned int rd, rs, rt; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + if(atoiT[1] == T_INTEGER) + return INS_ORI(); + + rd = insArgv[0]; + rs = insArgv[0]; + rt = insArgv[1]; + } + else + { + if(atoiT[2] == T_INTEGER) + return INS_ORI(); + + rd = insArgv[0]; + rs = insArgv[1]; + rt = insArgv[2]; + } + + OUTINS( R_TYPE (0, rs, rt, rd, 0, 37) ); +} + +void INS_ORI(void) +{ + unsigned int rt, rs, imm; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + // ANDI rt, rs, imm -> rt = rs + imm; + + if(insArgc == 2) + { + rt = insArgv[0]; + rs = insArgv[0]; + imm = insArgv[1]; + } + else + { + rt = insArgv[0]; + rs = insArgv[1]; + imm = insArgv[2]; + } + + if(imm > 0xFFFF) + instruction_warning("Immediate is possibly out of range"); + + OUTINS( I_TYPE (13, rs, rt, imm) ); +} + +void INS_SB(void) +{ + unsigned int base, rt, offset; + + SET_DIS_CHECK(); + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rt = insArgv[0]; + offset = insArgv[1]; + base = 0; + } + else + { + rt = insArgv[0]; + offset = insArgv[1]; + base = insArgv[2]; + } + + OUTINS(R_TYPE(40, 0, 0, 0, 0, 0) | compute_real_offset(offset, base, rt)); +} + +void INS_SH(void) +{ + unsigned int base, rt, offset; + + SET_DIS_CHECK(); + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rt = insArgv[0]; + offset = insArgv[1]; + base = 0; + } + else + { + rt = insArgv[0]; + offset = insArgv[1]; + base = insArgv[2]; + } + + OUTINS(R_TYPE(41, 0, 0, 0, 0, 0) | compute_real_offset(offset, base, rt)); +} + +void INS_SLL(void) +{ + unsigned int rd, rt, sa; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rd = insArgv[0]; + rt = insArgv[0]; + sa = insArgv[1]; + } + else + { + rd = insArgv[0]; + rt = insArgv[1]; + sa = insArgv[2]; + } + + OUTINS(R_TYPE(0, 0, rt, rd, sa, 0)); +} + +void INS_SLLV(void) +{ + unsigned int rd, rs, rt; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rd = insArgv[0]; + rt = insArgv[0]; + rs = insArgv[1]; + } + else + { + rd = insArgv[0]; + rt = insArgv[1]; + rs = insArgv[2]; + } + + OUTINS( R_TYPE (0, rs, rt, rd, 0, 4) ); +} + +void INS_SLT(void) +{ + unsigned int rd, rs, rt; + + if(insArgc != 3) + instruction_error("Wrong number of arguments"); + + if(atoiT[2] == T_INTEGER) + return INS_SLTI(); + + rd = insArgv[0]; + rs = insArgv[1]; + rt = insArgv[2]; + + OUTINS( R_TYPE (0, rs, rt, rd, 0, 42) ); +} + +void INS_SLTI(void) +{ + unsigned int imm, rs, rt; + + if(insArgc != 3) + instruction_error("Wrong number of arguments"); + + rt = insArgv[0]; + rs = insArgv[1]; + imm = insArgv[2]; + + if(imm > 0x7FFF && imm < 0xFFFF8000) + instruction_error("Immediate out of range."); + + OUTINS( I_TYPE (10, rs, rt, imm) ); +} + +void INS_SLTIU(void) +{ + unsigned int imm, rs, rt; + + if(insArgc != 3) + instruction_error("Wrong number of arguments"); + + rt = insArgv[0]; + rs = insArgv[1]; + imm = insArgv[2]; + + if(imm > 0x7FFF && imm < 0xFFFF8000) + instruction_error("Immediate out of range."); + + OUTINS( I_TYPE (11, rs, rt, imm) ); +} + +void INS_SLTU(void) +{ + unsigned int rd, rs, rt; + + if(insArgc != 3) + instruction_error("Wrong number of arguments"); + + if(atoiT[2] == T_INTEGER) + return INS_SLTIU(); + + rd = insArgv[0]; + rs = insArgv[1]; + rt = insArgv[2]; + + OUTINS( R_TYPE (0, rs, rt, rd, 0, 43) ); +} + +void INS_SRA(void) +{ + unsigned int rd, rt, sa; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rd = insArgv[0]; + rt = insArgv[0]; + sa = insArgv[1]; + } + else + { + rd = insArgv[0]; + rt = insArgv[1]; + sa = insArgv[2]; + } + + OUTINS(R_TYPE(0, 0, rt, rd, sa, 3)); +} + +void INS_SRAV(void) +{ + unsigned int rd, rs, rt; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rd = insArgv[0]; + rt = insArgv[0]; + rs = insArgv[1]; + } + else + { + rd = insArgv[0]; + rt = insArgv[1]; + rs = insArgv[2]; + } + + OUTINS( R_TYPE (0, rs, rt, rd, 0, 7) ); +} + +void INS_SRL(void) +{ + unsigned int rd, rt, sa; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rd = insArgv[0]; + rt = insArgv[0]; + sa = insArgv[1]; + } + else + { + rd = insArgv[0]; + rt = insArgv[1]; + sa = insArgv[2]; + } + + OUTINS(R_TYPE(0, 0, rt, rd, sa, 2)); +} + +void INS_SRLV(void) +{ + unsigned int rd, rs, rt; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rd = insArgv[0]; + rt = insArgv[0]; + rs = insArgv[1]; + } + else + { + rd = insArgv[0]; + rt = insArgv[1]; + rs = insArgv[2]; + } + + OUTINS( R_TYPE (0, rs, rt, rd, 0, 6) ); +} + +void INS_SUB(void) +{ + unsigned int rd, rs, rt; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + + if(insArgc == 2) + { + if(atoiT[1] == T_INTEGER) + return INS_SUBI(); + + rd = insArgv[0]; + rs = insArgv[0]; + rt = insArgv[1]; + } + else + { + if(atoiT[2] == T_INTEGER) + return INS_SUBI(); + + rd = insArgv[0]; + rs = insArgv[1]; + rt = insArgv[2]; + } + + OUTINS( R_TYPE (0, rs, rt, rd, 0, 34) ); +} + +void INS_SUBU(void) +{ + unsigned int rd, rs, rt; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + // ADD rd, rs, rt -> rd = rs + rt + + if(insArgc == 2) + { + if(atoiT[1] == T_INTEGER) + return INS_SUBIU(); + + rd = insArgv[0]; + rs = insArgv[0]; + rt = insArgv[1]; + } + else + { + if(atoiT[2] == T_INTEGER) + return INS_SUBIU(); + + rd = insArgv[0]; + rs = insArgv[1]; + rt = insArgv[2]; + } + + OUTINS( R_TYPE (0, rs, rt, rd, 0, 35) ); +} + +void INS_SW(void) +{ + unsigned int base, rt, offset; + + SET_DIS_CHECK(); + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rt = insArgv[0]; + offset = insArgv[1]; + base = 0; + } + else + { + rt = insArgv[0]; + offset = insArgv[1]; + base = insArgv[2]; + } + + OUTINS(R_TYPE(43, 0, 0, 0, 0, 0) | compute_real_offset(offset, base, rt)); +} + +void INS_SWC(void) +{ + unsigned int base, rt, offset; + + SET_DIS_CHECK(); + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rt = insArgv[0]; + offset = insArgv[1]; + base = 0; + } + else + { + rt = insArgv[0]; + offset = insArgv[1]; + base = insArgv[2]; + } + + OUTINS(R_TYPE(56 | copn, 0, 0, 0, 0, 0) | compute_real_offset(offset, base, rt)); +} + +void INS_SWL(void) +{ + unsigned int base, rt, offset; + + SET_DIS_CHECK(); + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rt = insArgv[0]; + offset = insArgv[1]; + base = 0; + } + else + { + rt = insArgv[0]; + offset = insArgv[1]; + base = insArgv[2]; + } + + OUTINS(R_TYPE(42, 0, 0, 0, 0, 0) | compute_real_offset(offset, base, rt)); +} + +void INS_SWR(void) +{ + unsigned int base, rt, offset; + + SET_DIS_CHECK(); + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rt = insArgv[0]; + offset = insArgv[1]; + base = 0; + } + else + { + rt = insArgv[0]; + offset = insArgv[1]; + base = insArgv[2]; + } + + OUTINS(R_TYPE(46, 0, 0, 0, 0, 0) | compute_real_offset(offset, base, rt)); +} + +void INS_SYSCALL(void) +{ + unsigned int imm = 0; + + if(insArgc > 1) + instruction_error("Too many arguments"); + + if(insArgc == 1) + imm = insArgv[0]; + + imm &= 0xFFFFF; + + OUTINS( (imm << 6) | 12 ); +} + +void INS_XOR(void) +{ + unsigned int rd, rs, rt; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + if(atoiT[1] == T_INTEGER) + return INS_XORI(); + + rd = insArgv[0]; + rs = insArgv[0]; + rt = insArgv[1]; + } + else + { + if(atoiT[2] == T_INTEGER) + return INS_XORI(); + + rd = insArgv[0]; + rs = insArgv[1]; + rt = insArgv[2]; + } + + OUTINS( R_TYPE (0, rs, rt, rd, 0, 38) ); +} + +void INS_XORI(void) +{ + unsigned int rt, rs, imm; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rt = insArgv[0]; + rs = insArgv[0]; + imm = insArgv[1]; + } + else + { + rt = insArgv[0]; + rs = insArgv[1]; + imm = insArgv[2]; + } + + if(imm > 0xFFFF) + instruction_warning("Immediate is possibly out of range"); + + OUTINS( I_TYPE (14, rs, rt, imm) ); +} + +// ***** PSEUDO INSTRUCTIONS ***** + +void INS_B(void) +{ + unsigned int imm; + + if(insArgc != 1) + instruction_error("Wrong number of arguments"); + + imm = insArgv[0]; + + OUTINS( I_TYPE(4, 0, 0, compute_branch(imm)) ); // <- beq zero, zero, imm +} + +/*void INS_LI(void) +{ + unsigned int rd, imm; + unsigned short lopart, hipart; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + rd = insArgv[0]; + imm = insArgv[1]; + + hipart = imm >> 16; + lopart = imm & 0xFFFF; + + if(atoiT[1] == T_INTEGER && imm >= 0 && imm <= 0xFFFF) + OUTINS(I_TYPE(13, 0, rd, lopart)); // ori $rd, $zero, imm + else + { + if(lopart >= 0x8000) + hipart++; + + OUTINS( I_TYPE(15, 0, rd, hipart)); // lui $rd, (imm > 16) + OUTINS( I_TYPE (9, rd, rd, lopart)); // addiu $rd, $rd, imm & 0xffff + } +}*/ + +void INS_LI(void) +{ + int i; + unsigned int rd, imm; + unsigned short lopart, hipart; + int unpredictable=0; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + rd = insArgv[0]; + imm = insArgv[1]; + + hipart = imm >> 16; + lopart = imm & 0xFFFF; + + if(!find_label_ok()) + { + if(cannotPredict.size == cannotPredict.pos) + { + cannotPredict.size += 128; + cannotPredict.el = realloc(cannotPredict.el, cannotPredict.size * sizeof(int)); + } + + cannotPredict.el[cannotPredict.pos++] = curPc; + } + + for(i = 0; i < cannotPredict.pos; i++) + { + if(curPc == cannotPredict.el[i]) + { + unpredictable = 1; + break; + } + } + + if(/*atoiT[1] == T_INTEGER &&*/ !unpredictable && imm >= 0 && imm <= 0xFFFF) + OUTINS(I_TYPE(13, 0, rd, lopart)); // ori $rd, $zero, imm + else if(!unpredictable && !lopart) + OUTINS(I_TYPE(15, 0, rd, hipart)); + else + { + // if(lopart >= 0x8000) + // hipart++; + + OUTINS( I_TYPE(15, 0, rd, hipart)); // lui $rd, (imm > 16) + + // OUTINS( I_TYPE(9, rd, rd, lopart)); // addiu $rd, $rd, imm & 0xffff + OUTINS( I_TYPE (13, rd, rd, lopart)); // ori $rd, $rd, imm & 0xffff + } + +} + +void INS_LA(void) +{ + int i; + unsigned int rd, imm; + unsigned short lopart, hipart; + int unpredictable=0; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + rd = insArgv[0]; + imm = insArgv[1]; + + hipart = imm >> 16; + lopart = imm & 0xFFFF; + + if(!find_label_ok()) + { + if(cannotPredict.size == cannotPredict.pos) + { + cannotPredict.size += 128; + cannotPredict.el = realloc(cannotPredict.el, cannotPredict.size * sizeof(int)); + } + + cannotPredict.el[cannotPredict.pos++] = curPc; + } + + for(i = 0; i < cannotPredict.pos; i++) + { + if(curPc == cannotPredict.el[i]) + { + unpredictable = 1; + break; + } + } + + if(/*atoiT[1] == T_INTEGER &&*/ !unpredictable && imm >= 0 && imm <= 0xFFFF) + OUTINS(I_TYPE(13, 0, rd, lopart)); // ori $rd, $zero, imm + //else if(!unpredictable && !lopart) + // OUTINS(I_TYPE(15, 0, rd, hipart)); + else + { + if(lopart >= 0x8000) + hipart++; + + OUTINS( I_TYPE(15, 0, rd, hipart)); // lui $rd, (imm > 16) + + OUTINS( I_TYPE(9, rd, rd, lopart)); // addiu $rd, $rd, imm & 0xffff +// OUTINS( I_TYPE (13, rd, rd, lopart)); // ori $rd, $rd, imm & 0xffff + } + +} + +/*void INS_LA(void) +{ + INS_LI(); // The LI and LA pseudo-instructions are the same thing in SPASM +}*/ + +void INS_NOP(void) +{ + OUTINS(0); +} + +void INS_MOVE(void) +{ + unsigned int rd, rs; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + rd = insArgv[0]; + rs = insArgv[1]; + + OUTINS( R_TYPE (0, rs, 0, rd, 0, 33) ); // addu $rd, $rs, $zero +} + +void INS_SUBI(void) +{ +// just like ADDI, but switches the sign of the immediate + + unsigned int rt, rs, imm; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + + if(insArgc == 2) + { + rt = insArgv[0]; + rs = insArgv[0]; + imm = -insArgv[1]; + } + else + { + rt = insArgv[0]; + rs = insArgv[1]; + imm = -insArgv[2]; + } + + if(imm > 0x7FFF && imm < 0xFFFF0000) + instruction_warning("Immediate is possibly out of range"); + + OUTINS( I_TYPE (8, rs, rt, imm) ); +} + +void INS_SUBIU(void) +{ + unsigned int rt, rs, imm; + + if(insArgc < 2) + instruction_error("Not enough arguments"); + if(insArgc > 3) + instruction_error("Too many arguments"); + + if(insArgc == 2) + { + rt = insArgv[0]; + rs = insArgv[0]; + imm = -insArgv[1]; + } + else + { + rt = insArgv[0]; + rs = insArgv[1]; + imm = -insArgv[2]; + } + + if(imm > 0x7FFF && imm < 0xFFFF0000) + instruction_warning("Immediate is possibly out of range"); + + OUTINS( I_TYPE (9, rs, rt, imm) ); +} + +void INS_BEQZ(void) +{ + unsigned int rt, imm; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + rt = insArgv[0]; + imm = insArgv[1]; + + OUTINS( I_TYPE(4, rt, 0, compute_branch(imm)) ); // <- beq zero, rt, imm +// OUTINS( I_TYPE(4, rs, rt, compute_branch(imm)) ); + +} + +void INS_BNEZ(void) +{ + unsigned int rt, imm; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + rt = insArgv[0]; + imm = insArgv[1]; + + OUTINS( I_TYPE(5,rt, 0, compute_branch(imm)) ); // <- bne zero, rt, imm +} + +void INS_BAL(void) +{ + unsigned int imm; + + if(insArgc != 1) + instruction_error("Wrong number of arguments"); + + imm = insArgv[0]; + + OUTINS( I_TYPE(1, 0, 17, compute_branch(imm)) ); //bgezal $zero, imm +} + +void INS_ORG(void) +{ + if(insArgc != 1) + instruction_error("Wrong number of arguments"); + + //if(!first_instruction) + // instruction_error("ORG is not the first instruction"); + + curPc = insArgv[0]; + startAddress = insArgv[0]; + org_found = 1; +} + +void INS_INCBIN(void) +{ + FILE *f; + char *path, *cp; + int sz; + + + if(insArgc != 1) + instruction_error("Wrong number of arguments"); + + path = rawArgv[0]; + + if(*path == '"') + { + path++; + if((cp = strrchr(path, '"'))) + *cp = '\0'; + } + else if(*path == '\'') + { + path++; + if((cp = strrchr(path, '\''))) + *cp = '\0'; + } + + //printf("DEBUG(INCBIN): including %s\n", path); + + f = spasm_fopen(path, "rb"); + + if(!f) + instruction_error("Could not open \"%s\"", path); + + fseek(f, 0, SEEK_END); + sz = ftell(f); + fseek(f, 0, SEEK_SET); + + if(curPass <= 0) + curPc += sz; + else + { + for(;sz;sz--) + OUTBYTE(fgetc(f)); + } + + fclose(f); +} + +void INS_DCB(void) +{ + unsigned int num, value; + + if(insArgc != 2) + instruction_error("Wrong number of arguments"); + + num = insArgv[0]; + value = insArgv[1]; + + if(num & (1<<31)) + { + instruction_warning("Negative number of values, ignoring instruction"); + + return; + } + + if(curPass <= 0) + curPc += num; + else + { + for(;num;num--) + OUTBYTE(value); + } +} + +void INS_DB(void) +{ + int i; + + for(i = 0; i < insArgc; i++) + { + if(rawArgv[i][0] == '"' || rawArgv[i][0] == '\'') + OUTSTRING(rawArgv[i]); + else + OUTBYTE(insArgv[i] & 0xFF); + } +} + +void INS_DH(void) +{ + int i; + + for(i = 0; i < insArgc; i++) + { + if(rawArgv[i][0] == '"' || rawArgv[i][0] == '\'') + OUTSTRING(rawArgv[i]); + else + OUTHALF(insArgv[i] & 0xFFFF); + } +} + +void INS_DW(void) +{ + int i; + + for(i = 0; i < insArgc; i++) + { + if(rawArgv[i][0] == '"' || rawArgv[i][0] == '\'') + OUTSTRING(rawArgv[i]); + else + OUTWORD(insArgv[i]); + } +} + +void INS_ALIGN(void) +{ + unsigned int unit; + unsigned int delta; + + if(insArgc != 1) + instruction_error("Wrong number of arguments"); + + unit = insArgv[0]; + + if(unit <= 0) + instruction_error("Alignment unit cannot be equal to zero or negative"); + + if((curPc % unit)) + { + delta = (unit - (curPc % unit)) % unit; + + if(curPass <= 0) + curPc += delta; + else + { + for(;delta;delta--) + OUTBYTE(0); + } + } +} + +void INS_INCLUDE(void) +{ + int i, l, o; + int sz; + int tsz; + FILE *f; + char *path; + char *cp; + char *newtext; + + if(insArgc != 1) + instruction_error("Wrong number of arguments"); + + if(curPass <= 0) + { + + path = rawArgv[0]; + + if(*path == '"') + { + path++; + if((cp = strrchr(path, '"'))) + *cp = '\0'; + } + else if(*path == '\'') + { + path++; + if((cp = strrchr(path, '\''))) + *cp = '\0'; + } + + f = spasm_fopen(path, "rb"); + + if(!f) + instruction_error("Could not open %s", path); + + //printf("DEBUG(INCLUDE): Including %s, line %d\n", path, line_number); + + fseek(f, 0, SEEK_END); + sz = ftell(f); + fseek(f, 0, SEEK_SET); + + tsz = strlen(curText); + + newtext = malloc(sz + tsz + 1); + + for(i = 0, l = 1; l < line_number; i++) + { + if(curText[i] == '\n') + l++; + + newtext[i] = curText[i]; + } + + fread(&newtext[i], sizeof(char), sz, f); + + o = i+sz; + + if(newtext[i+sz-1] != '\n') + { + instruction_warning("No newline found at end of file %s", path); + newtext[o++] = '\n'; + } + + + for(; curText[i] != '\n'; i++); + + i++; + newtext[o] = '\0'; + + strcat(newtext, &curText[i]); + + free(curText); + curText = newtext; + } +} + +void INS_BLANK(void) +{ + +} + +void *get_instruction(char *name) +{ + int i; + + + for(i = 0; instruction_table[i].name; i++) + { + //printf("name = ^%s$, iname = ^%s$\n", name, instruction_table[i].name); + + if(strcasecmp(name, instruction_table[i].name) == 0) + { + // printf("di sranron\n"); + return instruction_table[i].func; + } + } + + return NULL; +} |
