Permalink
Browse files

Merge pull request #123 from sp1187/mips

Add le/gt MIPS branch/set macros, li.s macro, other small MIPS fixes
  • Loading branch information...
Kingcom committed Oct 9, 2017
2 parents 9699df1 + 5d8fce5 commit 0cf6fdc050c91268308919df78e462ca4b8c5434
@@ -96,6 +96,22 @@ CAssemblerCommand* generateMipsMacroAbs(Parser& parser, MipsRegisterData& regist
});
}

CAssemblerCommand* generateMipsMacroLiFloat(Parser& parser, MipsRegisterData& registers, MipsImmediateData& immediates, int flags)
{
const wchar_t* templateLiFloat = LR"(
li r1,float(%imm%)
mtc1 r1,%rs%
)";

std::wstring sraop, subop;

std::wstring macroText = preprocessMacro(templateLiFloat,immediates);
return createMacro(parser,macroText,flags, {
{ L"%imm%", immediates.secondary.expression.toString() },
{ L"%rs%", registers.frs.name },
});
}

CAssemblerCommand* generateMipsMacroLi(Parser& parser, MipsRegisterData& registers, MipsImmediateData& immediates, int flags)
{
const wchar_t* templateLi = LR"(
@@ -332,6 +348,7 @@ CAssemblerCommand* generateMipsMacroBranch(Parser& parser, MipsRegisterData& reg
bool unsigned_ = type == MIPSM_GEU || type == MIPSM_LTU;
bool immediate = (flags & MIPSM_IMM) != 0;
bool likely = (flags & MIPSM_LIKELY) != 0;
bool revcmp = (flags & MIPSM_REVCMP) != 0;

std::wstring op;
if (bne || beq)
@@ -353,7 +370,12 @@ CAssemblerCommand* generateMipsMacroBranch(Parser& parser, MipsRegisterData& reg
} else if (immediate && (beqz || bnez))
{
const wchar_t* templateImmediate = LR"(
.if (%imm% < -0x8000) || (%imm% >= 0x8000)
.if %revcmp% && %imm% == 0
slt%u% r1,r0,%rs%
.elseif %revcmp%
li r1,%imm%
slt%u% r1,r1,%rs%
.elseif (%imm% < -0x8000) || (%imm% >= 0x8000)
li r1,%imm%
slt%u% r1,%rs%,r1
.else
@@ -370,7 +392,11 @@ CAssemblerCommand* generateMipsMacroBranch(Parser& parser, MipsRegisterData& reg
} else if (beqz || bnez)
{
const wchar_t* templateRegister = LR"(
slt%u% r1,%rs%,%rt%
.if %revcmp%
slt%u% r1,%rt%,%rs%
.else
slt%u% r1,%rs%,%rt%
.endif
%op% r1,%dest%
)";

@@ -387,6 +413,7 @@ CAssemblerCommand* generateMipsMacroBranch(Parser& parser, MipsRegisterData& reg
return createMacro(parser,macroText,flags, {
{ L"%op%", op },
{ L"%u%", unsigned_ ? L"u" : L""},
{ L"%revcmp%", revcmp ? L"1" : L"0"},
{ L"%rs%", registers.grs.name },
{ L"%rt%", registers.grt.name },
{ L"%imm%", immediates.primary.expression.toString() },
@@ -406,6 +433,7 @@ CAssemblerCommand* generateMipsMacroSet(Parser& parser, MipsRegisterData& regist
bool lt = type == MIPSM_LT || type == MIPSM_LTU;
bool unsigned_ = type == MIPSM_GEU || type == MIPSM_LTU;
bool immediate = (flags & MIPSM_IMM) != 0;
bool revcmp = (flags & MIPSM_REVCMP) != 0;

if (immediate && (ne || eq))
{
@@ -439,7 +467,12 @@ CAssemblerCommand* generateMipsMacroSet(Parser& parser, MipsRegisterData& regist
} else if (immediate && (ge || lt))
{
const wchar_t* templateImmediateGeLt = LR"(
.if (%imm% < -0x8000) || (%imm% >= 0x8000)
.if %revcmp% && %imm% == 0
slt%u% %rd%,r0,%rs%
.elseif %revcmp%
li %rd%,%imm%
slt%u% %rd%,%rd%,%rs%
.elseif (%imm% < -0x8000) || (%imm% >= 0x8000)
li %rd%,%imm%
slt%u% %rd%,%rs%,%rd%
.else
@@ -454,7 +487,11 @@ CAssemblerCommand* generateMipsMacroSet(Parser& parser, MipsRegisterData& regist
} else if (ge)
{
const wchar_t* templateGe = LR"(
slt%u% %rd%,%rs%,%rt%
.if %revcmp%
slt%u% %rd%,%rt%,%rs%
.else
slt%u% %rd%,%rs%,%rt%
.endif
xori %rd%,%rd%,1
)";

@@ -469,6 +506,7 @@ CAssemblerCommand* generateMipsMacroSet(Parser& parser, MipsRegisterData& regist
{ L"%u%", unsigned_ ? L"u" : L""},
{ L"%eq%", eq ? L"1" : L"0" },
{ L"%ge%", ge ? L"1" : L"0" },
{ L"%revcmp%", revcmp ? L"1" : L"0" },
{ L"%rd%", registers.grd.name },
{ L"%rs%", registers.grs.name },
{ L"%rt%", registers.grt.name },
@@ -547,8 +585,8 @@ CAssemblerCommand* generateMipsMacroRotate(Parser& parser, MipsRegisterData& reg
std::wstring macroText = preprocessMacro(selectedTemplate,immediates);
return createMacro(parser,macroText,flags, {
{ L"%left%", left ? L"1" : L"0" },
{ L"%rs%", registers.grs.name },
{ L"%rd%", registers.grd.name },
{ L"%rs%", registers.grs.name },
{ L"%rt%", registers.grt.name },
{ L"%amount%", immediates.primary.expression.toString() },
});
@@ -569,6 +607,8 @@ const MipsMacroDefinition mipsMacros[] = {
{ L"la.u", L"s,I", &generateMipsMacroLi, MIPSM_IMM|MIPSM_UPPER },
{ L"la.l", L"s,I", &generateMipsMacroLi, MIPSM_IMM|MIPSM_LOWER },

{ L"li.s", L"S,I", &generateMipsMacroLiFloat, MIPSM_IMM },

{ L"lb", L"s,I", &generateMipsMacroLoadStore, MIPSM_LOAD|MIPSM_B|MIPSM_UPPER|MIPSM_LOWER },
{ L"lbu", L"s,I", &generateMipsMacroLoadStore, MIPSM_LOAD|MIPSM_BU|MIPSM_UPPER|MIPSM_LOWER },
{ L"lh", L"s,I", &generateMipsMacroLoadStore, MIPSM_LOAD|MIPSM_HW|MIPSM_UPPER|MIPSM_LOWER },
@@ -674,31 +714,53 @@ const MipsMacroDefinition mipsMacros[] = {

{ L"blt", L"s,t,I", &generateMipsMacroBranch, MIPSM_LT|MIPSM_DONTWARNDELAYSLOT },
{ L"blt", L"s,i,I", &generateMipsMacroBranch, MIPSM_LT|MIPSM_IMM|MIPSM_DONTWARNDELAYSLOT },
{ L"bgt", L"s,t,I", &generateMipsMacroBranch, MIPSM_LT|MIPSM_REVCMP|MIPSM_DONTWARNDELAYSLOT },
{ L"bgt", L"s,i,I", &generateMipsMacroBranch, MIPSM_LT|MIPSM_IMM|MIPSM_REVCMP|MIPSM_DONTWARNDELAYSLOT },
{ L"bltu", L"s,t,I", &generateMipsMacroBranch, MIPSM_LTU|MIPSM_DONTWARNDELAYSLOT },
{ L"bltu", L"s,i,I", &generateMipsMacroBranch, MIPSM_LTU|MIPSM_IMM|MIPSM_DONTWARNDELAYSLOT },
{ L"bgtu", L"s,t,I", &generateMipsMacroBranch, MIPSM_LTU|MIPSM_REVCMP|MIPSM_DONTWARNDELAYSLOT },
{ L"bgtu", L"s,i,I", &generateMipsMacroBranch, MIPSM_LTU|MIPSM_IMM|MIPSM_REVCMP|MIPSM_DONTWARNDELAYSLOT },
{ L"bge", L"s,t,I", &generateMipsMacroBranch, MIPSM_GE|MIPSM_DONTWARNDELAYSLOT },
{ L"bge", L"s,i,I", &generateMipsMacroBranch, MIPSM_GE|MIPSM_IMM|MIPSM_DONTWARNDELAYSLOT },
{ L"ble", L"s,t,I", &generateMipsMacroBranch, MIPSM_GE|MIPSM_REVCMP|MIPSM_DONTWARNDELAYSLOT },
{ L"ble", L"s,i,I", &generateMipsMacroBranch, MIPSM_GE|MIPSM_IMM|MIPSM_REVCMP|MIPSM_DONTWARNDELAYSLOT },
{ L"bgeu", L"s,t,I", &generateMipsMacroBranch, MIPSM_GEU|MIPSM_DONTWARNDELAYSLOT },
{ L"bgeu", L"s,i,I", &generateMipsMacroBranch, MIPSM_GEU|MIPSM_IMM|MIPSM_DONTWARNDELAYSLOT },
{ L"bleu", L"s,t,I", &generateMipsMacroBranch, MIPSM_GEU|MIPSM_REVCMP|MIPSM_DONTWARNDELAYSLOT },
{ L"bleu", L"s,i,I", &generateMipsMacroBranch, MIPSM_GEU|MIPSM_IMM|MIPSM_REVCMP|MIPSM_DONTWARNDELAYSLOT },
{ L"bne", L"s,i,I", &generateMipsMacroBranch, MIPSM_NE|MIPSM_IMM|MIPSM_DONTWARNDELAYSLOT },
{ L"beq", L"s,i,I", &generateMipsMacroBranch, MIPSM_EQ|MIPSM_IMM|MIPSM_DONTWARNDELAYSLOT },
{ L"bltl", L"s,t,I", &generateMipsMacroBranch, MIPSM_LT|MIPSM_DONTWARNDELAYSLOT|MIPSM_LIKELY },
{ L"bltl", L"s,i,I", &generateMipsMacroBranch, MIPSM_LT|MIPSM_IMM|MIPSM_DONTWARNDELAYSLOT|MIPSM_LIKELY },
{ L"bgtl", L"s,t,I", &generateMipsMacroBranch, MIPSM_LT|MIPSM_REVCMP|MIPSM_DONTWARNDELAYSLOT|MIPSM_LIKELY },
{ L"bgtl", L"s,i,I", &generateMipsMacroBranch, MIPSM_LT|MIPSM_IMM|MIPSM_REVCMP|MIPSM_DONTWARNDELAYSLOT|MIPSM_LIKELY },
{ L"bltul", L"s,t,I", &generateMipsMacroBranch, MIPSM_LTU|MIPSM_DONTWARNDELAYSLOT|MIPSM_LIKELY },
{ L"bltul", L"s,i,I", &generateMipsMacroBranch, MIPSM_LTU|MIPSM_IMM|MIPSM_DONTWARNDELAYSLOT|MIPSM_LIKELY },
{ L"bgtul", L"s,t,I", &generateMipsMacroBranch, MIPSM_LTU|MIPSM_REVCMP|MIPSM_DONTWARNDELAYSLOT|MIPSM_LIKELY },
{ L"bgtul", L"s,i,I", &generateMipsMacroBranch, MIPSM_LTU|MIPSM_IMM|MIPSM_REVCMP|MIPSM_DONTWARNDELAYSLOT|MIPSM_LIKELY },
{ L"bgel", L"s,t,I", &generateMipsMacroBranch, MIPSM_GE|MIPSM_DONTWARNDELAYSLOT|MIPSM_LIKELY },
{ L"bgel", L"s,i,I", &generateMipsMacroBranch, MIPSM_GE|MIPSM_IMM|MIPSM_DONTWARNDELAYSLOT|MIPSM_LIKELY },
{ L"blel", L"s,t,I", &generateMipsMacroBranch, MIPSM_GE|MIPSM_REVCMP|MIPSM_DONTWARNDELAYSLOT|MIPSM_LIKELY },
{ L"blel", L"s,i,I", &generateMipsMacroBranch, MIPSM_GE|MIPSM_IMM|MIPSM_REVCMP|MIPSM_DONTWARNDELAYSLOT|MIPSM_LIKELY },
{ L"bgeul", L"s,t,I", &generateMipsMacroBranch, MIPSM_GEU|MIPSM_DONTWARNDELAYSLOT|MIPSM_LIKELY },
{ L"bgeul", L"s,i,I", &generateMipsMacroBranch, MIPSM_GEU|MIPSM_IMM|MIPSM_DONTWARNDELAYSLOT|MIPSM_LIKELY },
{ L"bleul", L"s,t,I", &generateMipsMacroBranch, MIPSM_GEU|MIPSM_REVCMP|MIPSM_DONTWARNDELAYSLOT|MIPSM_LIKELY },
{ L"bleul", L"s,i,I", &generateMipsMacroBranch, MIPSM_GEU|MIPSM_IMM|MIPSM_REVCMP|MIPSM_DONTWARNDELAYSLOT|MIPSM_LIKELY },
{ L"bnel", L"s,i,I", &generateMipsMacroBranch, MIPSM_NE|MIPSM_IMM|MIPSM_DONTWARNDELAYSLOT|MIPSM_LIKELY },
{ L"beql", L"s,i,I", &generateMipsMacroBranch, MIPSM_EQ|MIPSM_IMM|MIPSM_DONTWARNDELAYSLOT|MIPSM_LIKELY },

{ L"slt", L"d,s,I", &generateMipsMacroSet, MIPSM_LT|MIPSM_IMM },
{ L"sltu", L"d,s,I", &generateMipsMacroSet, MIPSM_LTU|MIPSM_IMM },
{ L"sgt", L"d,s,I", &generateMipsMacroSet, MIPSM_LT|MIPSM_IMM|MIPSM_REVCMP },
{ L"sgtu", L"d,s,I", &generateMipsMacroSet, MIPSM_LTU|MIPSM_IMM|MIPSM_REVCMP },
{ L"sge", L"d,s,t", &generateMipsMacroSet, MIPSM_GE },
{ L"sge", L"d,s,I", &generateMipsMacroSet, MIPSM_GE|MIPSM_IMM },
{ L"sle", L"d,s,t", &generateMipsMacroSet, MIPSM_GE|MIPSM_REVCMP },
{ L"sle", L"d,s,I", &generateMipsMacroSet, MIPSM_GE|MIPSM_IMM|MIPSM_REVCMP },
{ L"sgeu", L"d,s,t", &generateMipsMacroSet, MIPSM_GEU },
{ L"sgeu", L"d,s,I", &generateMipsMacroSet, MIPSM_GEU|MIPSM_IMM },
{ L"sleu", L"d,s,t", &generateMipsMacroSet, MIPSM_GEU|MIPSM_REVCMP },
{ L"sleu", L"d,s,I", &generateMipsMacroSet, MIPSM_GEU|MIPSM_IMM|MIPSM_REVCMP },
{ L"sne", L"d,s,t", &generateMipsMacroSet, MIPSM_NE },
{ L"sne", L"d,s,I", &generateMipsMacroSet, MIPSM_NE|MIPSM_IMM },
{ L"seq", L"d,s,t", &generateMipsMacroSet, MIPSM_EQ },
@@ -35,6 +35,7 @@
#define MIPSM_LOAD 0x00010000
#define MIPSM_STORE 0x00020000
#define MIPSM_LIKELY 0x00040000
#define MIPSM_REVCMP 0x00080000

class Parser;

@@ -9,7 +9,7 @@ const tMipsOpcode MipsOpcodes[] = {
// 000 | *1 | *2 | J | JAL | BEQ | BNE | BLEZ | BGTZ | 00..07
// 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI | 08..0F
// 010 | *3 | *4 | *5 | --- | BEQL | BNEL | BLEZL | BGTZL | 10..17
// 011 | DADDI | DADDIU| LDL | LDR | --- | --- | LQ | SQ | 18..1F
// 011 | DADDI | DADDIU| LDL | LDR | --- | --- | LQ | SQ | 18..1F
// 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU | 20..27
// 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE | 28..2F
// 110 | LL | LWC1 | LV.S | --- | LLD | ULV.Q | LV.Q | LD | 30..37
@@ -62,8 +62,10 @@ const tMipsOpcode MipsOpcodes[] = {
{ "ldl", "t,(s)", MIPS_OP(0x1A), MA_MIPS3, MO_64BIT|MO_DELAYRT|MO_IGNORERTD },
{ "ldr", "t,i16(s)", MIPS_OP(0x1B), MA_MIPS3, MO_64BIT|MO_DELAYRT|MO_IGNORERTD },
{ "ldr", "t,(s)", MIPS_OP(0x1B), MA_MIPS3, MO_64BIT|MO_DELAYRT|MO_IGNORERTD },
{ "lq", "t,i16(s)", MIPS_OP(0x1E), MA_MIPS1, MO_DELAYRT|MO_IGNORERTD },
{ "sq", "t,i16(s)", MIPS_OP(0x1F), MA_MIPS1, MO_DELAYRT|MO_IGNORERTD },
{ "lq", "t,i16(s)", MIPS_OP(0x1E), MA_PS2, MO_DELAYRT|MO_IGNORERTD },
{ "lq", "t,(s)", MIPS_OP(0x1E), MA_PS2, MO_DELAYRT|MO_IGNORERTD },
{ "sq", "t,i16(s)", MIPS_OP(0x1F), MA_PS2, MO_DELAYRT|MO_IGNORERTD },
{ "sq", "t,(s)", MIPS_OP(0x1F), MA_PS2, MO_DELAYRT|MO_IGNORERTD },
{ "lb", "t,i16(s)", MIPS_OP(0x20), MA_MIPS1, MO_DELAYRT|MO_IGNORERTD },
{ "lb", "t,(s)", MIPS_OP(0x20), MA_MIPS1, MO_DELAYRT|MO_IGNORERTD },
{ "lh", "t,i16(s)", MIPS_OP(0x21), MA_MIPS1, MO_DELAYRT|MO_IGNORERTD },
@@ -252,8 +254,12 @@ const tMipsOpcode MipsOpcodes[] = {
{ "mtsa", "s", MIPS_SPECIAL(0x29), MA_PS2, 0 },
{ "slt", "d,s,t", MIPS_SPECIAL(0x2A), MA_MIPS1, 0 },
{ "slt", "s,t", MIPS_SPECIAL(0x2A), MA_MIPS1, MO_RSD},
{ "sgt", "d,t,s", MIPS_SPECIAL(0x2A), MA_MIPS1, 0 },
{ "sgt", "d,s", MIPS_SPECIAL(0x2A), MA_MIPS1, MO_RDT},
{ "sltu", "d,s,t", MIPS_SPECIAL(0x2B), MA_MIPS1, 0 },
{ "sltu", "s,t", MIPS_SPECIAL(0x2B), MA_MIPS1, MO_RSD },
{ "sgtu", "d,t,s", MIPS_SPECIAL(0x2B), MA_MIPS1, 0 },
{ "sgtu", "d,s", MIPS_SPECIAL(0x2B), MA_MIPS1, MO_RDT},
{ "dadd", "d,s,t", MIPS_SPECIAL(0x2C), MA_MIPS3, MO_64BIT },
{ "dadd", "s,t", MIPS_SPECIAL(0x2C), MA_MIPS3, MO_64BIT|MO_RSD },
{ "max", "d,s,t", MIPS_SPECIAL(0x2C), MA_PSP, 0 },
@@ -514,7 +514,7 @@ ExpressionValue expFuncLo(const std::wstring& funcName, const std::vector<Expres

GET_PARAM(parameters,0,value);

return ExpressionValue(value & 0xFFFF);
return ExpressionValue((int64_t)(int16_t)(value & 0xFFFF));
}

const ExpressionFunctionMap expressionFunctions = {
@@ -224,6 +224,8 @@ Below is a table of functions built into the assembler that can be used with the
| `float(val)` | cast int `val` to float |
| `frac(val)` | fractional part of float `val` |
| `abs(val)` | absolute value of int or float `val` |
| `hi(val)` | High half of 32-bit value `val`, adjusted for sign extension of low half (MIPS) |
| `lo(val)` | Sign-extended low half of 32-bit value `val` (MIPS) |
| `strlen(str)` | number of characters in `str` |
| `substr(str, start, count)` | substring of `str` from `start`, length `count` |
| `regex_match(source, regex)` | `1` if `regex` matched entire `source`, `0` otherwise|
@@ -687,6 +689,14 @@ la reg,Immediate

Loads Immediate into the specified register by using a combination of `lui`/`ori`, a simple `addiu`, or a simple `ori`, depending on the value of the Immediate.

### Immediate float macros

```
li.s reg,Immediate
```

Loads float value Immediate into the specified FP register by using a combination of `li` and `mtc1`.

### Memory macros

```
@@ -747,22 +757,38 @@ Stores an unaligned halfword/word/doubleword to the address in sourcereg using a
```
blt reg1,reg2,Dest
bltu reg1,reg2,Dest
bgt reg1,reg2,Dest
bgtu reg1,reg2,Dest
bge reg1,reg2,Dest
bgeu reg1,reg2,Dest
ble reg1,reg2,Dest
bleu reg1,reg2,Dest
bltl reg1,reg2,Dest
bltul reg1,reg2,Dest
bgtl reg1,reg2,Dest
bgtul reg1,reg2,Dest
bgel reg1,reg2,Dest
bgeul reg1,reg2,Dest
blel reg1,reg2,Dest
bleul reg1,reg2,Dest
blt reg,Imm,Dest
bltu reg,Imm,Dest
bgt reg,Imm,Dest
bgtu reg,Imm,Dest
bge reg,Imm,Dest
bgeu reg,Imm,Dest
ble reg,Imm,Dest
bleu reg,Imm,Dest
bne reg,Imm,Dest
beq reg,Imm,Dest
bltl reg,Imm,Dest
bltul reg,Imm,Dest
bgtl reg,Imm,Dest
bgtul reg,Imm,Dest
bgel reg,Imm,Dest
bgeul reg,Imm,Dest
blel reg,Imm,Dest
bleul reg,Imm,Dest
bnel reg,Imm,Dest
beql reg,Imm,Dest
```
@@ -774,12 +800,18 @@ If reg/reg1 is less than/greater than or equal to/equal to/not equal to reg2/Imm
```
slt reg1,reg2,Imm
sltu reg1,reg2,Imm
sgt reg1,reg2,Imm
sgtu reg1,reg2,Imm
sge reg1,reg2,Imm
sgeu reg1,reg2,Imm
sle reg1,reg2,Imm
sleu reg1,reg2,Imm
sne reg1,reg2,Imm
seq reg1,reg2,Imm
sge reg1,reg2,reg3
sgeu reg1,reg2,reg3
sle reg1,reg2,reg3
sleu reg1,reg2,reg3
sne reg1,reg2,reg3
seq reg1,reg2,reg3
```
Oops, something went wrong.

0 comments on commit 0cf6fdc

Please sign in to comment.