| // Copyright 2014 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package armasm |
| |
| import ( |
| "encoding/binary" |
| "strings" |
| "testing" |
| ) |
| |
| func TestObjdumpARMTestdata(t *testing.T) { testObjdumpARM(t, testdataCases(t)) } |
| func TestObjdumpARMManual(t *testing.T) { testObjdumpARM(t, hexCases(t, objdumpManualTests)) } |
| func TestObjdumpARMCond(t *testing.T) { testObjdumpARM(t, condCases(t)) } |
| func TestObjdumpARMUncond(t *testing.T) { testObjdumpARM(t, uncondCases(t)) } |
| func TestObjdumpARMVFP(t *testing.T) { testObjdumpARM(t, vfpCases(t)) } |
| |
| // objdumpManualTests holds test cases that will be run by TestObjdumpARMManual. |
| // If you are debugging a few cases that turned up in a longer run, it can be useful |
| // to list them here and then use -run=Manual, particularly with tracing enabled. |
| // Note that these are byte sequences, so they must be reversed from the usual |
| // word presentation. |
| var objdumpManualTests = ` |
| 002a9b1d |
| 001b9bed |
| 020b8ded |
| 003a9b1d |
| 060b8ded |
| fcde1100 |
| b4de1100 |
| bc480000 |
| 0b008de7 |
| 0b00ade7 |
| fdbcfaf7 |
| ` |
| |
| // allowedMismatchObjdump reports whether the mismatch between text and dec |
| // should be allowed by the test. |
| func allowedMismatchObjdump(text string, size int, inst *Inst, dec ExtInst) bool { |
| if hasPrefix(text, "error:") { |
| if hasPrefix(dec.text, unsupported...) || strings.Contains(dec.text, "invalid:") || strings.HasSuffix(dec.text, "^") || strings.Contains(dec.text, "f16.f64") || strings.Contains(dec.text, "f64.f16") { |
| return true |
| } |
| // word 4320F02C: libopcodes says 'nopmi {44}'. |
| if hasPrefix(dec.text, "nop") && strings.Contains(dec.text, "{") { |
| return true |
| } |
| } |
| |
| if hasPrefix(dec.text, "error:") && text == "undef" && inst.Enc == 0xf7fabcfd { |
| return true |
| } |
| |
| // word 00f02053: libopcodes says 'noppl {0}'. |
| if hasPrefix(dec.text, "nop") && hasPrefix(text, "nop") && dec.text == text+" {0}" { |
| return true |
| } |
| |
| // word F57FF04F. we say 'dsb #15', libopcodes says 'dsb sy'. |
| if hasPrefix(text, "dsb") && hasPrefix(dec.text, "dsb") { |
| return true |
| } |
| // word F57FF06F. we say 'isb #15', libopcodes says 'isb sy'. |
| if hasPrefix(text, "isb") && hasPrefix(dec.text, "isb") { |
| return true |
| } |
| // word F57FF053. we say 'dmb #3', libopcodes says 'dmb osh'. |
| if hasPrefix(text, "dmb") && hasPrefix(dec.text, "dmb") { |
| return true |
| } |
| |
| // word 992D0000. push/stmdb with no registers (undefined). |
| // we say 'stmdbls sp!, {}', libopcodes says 'pushls {}'. |
| if hasPrefix(text, "stmdb") && hasPrefix(dec.text, "push") && strings.Contains(text, "{}") && strings.Contains(dec.text, "{}") { |
| return true |
| } |
| |
| // word 28BD0000. pop/ldm with no registers (undefined). |
| // we say 'ldmcs sp!, {}', libopcodes says 'popcs {}'. |
| if hasPrefix(text, "ldm") && hasPrefix(dec.text, "pop") && strings.Contains(text, "{}") && strings.Contains(dec.text, "{}") { |
| return true |
| } |
| |
| // word 014640F0. |
| // libopcodes emits #-0 for negative zero; we don't. |
| if strings.Replace(dec.text, "#-0", "#0", -1) == text || strings.Replace(dec.text, ", #-0", "", -1) == text { |
| return true |
| } |
| |
| // word 91EF90F0. we say 'strdls r9, [pc, #0]!' but libopcodes says 'strdls r9, [pc]'. |
| // word D16F60F0. we say 'strdle r6, [pc, #0]!' but libopcodes says 'strdle r6, [pc, #-0]'. |
| if strings.Replace(text, ", #0]!", "]", -1) == strings.Replace(dec.text, ", #-0]", "]", -1) { |
| return true |
| } |
| |
| // word 510F4000. we say apsr, libopcodes says CPSR. |
| if strings.Replace(dec.text, "CPSR", "apsr", -1) == text { |
| return true |
| } |
| |
| // word 06A4B059. |
| // for ssat and usat, libopcodes decodes asr #0 as asr #0 but the manual seems to say it should be asr #32. |
| // There is never an asr #0. |
| if strings.Replace(dec.text, ", asr #0", ", asr #32", -1) == text { |
| return true |
| } |
| |
| if len(dec.enc) >= 4 { |
| raw := binary.LittleEndian.Uint32(dec.enc[:4]) |
| |
| // word 21FFF0B5. |
| // the manual is clear that this is pre-indexed mode (with !) but libopcodes generates post-index (without !). |
| if raw&0x01200000 == 0x01200000 && strings.Replace(text, "!", "", -1) == dec.text { |
| return true |
| } |
| |
| // word C100543E: libopcodes says tst, but no evidence for that. |
| if strings.HasPrefix(dec.text, "tst") && raw&0x0ff00000 != 0x03100000 && raw&0x0ff00000 != 0x01100000 { |
| return true |
| } |
| |
| // word C3203CE8: libopcodes says teq, but no evidence for that. |
| if strings.HasPrefix(dec.text, "teq") && raw&0x0ff00000 != 0x03300000 && raw&0x0ff00000 != 0x01300000 { |
| return true |
| } |
| |
| // word D14C552E: libopcodes says cmp but no evidence for that. |
| if strings.HasPrefix(dec.text, "cmp") && raw&0x0ff00000 != 0x03500000 && raw&0x0ff00000 != 0x01500000 { |
| return true |
| } |
| |
| // word 2166AA4A: libopcodes says cmn but no evidence for that. |
| if strings.HasPrefix(dec.text, "cmn") && raw&0x0ff00000 != 0x03700000 && raw&0x0ff00000 != 0x01700000 { |
| return true |
| } |
| |
| // word E70AEEEF: libopcodes says str but no evidence for that. |
| if strings.HasPrefix(dec.text, "str") && len(dec.text) >= 5 && (dec.text[3] == ' ' || dec.text[5] == ' ') && raw&0x0e500018 != 0x06000000 && raw&0x0e500000 != 0x0400000 { |
| return true |
| } |
| |
| // word B0AF48F4: libopcodes says strd but P=0,W=1 which is unpredictable. |
| if hasPrefix(dec.text, "ldr", "str") && raw&0x01200000 == 0x00200000 { |
| return true |
| } |
| |
| // word B6CC1C76: libopcodes inexplicably says 'uxtab16lt r1, ip, r6, ROR #24' instead of 'uxtab16lt r1, ip, r6, ror #24' |
| if strings.ToLower(dec.text) == text { |
| return true |
| } |
| |
| // word F410FDA1: libopcodes says PLDW but the manual is clear that PLDW is F5/F7, not F4. |
| // word F7D0FB17: libopcodes says PLDW but the manual is clear that PLDW has 0x10 clear |
| if hasPrefix(dec.text, "pld") && raw&0xfd000010 != 0xf5000000 { |
| return true |
| } |
| |
| // word F650FE14: libopcodes says PLI but the manual is clear that PLI has 0x10 clear |
| if hasPrefix(dec.text, "pli") && raw&0xff000010 != 0xf6000000 { |
| return true |
| } |
| } |
| |
| return false |
| } |
| |
| // Instructions known to libopcodes (or xed) but not to us. |
| // Most of these are floating point coprocessor instructions. |
| var unsupported = strings.Fields(` |
| abs |
| acs |
| adf |
| aes |
| asn |
| atn |
| cdp |
| cf |
| cmf |
| cnf |
| cos |
| cps |
| crc32 |
| dvf |
| eret |
| exp |
| fadd |
| fcmp |
| fcpy |
| fcvt |
| fdiv |
| fdv |
| fix |
| fld |
| flt |
| fmac |
| fmd |
| fml |
| fmr |
| fms |
| fmul |
| fmx |
| fneg |
| fnm |
| frd |
| fsit |
| fsq |
| fst |
| fsu |
| fto |
| fui |
| hlt |
| hvc |
| lda |
| ldc |
| ldf |
| lfm |
| lgn |
| log |
| mar |
| mcr |
| mcrr |
| mia |
| mnf |
| mra |
| mrc |
| mrrc |
| mrs |
| msr |
| msr |
| muf |
| mvf |
| nrm |
| pol |
| pow |
| rdf |
| rfc |
| rfe |
| rfs |
| rmf |
| rnd |
| rpw |
| rsf |
| sdiv |
| sev |
| sfm |
| sha1 |
| sha256 |
| sin |
| smc |
| sqt |
| srs |
| stc |
| stf |
| stl |
| suf |
| tan |
| udf |
| udiv |
| urd |
| vfma |
| vfms |
| vfnma |
| vfnms |
| vrint |
| wfc |
| wfs |
| `) |