+ /* Clear the non-page, non-alignment bits from the address */
if (TCG_TARGET_REG_BITS == 32 || TARGET_LONG_BITS == 32) {
+ /* We don't support unaligned accesses on 32-bits, preserve
+ * the bottom bits and thus trigger a comparison failure on
+ * unaligned accesses
+ */
tcg_out_rlw(s, RLWINM, TCG_REG_R0, addrlo, 0,
(32 - s_bits) & 31, 31 - TARGET_PAGE_BITS);
- } else if (!s_bits) {
- tcg_out_rld(s, RLDICR, TCG_REG_R0, addrlo,
- 0, 63 - TARGET_PAGE_BITS);
+ } else if (s_bits) {
+ /* > byte access, we need to handle alignment */
+ if ((opc & MO_AMASK) == MO_ALIGN) {
+ /* Alignment required by the front-end, same as 32-bits */
+ tcg_out_rld(s, RLDICL, TCG_REG_R0, addrlo,
+ 64 - TARGET_PAGE_BITS, TARGET_PAGE_BITS - s_bits);
+ tcg_out_rld(s, RLDICL, TCG_REG_R0, TCG_REG_R0, TARGET_PAGE_BITS,
0);
+ } else {
+ /* We support unaligned accesses, we need to make sure we fail
+ * if we cross a page boundary. The trick is to add the
+ * access_size-1 to the address before masking the low bits.
+ * That will make the address overflow to the next page if we
+ * cross a page boundary which will then force a mismatch of
+ * the TLB compare since the next page cannot possibly be in
+ * the same TLB index.
+ */
+ tcg_out32(s, ADDI | TAI(TCG_REG_R0, addrlo, (1 << s_bits) - 1));
+ tcg_out_rld(s, RLDICR, TCG_REG_R0, TCG_REG_R0,
+ 0, 63 - TARGET_PAGE_BITS);
+ }
} else {
- tcg_out_rld(s, RLDICL, TCG_REG_R0, addrlo,
- 64 - TARGET_PAGE_BITS, TARGET_PAGE_BITS - s_bits);
- tcg_out_rld(s, RLDICL, TCG_REG_R0, TCG_REG_R0, TARGET_PAGE_BITS, 0);
+ /* Byte access, just chop off the bits below the page index */
+ tcg_out_rld(s, RLDICR, TCG_REG_R0, addrlo, 0, 63 - TARGET_PAGE_BITS);