diff --git a/Makefile.am b/Makefile.am
index 011e686f1bd8..23e51bb67ef3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -144,6 +144,8 @@ libcronus_la_SOURCES = \
 
 libpdbg_la_SOURCES = \
 	$(DT_sources) \
+	libpdbg/addressing.c \
+	libpdbg/addressing.h \
 	libpdbg/adu.c \
 	libpdbg/backend.h \
 	libpdbg/bitutils.h \
diff --git a/libpdbg/addressing.c b/libpdbg/addressing.c
new file mode 100644
index 000000000000..14aec2347be2
--- /dev/null
+++ b/libpdbg/addressing.c
@@ -0,0 +1,73 @@
+/* Copyright 2019 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdlib.h>
+#include <strings.h>
+
+#include "addressing.h"
+#include "debug.h"
+
+#define PDBG_CFAM_ADDRESS_MODE "PDBG_CFAM_ADDRESS_MODE"
+
+static void cfam_addr_help(void)
+{
+	pdbg_log(PDBG_ERROR,
+"The following CFAM addressing modes are supported:\n"
+"\n"
+"'"PDBG_CFAM_ADDRESS_MODE"=help': Print this help and exit\n"
+"'"PDBG_CFAM_ADDRESS_MODE"=raw': Byte-based engine addressing\n"
+"'"PDBG_CFAM_ADDRESS_MODE"=cooked': Register-indexed engine addressing\n"
+"\n"
+"Each engine is allocated 1kiB of address space in the CFAM. 'cooked'\n"
+"addressing mode requires the base address of the engine in the CFAM's\n"
+"address space be OR'ed with the 4-byte index of the register of interest\n");
+}
+
+static int cfam_addr_warned;
+
+uint32_t cfam_addr(uint32_t addr)
+{
+	char *mode;
+
+	/* PDBG_CFAM_ADDRESS_MODE=raw|cooked|help */
+	mode = getenv("PDBG_CFAM_ADDRESS_MODE");
+
+	if (!mode) {
+		if (!cfam_addr_warned) {
+			pdbg_log(PDBG_ERROR,
+"Please specify an explicit CFAM addressing mode using the\n"
+PDBG_CFAM_ADDRESS_MODE " environment variable. Defaulting to 'cooked'.\n"
+"The default may change to 'raw' in future releases\n");
+			pdbg_log(PDBG_ERROR, "\n");
+			cfam_addr_help();
+			cfam_addr_warned = 1;
+		}
+		mode = "cooked";
+	}
+
+	if (!strcasecmp("raw", mode)) {
+		return addr;
+	} else if (!strcasecmp("cooked", mode)) {
+		return ((addr & 0x7ffc00) | ((addr & 0x3ff) << 2));
+	} else if (!strcasecmp("help", mode)) {
+		cfam_addr_help();
+		/* A little rude in library code... */
+		exit(EXIT_SUCCESS);
+	} else {
+		cfam_addr_help();
+		/* A little rude in library code... */
+		exit(EXIT_FAILURE);
+	}
+}
diff --git a/libpdbg/addressing.h b/libpdbg/addressing.h
new file mode 100644
index 000000000000..56a5fcc93a06
--- /dev/null
+++ b/libpdbg/addressing.h
@@ -0,0 +1,23 @@
+/* Copyright 2019 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * 	http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __ADDRESSING_H
+#define __ADDRESSING_H
+
+#include <stdint.h>
+
+uint32_t cfam_addr(uint32_t addr);
+
+#endif
diff --git a/libpdbg/bmcfsi.c b/libpdbg/bmcfsi.c
index 1d2e304ea2ef..011da9a62222 100644
--- a/libpdbg/bmcfsi.c
+++ b/libpdbg/bmcfsi.c
@@ -25,6 +25,7 @@
 #include <assert.h>
 #include <inttypes.h>
 
+#include "addressing.h"
 #include "bitutils.h"
 #include "operations.h"
 #include "hwunit.h"
@@ -206,10 +207,12 @@ static uint64_t fsi_abs_ar(uint32_t addr, int read)
 {
 	uint32_t slave_id = (addr >> 21) & 0x3;
 
+	addr = cfam_addr(addr & 0x1fffff);
+
 	/* Reformat the address. I'm not sure I fully understand this
 	 * yet but we basically shift the bottom byte and add 0b01
 	 * (for the write word?) */
-       	addr = ((addr & 0x1ffc00) | ((addr & 0x3ff) << 2)) << 1;
+	addr <<= 1;
 	addr |= 0x3;
 	addr |= slave_id << 26;
 	addr |= (0x8ULL | !!(read)) << 22;
diff --git a/libpdbg/kernel.c b/libpdbg/kernel.c
index 4cc0334d7eb3..c71486ed0a85 100644
--- a/libpdbg/kernel.c
+++ b/libpdbg/kernel.c
@@ -25,6 +25,7 @@
 #include <inttypes.h>
 #include <endian.h>
 
+#include "addressing.h"
 #include "bitutils.h"
 #include "operations.h"
 #include "hwunit.h"
@@ -37,7 +38,7 @@ int fsi_fd;
 static int kernel_fsi_getcfam(struct fsi *fsi, uint32_t addr64, uint32_t *value)
 {
 	int rc;
-	uint32_t tmp, addr = (addr64 & 0x7ffc00) | ((addr64 & 0x3ff) << 2);
+	uint32_t tmp, addr = cfam_addr(addr64);
 
 	rc = lseek(fsi_fd, addr, SEEK_SET);
 	if (rc < 0) {
@@ -64,7 +65,7 @@ static int kernel_fsi_getcfam(struct fsi *fsi, uint32_t addr64, uint32_t *value)
 static int kernel_fsi_putcfam(struct fsi *fsi, uint32_t addr64, uint32_t data)
 {
 	int rc;
-	uint32_t tmp, addr = (addr64 & 0x7ffc00) | ((addr64 & 0x3ff) << 2);
+	uint32_t tmp, addr = cfam_addr(addr64);
 
 	rc = lseek(fsi_fd, addr, SEEK_SET);
 	if (rc < 0) {
