02111-1307, USA. */
/*@1@*/
+#define REGS_OFFSET 0
+//#define REGS_OFFSET 0x400
+
#ifndef REGSAVR_HEADER
#define REGSAVR_HEADER
int dummy;
};
-/* macros suck, can we use inline functions instead
- for the same effect? karl
+/* these macros suck, what was I thinking? Try to make it go fast
+ at the our expense? Daniels going to hate me if I continue to
+ clutter up his nice C++ with old crusty C macros :) Karl.
*/
-/* direct is a special code space for built-in ram and SFR, 1K size */
-#ifdef WORDS_BIGENDIAN
-#define set_word_direct(_index, _value) { \
- mem_direct[(_index)] = (_value >> 8); \
- mem_direct[(_index)] = (_value & 0xff); }
-
-#define get_word_direct(_index) \
- ( (mem_direct[(_index)] << 8) | mem_direct[(_index)+1] )
-#else
-#define set_word_direct(_index, _value) { \
- wmem_direct[(_index) >> 1] = _value; }
-#define get_word_direct(_index) (wmem_direct[(_index) >> 1] )
-#endif
+/* store to sfr */
+#define set_word_direct(addr, val) { sfr->set((t_addr) (addr), (val) & 0xff); \
+ sfr->set((t_addr) (addr+1), ((val) >> 8) & 0xff); }
+#define set_byte_direct(addr, val) sfr->set((t_addr) (addr), (val) )
+
+/* get from sfr */
+#define get_byte_direct(addr) sfr->get((t_addr) (addr))
+#define get_word_direct(addr) (sfr->get((t_addr) (addr)) | (sfr->get((t_addr) (addr+1)) << 8) )
+
+/* store to idata(onchip) ram */
+#define set_idata2(addr, val) { iram->set((t_addr) (addr), (val) & 0xff); \
+ iram->set((t_addr) (addr+1), ((val) >> 8) & 0xff); }
+#define set_idata1(addr, val) iram->set((t_addr) (addr), (val) )
-#define get_byte_direct(_index) (mem_direct[_index])
+/* get from idata(onchip) ram */
+#define get_idata1(addr) iram->get((t_addr) (addr))
+#define get_idata2(addr) (iram->get((t_addr) (addr)) | (iram->get((t_addr) (addr+1)) << 8) )
+/* store to xdata(external) ram */
+#define set_xdata2(addr, val) { ram->set((t_addr) (addr), (val) & 0xff); \
+ ram->set((t_addr) (addr+1), ((val) >> 8) & 0xff); }
+#define set_xdata1(addr, val) ram->set((t_addr) (addr), val)
+
+/* get from xdata(external) ram */
+#define get_xdata1(addr) ram->get((t_addr) (addr))
+#define get_xdata2(addr) (ram->get((t_addr) (addr)) | (ram->get((t_addr) (addr+1)) << 8) )
+
+#if 0
+ moved to inst.cc as functions
/* store to ram */
-#define store2(addr, val) { ram->set((t_addr) (addr), val & 0xff); \
- ram->set((t_addr) (addr+1), (val >> 8) & 0xff); }
+#define store2(addr, val) { ram->set((t_addr) (addr), (val) & 0xff); \
+ ram->set((t_addr) (addr+1), ((val) >> 8) & 0xff); }
#define store1(addr, val) ram->set((t_addr) (addr), val)
/* get from ram */
#define get1(addr) ram->get((t_addr) (addr))
#define get2(addr) (ram->get((t_addr) (addr)) | (ram->get((t_addr) (addr+1)) << 8) )
+#endif
/* get from code */
#define getcode1(addr) rom->get((t_addr) (addr))
#define fetch1() fetch()
/* get a 1 or 2 byte register */
-#define reg2(_index) get_reg(1, (_index))
+#define reg2(_index) get_reg(1, (_index<<1)) /* function in inst.cc */
#define reg1(_index) (unsigned char)get_reg(0, (_index))
-#define set_byte_direct(_index, _value) { \
- mem_direct[_index] = _value; \
-}
-
#define set_reg1(_index, _value) { \
- if ((_index) < 3) { /* banked */ \
- mem_direct[0x400+(_index)] = _value; \
- } else { /* non-banked */ \
- mem_direct[0x400+(_index)] = _value; \
- } \
+ set_byte_direct((REGS_OFFSET+(_index)), _value); \
}
#define set_reg2(_index, _value) { \
- if ((_index) < 3) { /* banked */ \
- set_word_direct((0x400+_index), _value); \
- } else { /* non-banked */ \
- set_word_direct((0x400+_index), _value); \
- } \
+ set_word_direct( (REGS_OFFSET+(_index<<1)), _value); \
}
#define set_reg(_word_flag, _index, _value) { \
{ set_reg1((_index), _value) } \
}
-// fixme: implement
-#define get_bit(x) (x)
-#define set_bit(x,y)
-
-/* R7 mirrors 1 of 2 real SP's */
+/* R7 mirrors 1 of 2 real SP's
+ note: we will probably need a real function here...
+ */
#define set_sp(_value) { \
- { set_word_direct(0x400+(7*2), _value); } \
+ { set_word_direct(REGS_OFFSET+(7*2), _value); } \
}
-#define get_sp() ((TYPE_UWORD)(get_word_direct(0x400+(7*2))))
+#define get_sp() ((TYPE_UWORD)(get_word_direct(REGS_OFFSET+(7*2))))
+
+/* the program status word */
+#define PSW 0x400
+#define get_psw() ((TYPE_UWORD)(get_word_direct(PSW)))
+#define set_psw(_flags) set_word_direct(PSW, _flags)
+
+/* the system configuration register */
+#define SCR 0x440
+#define get_scr() get_byte_direct(SCR)
+#define set_scr(scr) set_byte_direct(SCR, scr)
+
+// PSW bits...(note: consider replacing with Bit defines used in s51.src code)
+#define BIT_C 0x80
+#define BIT_AC 0x40
+#define BIT_V 0x04
+#define BIT_N 0x02
+#define BIT_Z 0x01
+#define BIT_ALL (BIT_C | BIT_AC | BIT_V | BIT_N | BIT_Z)
-// fixme: I don't know where the psw is kept, just want to compile...
-#define get_psw() ((TYPE_UWORD)(get_word_direct(0x400+(0x80*2))))
-#define set_psw(_flags) set_word_direct(0x400+(0x80*2), _flags)
#if 0
--------------------------------------------------------------------
-Notes:
- Register layout:
+Developer Notes.
+
+This user guide has got the detailed information on the XA chip.
+
+http://www.semiconductors.philips.com/acrobat/various/XA_USER_GUIDE_1.pdf
f: {unused slot(word accessable only) for R8-R15}
e: R7h,R7l Stack pointer, ptr to USP(PSW.SM=0), or SSP(PSW.SM=1)
8: R4h,R4l
below are the banked registers which mirror(B0..B3) depending on
PSW.(RS0,RS1)
-6: R3h,R3l \a
+6: R3h,R3l
4: R2h,R2l
2: R1h,R1l
0: R0h,R0l
Data word access limited to word boundaries. If non-word address used,
then will act as lesser word alignment used(addr b0=0).
-(note: trigger an exception in simulator if otherwise).
Internal memory takes precedence over external memory, unless
explicit movx used.
between 400H to 7FFH.
Branch targets must reside on even boundaries
-(note: trigger an exception in simulator if otherwise).
MOVC instructions use either PC(SSEL.4=0) or CS(SSEL.4=1) register.
Stack ptr is pre-decremented, followed by load(word operation),
default SPs are set to 100H. So first PUSH would go to FEH-FFH.
-#endif
+DIRECT MEMORY SPACE
+When we speak of direct memory space we refer to opcodes like
+MOV Rd, direct
+The "direct" part is always composed of 11 bits in the opcode.
+So the total size of "direct" space is 2K bytes.
+
+1.) This direct memory space contains the SFRs starting at 0x400 offset.
+
+Internal onchip memory(SFRs and onchip RAM) always override
+external memory. Read the specific Chip documentation for the
+location of SFRs and RAM.
+
+The codes space is independent.
+
+The registers: 4 banks of 8 bytes(R0-R3), R4-R7 8 bytes, and stack
+pointers are self contained and not part of any address space.
+(The CS,ES,DS appear to reside in SFR space).
+
+This is still confusing, let take some examples.
+
+---------------------------
+XA-G49 chip has 2k bytes built in RAM.
+
+According to the XA-G49 datasheet:
+
+With the DS set to 0, then all indirect address references
+between 0-7FFH reference the onchip 2K RAM. Direct address
+references below 0x400 access onchip 2K RAM.
+
+With the DS not set to 0, then all indirect address references
+between 0-7FFH reference external memory. Direct address
+references below 0x400 access external memory.
+
+Any direct address references between 400H and 7FFH access the SFRs
+regardless of the segment register contents.
+
+To access any external memory which overlaps the 2K onchip memory
+ues the MOVX instruction.
+
+---------------------------
+Proposed segment layout use for SDCC/XA compiler:
+
+XDATA -> external memory(use indirect addressing, ignore direct
+ addressing, ignore any overlap with onchip memory).
+
+IDATA -> onchip memory(use indirect addressing, ignore direct
+ addressing, assume small model where DS,ES always 0).
+
+DATA -> SFR memory access using direct addressing.
+
+CODE -> Far calls/returns are available.
+
+(Johan, Im just trying to spell this out explicitly for
+my own understanding.)
+
+---------------------------
+Proposed segment layout use for ucSim XA simulator.
+
+ram -> external memory.
+
+rom -> external/internal code.
+
+sfr -> SFR register space. Include registers/register banks here
+in some unused location to provide a means to dump all the register
+file contents using the "ds" command. Could make sfr memory larger
+than 0x800, and use the space above 0x800 to hold registers/sp-s.
+
+idata -> onchip memory.
+
+I think we can determine the size of idata memory at run time, so
+this could allow for various sized onchip memorys. So indirect
+memory accesses like this:
+set_indirect1(addr, value) {
+ if (addr < mem_size(idata)) {
+ set_idata(addr,value);
+ } else {
+ set_xdata(addr,value);
+ }
+}
+
+----------------------------------------------
+#endif
-// PSW bits...
-#define BIT_C 0x80
-#define BIT_AC 0x40
-#define BIT_V 0x04
-#define BIT_N 0x02
-#define BIT_Z 0x01
-#define BIT_ALL (BIT_C | BIT_AC | BIT_V | BIT_N | BIT_Z)
#endif
/* End of xa.src/regsxa.h */