Sandipan Das has uploaded this change for review. (
https://gem5-review.googlesource.com/c/public/gem5/+/16614
Change subject: arch-power: Fix fixed-point arithmetic multiply and divide
instructions
......................................................................
arch-power: Fix fixed-point arithmetic multiply and divide instructions
This fixes the following arithmetic instructions:
* Multiply Low Immediate (mulli)
* Multiply Low Word (mullw[o][.])
* Multiply High Word (mulhw[.])
* Multiply High Word Unsigned (mulhwu[.])
* Divide Word (divw[o][.])
* Divide Word Unsigned (divwu[o][.])
This also fixes disassembly generation for all of the above.
Change-Id: I46fd3751b86a7436a962f8b93f26d8343f215fed
Signed-off-by: Sandipan Das <[email protected]>
---
M src/arch/power/isa/decoder.isa
M src/arch/power/isa/formats/integer.isa
2 files changed, 91 insertions(+), 73 deletions(-)
diff --git a/src/arch/power/isa/decoder.isa b/src/arch/power/isa/decoder.isa
index fa52a38..059ad53 100644
--- a/src/arch/power/isa/decoder.isa
+++ b/src/arch/power/isa/decoder.isa
@@ -216,9 +216,8 @@
true);
7: mulli({{
- int32_t src = Ra_sw;
- int64_t prod = src * simm;
- Rt = (uint32_t)prod;
+ int64_t res = Ra_sd * simm;
+ Rt = res;
}});
}
@@ -562,67 +561,49 @@
// Arithmetic instructions all use source registers Ra and Rb,
// with destination register Rt.
- format IntArithOp {
+ format IntArithCheckRcOp {
75: mulhw({{
- int64_t prod = Ra_sd * Rb_sd;
- Rt = prod >> 32;
+ uint64_t res = (int64_t)Ra_sw * Rb_sw;
+ res = res >> 32;
+ Rt = res;
}});
+
11: mulhwu({{
- uint64_t prod = Ra_ud * Rb_ud;
- Rt = prod >> 32;
+ uint64_t res = (uint64_t)Ra_uw * Rb_uw;
+ res = res >> 32;
+ Rt = res;
}});
- 235: mullw({{ int64_t prod = Ra_sd * Rb_sd; Rt = prod; }});
- 747: mullwo({{
- int64_t src1 = Ra_sd;
- int64_t src2 = Rb;
- int64_t prod = src1 * src2;
- Rt = prod;
+
+ 235: mullw({{
+ int64_t res = (int64_t)Ra_sw * Rb_sw;
+ if (res != (int32_t)res) {
+ setOV = true;
+ }
+ Rt = res;
}},
true);
491: divw({{
int32_t src1 = Ra_sw;
int32_t src2 = Rb_sw;
- if ((src1 != 0x80000000 || src2 != 0xffffffff)
- && src2 != 0) {
- Rt = src1 / src2;
+ if ((src1 != INT32_MIN || src2 != -1) && src2 != 0) {
+ Rt = (uint32_t)(src1 / src2);
} else {
Rt = 0;
- }
- }});
-
- 1003: divwo({{
- int32_t src1 = Ra_sw;
- int32_t src2 = Rb_sw;
- if ((src1 != 0x80000000 || src2 != 0xffffffff)
- && src2 != 0) {
- Rt = src1 / src2;
- } else {
- Rt = 0;
- divSetOV = true;
+ setOV = true;
}
}},
true);
459: divwu({{
- uint32_t src1 = Ra_sw;
- uint32_t src2 = Rb_sw;
+ uint32_t src1 = Ra_uw;
+ uint32_t src2 = Rb_uw;
if (src2 != 0) {
Rt = src1 / src2;
} else {
Rt = 0;
+ setOV = true;
}
- }});
-
- 971: divwuo({{
- uint32_t src1 = Ra_sw;
- uint32_t src2 = Rb_sw;
- if (src2 != 0) {
- Rt = src1 / src2;
- } else {
- Rt = 0;
- divSetOV = true;
- }
}},
true);
}
diff --git a/src/arch/power/isa/formats/integer.isa
b/src/arch/power/isa/formats/integer.isa
index eac6db2..b4ec74f 100644
--- a/src/arch/power/isa/formats/integer.isa
+++ b/src/arch/power/isa/formats/integer.isa
@@ -106,17 +106,24 @@
}
'''
-computeDivOVCode = '''
- if (divSetOV) {
+setCACode = '''
+ if (setCA) {
+ xer.ca = 1;
+ xer.ca32 = 1;
+ } else {
+ xer.ca = 0;
+ xer.ca32 = 0;
+ }
+'''
+
+setOVCode = '''
+ if (setOV) {
xer.ov = 1;
+ xer.ov32 = 1;
xer.so = 1;
} else {
- if (findOverflow(32, %(result)s, %(inputa)s, %(inputb)s)) {
- xer.ov = 1;
- xer.so = 1;
- } else {
- xer.ov = 0;
- }
+ xer.ov = 0;
+ xer.ov32 = 0;
}
'''
@@ -319,39 +326,69 @@
// Instructions that use source registers Ra and Rb, with the result
// placed into Rt. Basically multiply and divide instructions. The
-// carry bit is never set, but overflow can be calculated. Division
-// explicitly sets the overflow bit in certain situations and this is
-// dealt with using the 'divSetOV' boolean in decoder.isa. We generate
-// two versions of each instruction to deal with the Rc bit.
-def format IntArithOp(code, computeOV = 0, inst_flags = []) {{
+// carry bit is never set, but overflow can be calculated. In certain
+// situations, the overflow bits have to be set and this is dealt with
+// using the 'setOV' boolean in decoder.isa.
+//
+// In case overflow is to be calculated, we generate four versions of
+// each instruction to deal with different combinations of having the
+// OE bit set or unset and the Rc bit set or unset too. Otherwise, we
+// generate two versions of each instruction to deal with the Rc bit.
+def format IntArithCheckRcOp(code, computeOV = 0, inst_flags = []) {{
# The result is always in Rt, but the source values vary
dict = {'result':'Rt', 'inputa':'src1', 'inputb':'src2'}
# Deal with setting the overflow flag
if computeOV:
- code = 'bool divSetOV = false;\n' + code
- code += computeDivOVCode % dict + setXERCode
+ # Setup the 4 code versions and add code to access XER if necessary
+ code = 'bool setOV M5_VAR_USED = false;\n' + code
+ code_rc1 = readXERCode + code + computeCR0Code % dict
+ code_oe1 = readXERCode + code + setOVCode + setXERCode
+ code_rc1_oe1 = readXERCode + code + setOVCode + setXERCode
+ code_rc1_oe1 += computeCR0Code % dict
- # Setup the 2 code versions and add code to access XER if necessary
- code_rc1 = readXERCode + code + computeCR0Code % dict
- if computeOV:
- code = readXERCode + code
+ # Generate the classes
+ (header_output, decoder_output, decode_block, exec_output) = \
+ GenAluOp(name, Name, 'IntArithOp', code, inst_flags,
+ CheckRcOeDecode, BasicConstructor)
+ (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
+ GenAluOp(name, Name + 'RcSet', 'IntArithOp', code_rc1,
inst_flags,
+ CheckRcOeDecode, IntRcConstructor)
+ (header_output_oe1, decoder_output_oe1, _, exec_output_oe1) = \
+ GenAluOp(name, Name + 'OeSet', 'IntArithOp', code_oe1,
inst_flags,
+ CheckRcOeDecode, IntOeConstructor)
+ (header_output_rc1_oe1, decoder_output_rc1_oe1, _,
+ exec_output_rc1_oe1) = \
+ GenAluOp(name, Name + 'RcSetOeSet', 'IntArithOp', code_rc1_oe1,
+ inst_flags, CheckRcOeDecode, IntRcOeConstructor)
- # Generate the classes
- (header_output, decoder_output, decode_block, exec_output) = \
- GenAluOp(name, Name, 'IntOp', code, inst_flags,
- CheckRcDecode, BasicConstructor)
+ # Finally, add to the other outputs
+ header_output += \
+ header_output_rc1 + header_output_oe1 + header_output_rc1_oe1
+ decoder_output += \
+ decoder_output_rc1 + decoder_output_oe1 +
decoder_output_rc1_oe1
+ exec_output += \
+ exec_output_rc1 + exec_output_oe1 + exec_output_rc1_oe1
- # Generate the second class
- (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
- GenAluOp(name, Name + 'RcSet', 'IntOp', code_rc1, inst_flags,
- CheckRcDecode, IntRcConstructor)
+ else:
+ # Setup the 2 code versions and add code to access XER if necessary
+ code_rc1 = readXERCode + code + computeCR0Code % dict
- # Finally, add to the other outputs
- header_output += header_output_rc1
- decoder_output += decoder_output_rc1
- exec_output += exec_output_rc1
+ # Generate the first class
+ (header_output, decoder_output, decode_block, exec_output) = \
+ GenAluOp(name, Name, 'IntArithOp', code, inst_flags,
+ CheckRcDecode, BasicConstructor)
+
+ # Generate the second class
+ (header_output_rc1, decoder_output_rc1, _, exec_output_rc1) = \
+ GenAluOp(name, Name + 'RcSet', 'IntArithOp', code_rc1,
inst_flags,
+ CheckRcDecode, IntRcConstructor)
+
+ # Finally, add to the other outputs
+ header_output += header_output_rc1
+ decoder_output += decoder_output_rc1
+ exec_output += exec_output_rc1
}};
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/16614
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: I46fd3751b86a7436a962f8b93f26d8343f215fed
Gerrit-Change-Number: 16614
Gerrit-PatchSet: 1
Gerrit-Owner: Sandipan Das <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev