aboutsummaryrefslogtreecommitdiff
path: root/qtmips_machine
diff options
context:
space:
mode:
authorPavel Pisa <pisa@cmp.felk.cvut.cz>2019-07-02 17:14:38 +0200
committerPavel Pisa <pisa@cmp.felk.cvut.cz>2019-07-02 17:14:38 +0200
commit040c1998500d3b0b50b3ddef4fe93216563343a8 (patch)
treec05815e566cc82d4276128b974e1557cb0d56a51 /qtmips_machine
parentdce00ea47fd4100df97349fd2bf998169b05b74a (diff)
downloadqtmips-040c1998500d3b0b50b3ddef4fe93216563343a8.tar.gz
qtmips-040c1998500d3b0b50b3ddef4fe93216563343a8.tar.bz2
qtmips-040c1998500d3b0b50b3ddef4fe93216563343a8.zip
Teach simple embedded assembler .orig and .word directives.
Signed-off-by: Pavel Pisa <pisa@cmp.felk.cvut.cz>
Diffstat (limited to 'qtmips_machine')
-rw-r--r--qtmips_machine/instruction.cpp90
-rw-r--r--qtmips_machine/instruction.h9
2 files changed, 72 insertions, 27 deletions
diff --git a/qtmips_machine/instruction.cpp b/qtmips_machine/instruction.cpp
index 1d32f17..502fa81 100644
--- a/qtmips_machine/instruction.cpp
+++ b/qtmips_machine/instruction.cpp
@@ -1041,11 +1041,11 @@ static int parse_reg_from_string(QString str, uint *chars_taken = nullptr)
static void reloc_append(RelocExpressionList *reloc, QString fl, uint32_t inst_addr,
std::int64_t offset, const ArgumentDesc *adesc, uint *chars_taken = nullptr,
- int line = 0) {
+ int line = 0, int options = 0) {
uint bits = IMF_SUB_GET_BITS(adesc->loc);
uint shift = IMF_SUB_GET_SHIFT(adesc->loc);
QString expression = "";
- QString allowed_operators = "+-/*";
+ QString allowed_operators = "+-/*|&";
int i = 0;
for (; i < fl.size(); i++) {
QChar ch = fl.at(i);
@@ -1060,16 +1060,18 @@ static void reloc_append(RelocExpressionList *reloc, QString fl, uint32_t inst_a
}
reloc->append(new RelocExpression(inst_addr, expression, offset,
- adesc->min, adesc->max, shift, bits, adesc->shift, line));
+ adesc->min, adesc->max, shift, bits, adesc->shift, line, options));
if (chars_taken != nullptr) {
*chars_taken = i;
}
}
+#define CFS_OPTION_SILENT_MASK 0x100
+
ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize,
QString inst_base, QVector<QString> &inst_fields,
std::uint32_t inst_addr, RelocExpressionList *reloc,
- int line, bool pseudo_opt)
+ int line, bool pseudo_opt, int options)
{
int field = 0;
std::uint32_t inst_code = 0;
@@ -1144,7 +1146,7 @@ ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize,
val += std::strtoull(p, &r, 0);
chars_taken = r - p;
} else {
- reloc_append(reloc, fl, inst_addr, val, adesc, &chars_taken, line);
+ reloc_append(reloc, fl, inst_addr, val, adesc, &chars_taken, line, options);
val = 0;
}
break;
@@ -1161,7 +1163,7 @@ ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize,
chars_taken = r - p;
break;
} else {
- reloc_append(reloc, fl, val, inst_addr, adesc, &chars_taken, line);
+ reloc_append(reloc, fl, val, inst_addr, adesc, &chars_taken, line, options);
val = 0;
}
}
@@ -1169,25 +1171,29 @@ ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize,
field = -1;
break;
}
- if (val & ((1 << adesc->shift) - 1)) {
+ if ((val & ((1 << adesc->shift) - 1)) &&
+ !(options & CFS_OPTION_SILENT_MASK)) {
field = -1;
break;
}
+ int shift_right = adesc->shift + (options & 0xff);
if (adesc->min >= 0)
- val = (val >> adesc->shift) ;
+ val = (val >> shift_right) ;
else
- val = (std::uint64_t)((std::int64_t)val >> adesc->shift) ;
- if (adesc->min < 0) {
- if (((std::int64_t)val < adesc->min) ||
- ((std::int64_t)val > adesc->max)) {
- field = -1;
- break;
- }
- } else {
- if ((val < (std::uint64_t)adesc->min) ||
- (val > (std::uint64_t)adesc->max)) {
- field = -1;
- break;
+ val = (std::uint64_t)((std::int64_t)val >> shift_right) ;
+ if (!(options & CFS_OPTION_SILENT_MASK)) {
+ if (adesc->min < 0) {
+ if (((std::int64_t)val < adesc->min) ||
+ ((std::int64_t)val > adesc->max)) {
+ field = -1;
+ break;
+ }
+ } else {
+ if ((val < (std::uint64_t)adesc->min) ||
+ (val > (std::uint64_t)adesc->max)) {
+ field = -1;
+ break;
+ }
}
}
val = (val & ((1 << bits) - 1)) << shift;
@@ -1210,6 +1216,19 @@ ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize,
if ((inst_base == "NOP") && (inst_fields.size() == 0)) {
inst_code = 0;
ret = 4;
+ } else if (pseudo_opt) {
+ if (((inst_base == "LA") || (inst_base == "LI")) && (inst_fields.size() == 2)) {
+ if(code_from_string(code, buffsize, "LUI", inst_fields,
+ inst_addr, reloc, line, false,
+ CFS_OPTION_SILENT_MASK + 16) < 0)
+ return -1;
+ inst_fields.insert(1, "$0");
+ if (code_from_string(code + 1, buffsize - 4, "ORI", inst_fields,
+ inst_addr + 4, reloc, line, false,
+ CFS_OPTION_SILENT_MASK + 0) < 0)
+ return -1;
+ return 8;
+ }
}
if (buffsize >= 4)
*code = inst_code;
@@ -1218,7 +1237,7 @@ ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize,
ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize,
QString str, std::uint32_t inst_addr,
- RelocExpressionList *reloc, int line, bool pseudo_opt)
+ RelocExpressionList *reloc, int line, bool pseudo_opt, int options)
{
if (str_to_instruction_code_map.isEmpty())
instruction_from_string_build_base();
@@ -1270,12 +1289,35 @@ ssize_t Instruction::code_from_string(std::uint32_t *code, size_t buffsize,
return -1;
return code_from_string(code, buffsize, inst_base, inst_fields, inst_addr,
- reloc, line, pseudo_opt);
+ reloc, line, pseudo_opt, options);
}
bool Instruction::update(std::int64_t val, RelocExpression *relocexp) {
- std::int64_t mask = ((1 << relocexp->bits) - 1) << relocexp->lsb_bit;
+ std::int64_t mask = (((std::int64_t)1 << relocexp->bits) - 1) << relocexp->lsb_bit;
dt &= ~ mask;
- dt |= (((val + relocexp->offset) >> relocexp->shift) << relocexp->lsb_bit) & mask;
+ val += relocexp->offset;
+ if ((val & ((1 << relocexp->shift) - 1)) &&
+ !(relocexp->options & CFS_OPTION_SILENT_MASK)) {
+ return false;
+ }
+ int shift_right = relocexp->shift + (relocexp->options & 0xff);
+ if (relocexp->min >= 0)
+ val = (val >> shift_right) ;
+ else
+ val = (std::uint64_t)((std::int64_t)val >> shift_right);
+ if (!(relocexp->options & CFS_OPTION_SILENT_MASK)) {
+ if (relocexp->min < 0) {
+ if (((std::int64_t)val < relocexp->min) ||
+ ((std::int64_t)val > relocexp->max)) {
+ return false;
+ }
+ } else {
+ if (((std::uint64_t)val < (std::uint64_t)relocexp->min) ||
+ ((std::uint64_t)val > (std::uint64_t)relocexp->max)) {
+ return false;
+ }
+ }
+ }
+ dt |= (val << relocexp->lsb_bit) & mask;
return true;
}
diff --git a/qtmips_machine/instruction.h b/qtmips_machine/instruction.h
index 3e48fc2..76fca87 100644
--- a/qtmips_machine/instruction.h
+++ b/qtmips_machine/instruction.h
@@ -77,7 +77,8 @@ enum InstructionFlags {
struct RelocExpression {
inline RelocExpression(std::int32_t location, QString expression, std::int64_t offset, std::int64_t min,
- std::int64_t max, unsigned lsb_bit, unsigned bits, unsigned shift, int line) {
+ std::int64_t max, unsigned lsb_bit, unsigned bits, unsigned shift, int line,
+ int options) {
this->location = location;
this->expression = expression;
this->offset = offset;
@@ -87,6 +88,7 @@ struct RelocExpression {
this->bits = bits;
this->shift = shift;
this->line = line;
+ this->options = options;
}
std::int32_t location;
QString expression;
@@ -97,6 +99,7 @@ struct RelocExpression {
unsigned bits;
unsigned shift;
int line;
+ int options;
};
typedef QVector<RelocExpression *> RelocExpressionList;
@@ -148,12 +151,12 @@ public:
QString inst_base, QVector<QString> &inst_fields,
std::uint32_t inst_addr = 0,
RelocExpressionList *reloc = nullptr,
- int line = 0, bool pseudo_opt = false);
+ int line = 0, bool pseudo_opt = false, int options = 0);
static ssize_t code_from_string(std::uint32_t *code, size_t buffsize,
QString str, std::uint32_t inst_addr = 0,
RelocExpressionList *reloc = nullptr,
- int line = 0, bool pseudo_opt = false);
+ int line = 0, bool pseudo_opt = false, int options = 0);
bool update(std::int64_t val, RelocExpression *relocexp);
private: