summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGabe Black <gblack@eecs.umich.edu>2010-06-02 12:58:03 -0500
committerGabe Black <gblack@eecs.umich.edu>2010-06-02 12:58:03 -0500
commitb615ed147036ec13fd319c835c06bb48df51d4ba (patch)
tree772572c267bf40aad6436ea4040b04a9b79ab28a /src
parent274badd201e634b646a7d6cc5d64def956dd5e80 (diff)
downloadgem5-b615ed147036ec13fd319c835c06bb48df51d4ba.tar.xz
ARM: Hook the new branch instructions into the 32 bit thumb decoder.
Diffstat (limited to 'src')
-rw-r--r--src/arch/arm/isa/decoder/thumb.isa2
-rw-r--r--src/arch/arm/isa/formats/branch.isa138
2 files changed, 136 insertions, 4 deletions
diff --git a/src/arch/arm/isa/decoder/thumb.isa b/src/arch/arm/isa/decoder/thumb.isa
index 349a4a87d..0dcd8937d 100644
--- a/src/arch/arm/isa/decoder/thumb.isa
+++ b/src/arch/arm/isa/decoder/thumb.isa
@@ -161,7 +161,7 @@
0x0: Thumb32DataProcModImm::thumb32DataProcModImm();
0x1: WarnUnimpl::Data_processing_plain_binary_immediate();
}
- 0x1: BranchesAndMiscCtrl::branchesAndMiscCtrl();
+ 0x1: Thumb32BranchesAndMiscCtrl::thumb32BranchesAndMiscCtrl();
}
0x3: decode HTOPCODE_10_9 {
0x0: decode HTOPCODE_4 {
diff --git a/src/arch/arm/isa/formats/branch.isa b/src/arch/arm/isa/formats/branch.isa
index 0be00c20c..caf6f6227 100644
--- a/src/arch/arm/isa/formats/branch.isa
+++ b/src/arch/arm/isa/formats/branch.isa
@@ -105,9 +105,141 @@ def format Thumb16UncondBranch() {{
'''
}};
-def format Thumb32 BranchesAndMiscCtrl() {{
+def format Thumb32BranchesAndMiscCtrl() {{
decode_block = '''
- return new WarnUnimplemented("Branches_and_miscellaneous_control",
- machInst);
+ {
+ const uint32_t op = bits(machInst, 26, 20);
+ const uint32_t op1 = bits(machInst, 14, 12);
+ const uint32_t op2 = bits(machInst, 11, 8);
+ switch (op1 & 0x5) {
+ case 0x0:
+ if (op == 127) {
+ if (op1 & 0x2) {
+ // Permanentl undefined.
+ return new WarnUnimplemented("undefined", machInst);
+ } else {
+ return new WarnUnimplemented("smc", machInst);
+ }
+ } else if ((op & 0x38) != 0x38) {
+ const uint32_t s = bits(machInst, 26);
+ const uint32_t j1 = bits(machInst, 13);
+ const uint32_t j2 = bits(machInst, 11);
+ const uint32_t imm6 = bits(machInst, 21, 16);
+ const uint32_t imm11 = bits(machInst, 10, 0);
+ const int32_t imm = sext<21>((s << 20) |
+ (j2 << 19) | (j1 << 18) |
+ (imm6 << 12) | (imm11 << 1));
+ return new B(machInst, imm,
+ (ConditionCode)(uint32_t)bits(machInst, 25, 22));
+ } else {
+ switch (op) {
+ case 0x38:
+ if ((op2 & 0x3) == 0) {
+ // Application level
+ return new WarnUnimplemented("msr", machInst);
+ }
+ // Fall through on purpose...
+ case 0x39:
+ // System level
+ return new WarnUnimplemented("msr", machInst);
+ case 0x3a:
+ {
+ const uint32_t op1 = bits(machInst, 10, 8);
+ const uint32_t op2 = bits(machInst, 7, 0);
+ if (op1 != 0) {
+ return new WarnUnimplemented("cps", machInst);
+ } else if ((op2 & 0xf0) == 0xf0) {
+ return new WarnUnimplemented("dbg", machInst);
+ } else {
+ switch (op2) {
+ case 0x0:
+ return new WarnUnimplemented("nop", machInst);
+ case 0x1:
+ return new WarnUnimplemented("yield", machInst);
+ case 0x2:
+ return new WarnUnimplemented("wfe", machInst);
+ case 0x3:
+ return new WarnUnimplemented("wfi", machInst);
+ case 0x4:
+ return new WarnUnimplemented("sev", machInst);
+ default:
+ break;
+ }
+ }
+ break;
+ }
+ case 0x3b:
+ {
+ const uint32_t op = bits(machInst, 7, 4);
+ switch (op) {
+ case 0x0:
+ return new WarnUnimplemented("leavex", machInst);
+ case 0x1:
+ return new WarnUnimplemented("enterx", machInst);
+ case 0x2:
+ return new WarnUnimplemented("clrex", machInst);
+ case 0x4:
+ return new WarnUnimplemented("dsb", machInst);
+ case 0x5:
+ return new WarnUnimplemented("dmb", machInst);
+ case 0x6:
+ return new WarnUnimplemented("isb", machInst);
+ default:
+ break;
+ }
+ break;
+ }
+ case 0x3c:
+ return new WarnUnimplemented("bxj", machInst);
+ case 0x3d:
+ return new WarnUnimplemented("subs_pc_lr_and_rel_insts",
+ machInst);
+ case 0x3e:
+ case 0x3f:
+ return new WarnUnimplemented("mrs", machInst);
+ }
+ break;
+ }
+ case 0x1:
+ {
+ const uint32_t s = bits(machInst, 26);
+ const uint32_t i1 = !(bits(machInst, 13) ^ s);
+ const uint32_t i2 = !(bits(machInst, 11) ^ s);
+ const uint32_t imm10 = bits(machInst, 25, 16);
+ const uint32_t imm11 = bits(machInst, 10, 0);
+ const int32_t imm = sext<25>((s << 24) |
+ (i1 << 23) | (i2 << 22) |
+ (imm10 << 12) | (imm11 << 1));
+ return new B(machInst, imm, COND_UC);
+ }
+ case 0x4:
+ {
+ const uint32_t s = bits(machInst, 26);
+ const uint32_t i1 = !(bits(machInst, 13) ^ s);
+ const uint32_t i2 = !(bits(machInst, 11) ^ s);
+ const uint32_t imm10h = bits(machInst, 25, 16);
+ const uint32_t imm10l = bits(machInst, 10, 1);
+ const int32_t imm = sext<25>((s << 24) |
+ (i1 << 23) | (i2 << 22) |
+ (imm10h << 12) | (imm10l << 2));
+ return new BlxImm(machInst, imm);
+ }
+ case 0x5:
+ {
+ const uint32_t s = bits(machInst, 26);
+ const uint32_t i1 = !(bits(machInst, 13) ^ s);
+ const uint32_t i2 = !(bits(machInst, 11) ^ s);
+ const uint32_t imm10 = bits(machInst, 25, 16);
+ const uint32_t imm11 = bits(machInst, 10, 0);
+ const int32_t imm = sext<25>((s << 24) |
+ (i1 << 23) | (i2 << 22) |
+ (imm10 << 12) | (imm11 << 1));
+ return new Bl(machInst, imm, COND_UC);
+ }
+ default:
+ break;
+ }
+ return new Unknown(machInst);
+ }
'''
}};