aboutsummaryrefslogtreecommitdiff
path: root/target-xtensa/op_helper.c
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2012-12-05 07:15:20 +0400
committerBlue Swirl <blauwirbel@gmail.com>2012-12-08 18:48:26 +0000
commitfcc803d119a4c01a9b0ee5bda35fda1eeabffa33 (patch)
treebbd6697bd198b45b2322e5b43d3ab5159e093d98 /target-xtensa/op_helper.c
parent536b558f5896ebbd635b57fa393e82faaa32ad52 (diff)
target-xtensa: implement ATOMCTL SR
ATOMCTL SR controls s32c1i opcode behavior depending on targeted memory type. See ISA, 4.3.12.4 for details. Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Diffstat (limited to 'target-xtensa/op_helper.c')
-rw-r--r--target-xtensa/op_helper.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/target-xtensa/op_helper.c b/target-xtensa/op_helper.c
index ae0c09977b..0e0f21d1a2 100644
--- a/target-xtensa/op_helper.c
+++ b/target-xtensa/op_helper.c
@@ -415,6 +415,63 @@ void HELPER(check_interrupts)(CPUXtensaState *env)
check_interrupts(env);
}
+/*!
+ * Check vaddr accessibility/cache attributes and raise an exception if
+ * specified by the ATOMCTL SR.
+ *
+ * Note: local memory exclusion is not implemented
+ */
+void HELPER(check_atomctl)(CPUXtensaState *env, uint32_t pc, uint32_t vaddr)
+{
+ uint32_t paddr, page_size, access;
+ uint32_t atomctl = env->sregs[ATOMCTL];
+ int rc = xtensa_get_physical_addr(env, true, vaddr, 1,
+ xtensa_get_cring(env), &paddr, &page_size, &access);
+
+ /*
+ * s32c1i never causes LOAD_PROHIBITED_CAUSE exceptions,
+ * see opcode description in the ISA
+ */
+ if (rc == 0 &&
+ (access & (PAGE_READ | PAGE_WRITE)) != (PAGE_READ | PAGE_WRITE)) {
+ rc = STORE_PROHIBITED_CAUSE;
+ }
+
+ if (rc) {
+ HELPER(exception_cause_vaddr)(env, pc, rc, vaddr);
+ }
+
+ /*
+ * When data cache is not configured use ATOMCTL bypass field.
+ * See ISA, 4.3.12.4 The Atomic Operation Control Register (ATOMCTL)
+ * under the Conditional Store Option.
+ */
+ if (!xtensa_option_enabled(env->config, XTENSA_OPTION_DCACHE)) {
+ access = PAGE_CACHE_BYPASS;
+ }
+
+ switch (access & PAGE_CACHE_MASK) {
+ case PAGE_CACHE_WB:
+ atomctl >>= 2;
+ case PAGE_CACHE_WT:
+ atomctl >>= 2;
+ case PAGE_CACHE_BYPASS:
+ if ((atomctl & 0x3) == 0) {
+ HELPER(exception_cause_vaddr)(env, pc,
+ LOAD_STORE_ERROR_CAUSE, vaddr);
+ }
+ break;
+
+ case PAGE_CACHE_ISOLATE:
+ HELPER(exception_cause_vaddr)(env, pc,
+ LOAD_STORE_ERROR_CAUSE, vaddr);
+ break;
+
+ default:
+ break;
+ }
+}
+
void HELPER(wsr_rasid)(CPUXtensaState *env, uint32_t v)
{
v = (v & 0xffffff00) | 0x1;