Revision 179
Added by markw almost 11 years ago
firmware_5200/Makefile | ||
---|---|---|
BASE = zpu-elf
|
||
CC = $(BASE)-gcc
|
||
LD = $(BASE)-gcc
|
||
AS = $(BASE)-as
|
||
CP = $(BASE)-objcopy
|
||
DUMP = $(BASE)-objdump
|
||
|
||
# we use mincrt0.s from here
|
||
STARTUP_DIR = .
|
||
|
||
# we fetch ROM prologue / epilogue from here
|
||
RTL_DIR = $(ZPUFLEXDIR)/RTL/
|
||
|
||
|
||
BUILD_DIR=zpu_obj
|
||
|
||
#MINSTARTUP_SRC = mincrt0.s
|
||
MINSTARTUP_SRC = mycrt0.s
|
||
MINSTARTUP_OBJ = $(patsubst $(STARTUP_DIR)/%.s,$(BUILD_DIR)/%.o,$(MINSTARTUP_SRC))
|
||
|
||
AEON_LITE_PRJ = AEON_LITE
|
||
AEON_LITE_SRC = main_aeon_lite.c regs.c freeze.c joystick.c fileutils.c fileselector.c pokey/uart.c hexdump.c printf/printf.c fat/pff_file.c fat/pff.c common/utils.c sd_direct/diskio_mmc.c sd_direct/spi.c sd_direct/mmc2.c de1/dirs.c
|
||
AEON_LITE_OBJ = $(patsubst %.c,$(BUILD_DIR)/%.o,$(AEON_LITE_SRC))
|
||
|
||
DE1_PRJ = DE1
|
||
DE1_SRC = main.c regs.c freeze.c joystick.c fileutils.c fileselector.c pokey/uart.c hexdump.c printf/printf.c fat/pff_file.c fat/pff.c common/utils.c sd_direct/diskio_mmc.c sd_direct/spi.c sd_direct/mmc2.c de1/dirs.c
|
||
DE1_OBJ = $(patsubst %.c,$(BUILD_DIR)/%.o,$(DE1_SRC))
|
||
|
||
CHAMELEON_PRJ = CHAMELEON
|
||
CHAMELEON_SRC = main.c regs.c freeze.c joystick.c fileutils.c fileselector.c pokey/uart.c hexdump.c printf/printf.c fat/pff_file.c fat/pff.c common/utils.c sd_direct/diskio_mmc.c sd_direct/spi.c sd_direct/mmc2.c chameleon/dirs.c
|
||
CHAMELEON_OBJ = $(patsubst %.c,$(BUILD_DIR)/%.o,$(CHAMELEON_SRC))
|
||
|
||
MCC_PRJ = MCC216
|
||
MCC_SRC = main.c regs.c freeze.c joystick.c fileutils.c fileselector.c pokey/uart.c hexdump.c printf/printf.c fat/pff_file.c fat/pff.c common/utils.c sd_direct/diskio_mmc.c sd_direct/spi.c sd_direct/mmc2.c mcc/dirs.c
|
||
MCC_OBJ = $(patsubst %.c,$(BUILD_DIR)/%.o,$(MCC_SRC))
|
||
|
||
MIST_PRJ = MIST
|
||
MIST_SRC = main.c regs.c freeze.c joystick.c fileutils.c fileselector.c pokey/uart.c hexdump.c printf/printf.c fat/pff_file.c fat/pff.c common/utils.c mist/diskio_sectorrequest.c mist/dirs.c
|
||
MIST_OBJ = $(patsubst %.c,$(BUILD_DIR)/%.o,$(MIST_SRC))
|
||
|
||
LINKMAP = ./standalone_simple.ld
|
||
|
||
|
||
# Commandline options for each tool.
|
||
|
||
#ZPUOPTS= -mno-poppcrel -mno-pushspadd -mno-callpcrel -mno-shortop -mno-neg # No-neg requires bugfixed toolchain
|
||
#Include everything -> need to include emulation rom...
|
||
ZPUOPTS =
|
||
CFLAGS = -I. -Isd_direct -Iprintf -Ifat -Icommon -c -g -Os $(ZPUOPTS) -DDISABLE_UART_RX
|
||
|
||
LFLAGS = -nostartfiles -Wl,--relax -g -Os
|
||
#LFLAGS = -nostartfiles -Os
|
||
|
||
|
||
# Our target.
|
||
all: mcc mist de1 aeon_lite chameleon
|
||
|
||
install:
|
||
cd ../common/romgen && ./createall && cd ../../firmware
|
||
|
||
aeon_lite: $(BUILD_DIR) $(AEON_LITE_PRJ).bin $(AEON_LITE_PRJ).rpt
|
||
|
||
de1: $(BUILD_DIR) $(DE1_PRJ).bin $(DE1_PRJ).rpt
|
||
|
||
chameleon: $(BUILD_DIR) $(CHAMELEON_PRJ).bin $(CHAMELEON_PRJ).rpt
|
||
|
||
mcc: $(BUILD_DIR) $(MCC_PRJ).bin $(MCC_PRJ).rpt
|
||
|
||
mist: $(BUILD_DIR) $(MIST_PRJ).bin $(MIST_PRJ).rpt
|
||
|
||
clean:
|
||
rm -rf $(BUILD_DIR)/* *.hex *.elf *.map *.lst *.srec *.bin *.rpt
|
||
|
||
|
||
# Convert ELF binary to bin file.
|
||
%.bin: %.elf
|
||
$(CP) -O binary $< $@
|
||
|
||
%.rpt: %.elf
|
||
echo >$@ -n "End of code:\t"
|
||
$(DUMP) -x $< | grep >>$@ _romend
|
||
echo >>$@ -n "Start of BSS:\t"
|
||
$(DUMP) -x $< | grep >>$@ __bss_start__
|
||
echo >>$@ -n "End of BSS:\t"
|
||
$(DUMP) -x $< | grep >>$@ __bss_end__
|
||
cat $@
|
||
|
||
# Link - this produces an ELF binary.
|
||
|
||
$(AEON_LITE_PRJ).elf: $(MINSTARTUP_OBJ) $(AEON_LITE_OBJ)
|
||
$(LD) $(LFLAGS) -T $(LINKMAP) -o $@ $+ $(LIBS)
|
||
|
||
$(DE1_PRJ).elf: $(MINSTARTUP_OBJ) $(DE1_OBJ)
|
||
$(LD) $(LFLAGS) -T $(LINKMAP) -o $@ $+ $(LIBS)
|
||
|
||
$(CHAMELEON_PRJ).elf: $(MINSTARTUP_OBJ) $(CHAMELEON_OBJ)
|
||
$(LD) $(LFLAGS) -T $(LINKMAP) -o $@ $+ $(LIBS)
|
||
|
||
$(MCC_PRJ).elf: $(MINSTARTUP_OBJ) $(MCC_OBJ)
|
||
$(LD) $(LFLAGS) -T $(LINKMAP) -o $@ $+ $(LIBS)
|
||
|
||
$(MIST_PRJ).elf: $(MINSTARTUP_OBJ) $(MIST_OBJ)
|
||
$(LD) $(LFLAGS) -T $(LINKMAP) -o $@ $+ $(LIBS)
|
||
|
||
$(BUILD_DIR)/%.o: %.c Makefile
|
||
mkdir -p `dirname $@`
|
||
$(CC) $(CFLAGS) -o $@ -c $<
|
||
|
||
$(BUILD_DIR)/%.o: %.s
|
||
$(AS) -o $@ $<
|
||
|
||
$(BUILD_DIR)/%.o: $(STARTUP_DIR)/%.s
|
||
$(AS) -o $@ $<
|
||
|
||
$(BUILD_DIR):
|
||
mkdir $(BUILD_DIR)
|
||
|
firmware_5200/TODO | ||
---|---|---|
DONE i) Test writes at pf_file level on PC
|
||
DONE! ii) When file selected, boot rather than just printing something!
|
||
DONE iii) Add settings
|
||
DONE iv) Try out writes on Atari side
|
||
v) Check that read-only works...
|
||
DONE!--vi) Show selected file clearly!
|
firmware_5200/actions.c | ||
---|---|---|
int bit_set(int var, int bit)
|
||
{
|
||
return (((1<<bit)&var)!=0);
|
||
}
|
||
|
||
void actions()
|
||
{
|
||
unsigned int i = 0;
|
||
//unsigned volatile char * store = 0xf00000; // SDRAM - fails!!
|
||
//unsigned volatile char * store = 0xf80000; // SRAM...
|
||
//unsigned volatile char * store2 = 0xfc0000; // custom chips...
|
||
|
||
// cold start (need to clear a few key locations to make OS cold start)
|
||
// file selector (where applicable)
|
||
// options (where applicable)
|
||
|
||
int keys = *zpu_in;
|
||
|
||
if (bit_set(keys,0))
|
||
{
|
||
coldstart();
|
||
}
|
||
else if (bit_set(keys,1))
|
||
{
|
||
set_pause_6502(1);
|
||
freeze();
|
||
menu_options();
|
||
restore();
|
||
set_pause_6502(0);
|
||
}
|
||
else if (bit_set(keys,2))
|
||
{
|
||
set_pause_6502(1);
|
||
freeze();
|
||
menu_fileselector();
|
||
coldstart();
|
||
}
|
||
}
|
||
|
||
void menu_options()
|
||
{
|
||
// title
|
||
// memory
|
||
// rom
|
||
// turbo
|
||
// disks
|
||
// exit/reboot
|
||
|
||
// simple state machine for menu, so I set up a small data structure then it just runs from that...
|
||
}
|
||
|
||
void menu_fileselector()
|
||
{
|
||
// title
|
||
// loads of stuff, filtered by type
|
||
// directories can be selected
|
||
// initial directory set, after that starts where it was left
|
||
}
|
||
|
firmware_5200/aeon_lite/memory.h | ||
---|---|---|
#pragma once
|
||
|
||
// Memory usage...
|
||
// 0x90000-0x9FFFF (0x890000 in zpu space) = directory cache - 64k
|
||
// 0xA0000-0xBFFFF (0x8a0000 in zpu space) = freeze backup
|
||
// 0xC0000-0xDFFFF (0x8c0000 in zpu space) = os rom/basic rom
|
||
|
||
#define DIR_INIT_MEM 0x890000
|
||
#define DIR_INIT_MEMSIZE 65536
|
||
#define FREEZE_MEM 0x8a0000
|
||
#define ROM_MEM 0xc0000
|
||
|
firmware_5200/build | ||
---|---|---|
zpu-elf-gcc -I. -Isd_direct -Iprintf -Ifat -Icommon -c -g -O2 -DDISABLE_UART_RX -o zpu_obj/uart.o -c pokey/uart.c
|
||
zpu-elf-gcc -I. -Isd_direct -Iprintf -Ifat -Icommon -c -g -O2 -DDISABLE_UART_RX -o zpu_obj/hexdump.o -c hexdump.c
|
||
zpu-elf-gcc -I. -Isd_direct -Iprintf -Ifat -Icommon -c -g -O2 -DDISABLE_UART_RX -o zpu_obj/printf.o -c printf/printf.c
|
||
zpu-elf-gcc -I. -Isd_direct -Iprintf -Ifat -Icommon -c -g -O2 -DDISABLE_UART_RX -o zpu_obj/pff_file.o -c fat/pff_file.c
|
||
zpu-elf-gcc -I. -Isd_direct -Iprintf -Ifat -Icommon -c -g -O2 -DDISABLE_UART_RX -o zpu_obj/pff.o -c fat/pff.c
|
||
zpu-elf-gcc -I. -Isd_direct -Iprintf -Ifat -Icommon -c -g -O2 -DDISABLE_UART_RX -o zpu_obj/utils.o -c common/utils.c
|
||
zpu-elf-gcc -I. -Isd_direct -Iprintf -Ifat -Icommon -c -g -O2 -DDISABLE_UART_RX -o zpu_obj/diskio_mmc.o -c diskio_mmc.c
|
||
zpu-elf-gcc -nostartfiles -Wl,--relax -g -Os -T ./standalone_simple.ld -o JustStartAtari.elf mycrt0.s zpu_obj/main.o zpu_obj/regs.o zpu_obj/atari_drive_emulator.o zpu_obj/pokey/uart.o zpu_obj/hexdump.o zpu_obj/printf/printf.o zpu_obj/fat/pff_file.o zpu_obj/fat/pff.o zpu_obj/common/utils.o zpu_obj/diskio_mmc.o
|
||
zpu-elf-objcopy -O binary JustStartAtari.elf JustStartAtari.bin
|
||
echo >JustStartAtari.rpt -n "End of code:\t"
|
||
zpu-elf-objdump -x JustStartAtari.elf | grep >>JustStartAtari.rpt _romend
|
||
echo >>JustStartAtari.rpt -n "Start of BSS:\t"
|
||
zpu-elf-objdump -x JustStartAtari.elf | grep >>JustStartAtari.rpt __bss_start__
|
||
echo >>JustStartAtari.rpt -n "End of BSS:\t"
|
||
zpu-elf-objdump -x JustStartAtari.elf | grep >>JustStartAtari.rpt __bss_end__
|
||
cat JustStartAtari.rpt
|
||
|
||
firmware_5200/build_native_drive | ||
---|---|---|
gcc -g -O0 -DLITTLE_ENDIAN test_drive.c fileutils.c atari_drive_emulator.c native/uart.c hexdump.c printf/printf.c fat/pff_file.c fat/pff.c common/utils.c sd_direct/diskio_mmc.c native/mmc.c -I. -Iprintf -Ifat -Icommon
|
||
firmware_5200/build_native_file_test | ||
---|---|---|
gcc -g -O0 printf/printf.c test_file.c fileutils.c fileselector.c fat/pff_file.c fat/pff.c common/utils.c native/regs.c native/joystick.c native/diskio_mmc.c native/mmc.c native/screen.c -I. -Ifat -Icommon -Iprintf
|
||
firmware_5200/build_native_joystick | ||
---|---|---|
gcc -g -O0 test_joy.c joystick.c native/regs.c -I.
|
||
firmware_5200/build_sd_test | ||
---|---|---|
gcc -g -O0 printf/printf.c test_sd.c fileutils.c fileselector.c fat/pff_file.c fat/pff.c common/utils.c native/regs.c native/joystick.c sd_direct/mmc.c sd_direct/diskio_mmc.c native/screen.c native/spi.c -I. -Ifat -Icommon -Iprintf
|
||
firmware_5200/fileutils.c | ||
---|---|---|
#include "printf.h"
|
||
|
||
#include "utils.h"
|
||
|
||
int compare_ext(char const * filename, char const * ext)
|
||
{
|
||
int dot = 0;
|
||
//printf("WTFA:%s %s\n",filenamein, extin);
|
||
//printf("WTFB:%s %s\n",filename, ext);
|
||
|
||
char const * end = strlen(filename) + filename;
|
||
while (--end != filename)
|
||
{
|
||
if (*end == '.')
|
||
break;
|
||
}
|
||
if (0==stricmp(end+1,ext)) return 1;
|
||
|
||
return 0;
|
||
}
|
||
|
firmware_5200/freeze.h | ||
---|---|---|
#pragma once
|
||
|
||
// Allow us to take over the system
|
||
// NB: CPU should be frozen before calling these!
|
||
|
||
// Provide 128K of RAM...
|
||
void freeze_init(void * memory);
|
||
|
||
// Set hardware registers to 'neutral'
|
||
// Back up system ram
|
||
void freeze();
|
||
|
||
// Restore system ram
|
||
// Restore hardware registers
|
||
void restore();
|
||
|
firmware_5200/joystick.c | ||
---|---|---|
#include "joystick.h"
|
||
|
||
#include "regs.h"
|
||
|
||
//#include <stdio.h>
|
||
|
||
void joystick_poll(struct joystick_status * status)
|
||
{
|
||
status->x_ = 0;
|
||
status->y_ = 0;
|
||
status->fire_ = 0;
|
||
|
||
unsigned char kbcode = *atari_kbcode;
|
||
kbcode &= 0x1e;
|
||
|
||
unsigned char key_held = *atari_skctl;
|
||
if ((key_held&0x4) != 0)
|
||
{
|
||
kbcode = 0x0;
|
||
}
|
||
|
||
status->y_ = (0x8==(kbcode&0x18)) -((unsigned int)(0x18==(kbcode&0x18)));
|
||
status->x_ = (0x2==(kbcode&0x6)) -((unsigned int)(0x6==(kbcode&0x6)));
|
||
//status->fire_ = !(1&*atari_trig0);
|
||
status->fire_ = kbcode==0x14;
|
||
|
||
//if (porta != 0xff)
|
||
//printf("%02x %x %x %x\n",porta,status->x_,status->y_,status->fire_);
|
||
/*
|
||
if (0==(porta&0x2)) // down
|
||
{
|
||
status->y_ =1;
|
||
}
|
||
else if (0==(porta&0x1)) // up
|
||
{
|
||
status->y_ =-1;
|
||
}
|
||
if (0==(porta&0x8)) // right
|
||
{
|
||
status->x_ = 1;
|
||
}
|
||
else if (0==(porta&0x4)) // left
|
||
{
|
||
status->x_ = -1;
|
||
}
|
||
if (0==(1&*atari_trig0)) // fire
|
||
{
|
||
status->fire_ = 1;
|
||
}
|
||
*/
|
||
}
|
||
|
||
void joystick_wait(struct joystick_status * status, enum JoyWait waitFor)
|
||
{
|
||
while (1)
|
||
{
|
||
joystick_poll(status);
|
||
switch (waitFor)
|
||
{
|
||
case WAIT_QUIET:
|
||
if (status->x_ == 0 && status->y_ == 0 && status->fire_ == 0) return;
|
||
break;
|
||
case WAIT_FIRE:
|
||
if (status->fire_ == 1) return;
|
||
break;
|
||
case WAIT_EITHER:
|
||
if (status->fire_ == 1) return;
|
||
// fall through
|
||
case WAIT_MOVE:
|
||
if (status->x_ !=0 || status->y_ != 0) return;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
firmware_5200/chameleon/dirs.c | ||
---|---|---|
char USER_DIR[]="/atari800/user";
|
||
char ROM_DIR[]="/atari800/rom";
|
firmware_5200/common/integer.h | ||
---|---|---|
#ifndef _INTEGER
|
||
#define _INTEGER
|
||
|
||
/* These types must be 16-bit, 32-bit or larger integer */
|
||
typedef int INT;
|
||
typedef unsigned int UINT;
|
||
|
||
/* These types must be 8-bit integer */
|
||
typedef char CHAR;
|
||
typedef unsigned char UCHAR;
|
||
typedef unsigned char BYTE;
|
||
typedef unsigned char u08;
|
||
typedef unsigned char uint8_t;
|
||
|
||
/* These types must be 16-bit integer */
|
||
typedef short SHORT;
|
||
typedef unsigned short USHORT;
|
||
typedef unsigned short WORD;
|
||
typedef unsigned short WCHAR;
|
||
typedef unsigned short u16;
|
||
|
||
/* These types must be 32-bit integer */
|
||
typedef long LONG;
|
||
typedef unsigned long ULONG;
|
||
typedef unsigned long DWORD;
|
||
typedef unsigned int u32;
|
||
|
||
#define EEMEM
|
||
|
||
#endif
|
firmware_5200/common/utils.c | ||
---|---|---|
#include "utils.h"
|
||
|
||
int strcmp(char const * a, char const * b)
|
||
{
|
||
while (*a || *b)
|
||
{
|
||
if (*a<*b)
|
||
return -1;
|
||
else if (*a>*b)
|
||
return 1;
|
||
|
||
++a;
|
||
++b;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
int stricmp(char const * a, char const * b)
|
||
{
|
||
char buffer[128];
|
||
char buffer2[128];
|
||
stricpy(&buffer[0],a);
|
||
stricpy(&buffer2[0],b);
|
||
return strcmp(&buffer[0],&buffer2[0]);
|
||
}
|
||
|
||
void strcpy(char * dest, char const * src)
|
||
{
|
||
while (*dest++=*src++);
|
||
}
|
||
|
||
void stricpy(char * dest, char const * src)
|
||
{
|
||
while (*src)
|
||
{
|
||
char val = *src++;
|
||
if (val>='A' && val<='Z') val+=-'A'+'a';
|
||
|
||
*dest++ = val;
|
||
}
|
||
*dest = '\0';
|
||
}
|
||
|
||
int strlen(char const * a)
|
||
{
|
||
int count;
|
||
for (count=0; *a; ++a,++count);
|
||
return count;
|
||
}
|
||
|
firmware_5200/common/utils.h | ||
---|---|---|
int strcmp(char const * a, char const * b);
|
||
int stricmp(char const * a, char const * b);
|
||
void strcpy(char * dest, char const * src);
|
||
void stricpy(char * dest, char const * src);
|
||
int strlen(char const * a);
|
||
|
firmware_5200/common/x | ||
---|---|---|
g++: error: fat/pff_file.c: No such file or directory
|
||
g++: fatal error: no input files
|
||
compilation terminated.
|
firmware_5200/crt0.S | ||
---|---|---|
/* Startup code for ZPU
|
||
Copyright (C) 2005 Free Software Foundation, Inc.
|
||
|
||
This file is free software; you can redistribute it and/or modify it
|
||
under the terms of the GNU General Public License as published by the
|
||
Free Software Foundation; either version 2, or (at your option) any
|
||
later version.
|
||
|
||
In addition to the permissions in the GNU General Public License, the
|
||
Free Software Foundation gives you unlimited permission to link the
|
||
compiled version of this file with other programs, and to distribute
|
||
those programs without any restriction coming from the use of this
|
||
file. (The General Public License restrictions do apply in other
|
||
respects; for example, they cover modification of the file, and
|
||
distribution when not linked into another program.)
|
||
|
||
This file is distributed in the hope that it will be useful, but
|
||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with this program; see the file COPYING. If not, write to
|
||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||
Boston, MA 02111-1307, USA. */
|
||
.file "crt0.S"
|
||
|
||
|
||
|
||
|
||
; .section ".fixed_vectors","ax"
|
||
; KLUDGE!!! we remove the executable bit to avoid relaxation
|
||
.section ".fixed_vectors","a"
|
||
|
||
; DANGER!!!!
|
||
; we need to align these code sections to 32 bytes, which
|
||
; means we must not use any assembler instructions that are relaxed
|
||
; at linker time
|
||
; DANGER!!!!
|
||
|
||
.macro fixedim value
|
||
im \value
|
||
.endm
|
||
|
||
.macro jsr address
|
||
im _memreg ; save R0
|
||
load
|
||
im _memreg+4 ; save R1
|
||
load
|
||
im _memreg+8 ; save R2
|
||
load
|
||
fixedim \address
|
||
call
|
||
im _memreg+8
|
||
store ; restore R2
|
||
im _memreg+4
|
||
store ; restore R1
|
||
im _memreg
|
||
store ; restore R0
|
||
.endm
|
||
|
||
|
||
.macro jmp address
|
||
fixedim \address
|
||
poppc
|
||
.endm
|
||
|
||
|
||
.macro fast_neg
|
||
not
|
||
im 1
|
||
add
|
||
.endm
|
||
|
||
.macro cimpl funcname
|
||
; save R0
|
||
im _memreg
|
||
load
|
||
|
||
; save R1
|
||
im _memreg+4
|
||
load
|
||
|
||
; save R2
|
||
im _memreg+8
|
||
load
|
||
|
||
loadsp 20
|
||
loadsp 20
|
||
|
||
fixedim \funcname
|
||
call
|
||
|
||
; destroy arguments on stack
|
||
storesp 0
|
||
storesp 0
|
||
|
||
im _memreg
|
||
load
|
||
|
||
; poke the result into the right slot
|
||
storesp 24
|
||
|
||
; restore R2
|
||
im _memreg+8
|
||
store
|
||
|
||
; restore R1
|
||
im _memreg+4
|
||
store
|
||
|
||
; restore r0
|
||
im _memreg
|
||
store
|
||
|
||
|
||
storesp 4
|
||
poppc
|
||
.endm
|
||
|
||
.macro mult1bit
|
||
; create mask of lowest bit in A
|
||
loadsp 8 ; A
|
||
im 1
|
||
and
|
||
im -1
|
||
add
|
||
not
|
||
loadsp 8 ; B
|
||
and
|
||
add ; accumulate in C
|
||
|
||
; shift B left 1 bit
|
||
loadsp 4 ; B
|
||
addsp 0
|
||
storesp 8 ; B
|
||
|
||
; shift A right 1 bit
|
||
loadsp 8 ; A
|
||
flip
|
||
addsp 0
|
||
flip
|
||
storesp 12 ; A
|
||
.endm
|
||
|
||
|
||
|
||
/* vectors */
|
||
.balign 32,0
|
||
# offset 0x0000 0000
|
||
.globl _start
|
||
_start:
|
||
; intSp must be 0 when we jump to _premain
|
||
|
||
im ZPU_ID
|
||
loadsp 0
|
||
im _cpu_config
|
||
store
|
||
config
|
||
jmp _premain
|
||
|
||
|
||
|
||
.balign 32,0
|
||
# offset 0x0000 0020
|
||
.globl _zpu_interrupt_vector
|
||
_zpu_interrupt_vector:
|
||
jmp ___zpu_interrupt_vector
|
||
|
||
|
||
.balign 16,0
|
||
# offset 0x0000 0030
|
||
.globl _memreg
|
||
.weak _memreg
|
||
_memreg:
|
||
|
||
|
||
/* instruction emulation code */
|
||
|
||
# opcode 34
|
||
# offset 0x0000 0040
|
||
.balign 32,0
|
||
_loadh:
|
||
loadsp 4
|
||
; by not masking out bit 0, we cause a memory access error
|
||
; on unaligned access
|
||
im ~0x2
|
||
and
|
||
load
|
||
|
||
; mult 8
|
||
loadsp 8
|
||
im 3
|
||
and
|
||
fast_neg
|
||
im 2
|
||
add
|
||
im 3
|
||
ashiftleft
|
||
; shift right addr&3 * 8
|
||
lshiftright
|
||
im 0xffff
|
||
and
|
||
storesp 8
|
||
|
||
poppc
|
||
|
||
# opcode 35
|
||
# offset 0x0000 0060
|
||
.balign 32,0
|
||
_storeh:
|
||
loadsp 4
|
||
; by not masking out bit 0, we cause a memory access error
|
||
; on unaligned access
|
||
im ~0x2
|
||
and
|
||
load
|
||
|
||
; mask
|
||
im 0xffff
|
||
loadsp 12
|
||
im 3
|
||
and
|
||
fast_neg
|
||
im 2
|
||
add
|
||
im 3
|
||
ashiftleft
|
||
ashiftleft
|
||
not
|
||
|
||
and
|
||
|
||
loadsp 12
|
||
im 0xffff
|
||
|
||
nop
|
||
|
||
fixedim _storehtail
|
||
poppc
|
||
|
||
|
||
# opcode 36
|
||
# offset 0x0000 0080
|
||
.balign 32,0
|
||
_lessthan:
|
||
loadsp 8
|
||
fast_neg
|
||
loadsp 8
|
||
add
|
||
|
||
; DANGER!!!!
|
||
; 0x80000000 will overflow when negated, so we need to mask
|
||
; the result above with the compare positive to negative
|
||
; number case
|
||
loadsp 12
|
||
loadsp 12
|
||
not
|
||
and
|
||
not
|
||
and
|
||
|
||
|
||
; handle case where we are comparing a negative number
|
||
; and positve number. This can underflow. E.g. consider 0x8000000 < 0x1000
|
||
loadsp 12
|
||
not
|
||
loadsp 12
|
||
and
|
||
|
||
or
|
||
|
||
|
||
|
||
flip
|
||
im 1
|
||
and
|
||
|
||
|
||
storesp 12
|
||
storesp 4
|
||
poppc
|
||
|
||
|
||
# opcode 37
|
||
# offset 0x0000 00a0
|
||
.balign 32,0
|
||
_lessthanorequal:
|
||
loadsp 8
|
||
loadsp 8
|
||
lessthan
|
||
loadsp 12
|
||
loadsp 12
|
||
eq
|
||
or
|
||
|
||
storesp 12
|
||
storesp 4
|
||
poppc
|
||
|
||
|
||
# opcode 38
|
||
# offset 0x0000 00c0
|
||
.balign 32,0
|
||
_ulessthan:
|
||
; fish up arguments
|
||
loadsp 4
|
||
loadsp 12
|
||
|
||
/* low: -1 if low bit dif is negative 0 otherwise: neg (not x&1 and (y&1))
|
||
x&1 y&1 neg (not x&1 and (y&1))
|
||
1 1 0
|
||
1 0 0
|
||
0 1 -1
|
||
0 0 0
|
||
|
||
*/
|
||
loadsp 4
|
||
not
|
||
loadsp 4
|
||
and
|
||
im 1
|
||
and
|
||
neg
|
||
|
||
|
||
/* high: upper 31-bit diff is only wrong when diff is 0 and low=-1
|
||
high=x>>1 - y>>1 + low
|
||
|
||
extremes
|
||
|
||
0000 - 1111:
|
||
low= neg(not 0 and 1) = 1111 (-1)
|
||
high=000+ neg(111) +low = 000 + 1001 + low = 1000
|
||
OK
|
||
|
||
1111 - 0000
|
||
low=neg(not 1 and 0) = 0
|
||
high=111+neg(000) + low = 0111
|
||
OK
|
||
|
||
|
||
*/
|
||
loadsp 8
|
||
|
||
flip
|
||
addsp 0
|
||
flip
|
||
|
||
loadsp 8
|
||
|
||
flip
|
||
addsp 0
|
||
flip
|
||
|
||
sub
|
||
|
||
; if they are equal, then the last bit decides...
|
||
add
|
||
|
||
/* test if negative: result = flip(diff) & 1 */
|
||
flip
|
||
im 1
|
||
and
|
||
|
||
; destroy a&b which are on stack
|
||
storesp 4
|
||
storesp 4
|
||
|
||
storesp 12
|
||
storesp 4
|
||
poppc
|
||
|
||
# opcode 39
|
||
# offset 0x0000 00e0
|
||
.balign 32,0
|
||
_ulessthanorequal:
|
||
loadsp 8
|
||
loadsp 8
|
||
ulessthan
|
||
loadsp 12
|
||
loadsp 12
|
||
eq
|
||
or
|
||
|
||
storesp 12
|
||
storesp 4
|
||
poppc
|
||
|
||
|
||
# opcode 40
|
||
# offset 0x0000 0100
|
||
.balign 32,0
|
||
.globl _swap
|
||
_swap:
|
||
breakpoint ; tbd
|
||
|
||
# opcode 41
|
||
# offset 0x0000 0120
|
||
.balign 32,0
|
||
_slowmult:
|
||
im _slowmultImpl
|
||
poppc
|
||
|
||
# opcode 42
|
||
# offset 0x0000 0140
|
||
.balign 32,0
|
||
_lshiftright:
|
||
loadsp 8
|
||
flip
|
||
|
||
loadsp 8
|
||
ashiftleft
|
||
flip
|
||
|
||
storesp 12
|
||
storesp 4
|
||
|
||
poppc
|
||
|
||
|
||
# opcode 43
|
||
# offset 0x0000 0160
|
||
.balign 32,0
|
||
_ashiftleft:
|
||
loadsp 8
|
||
|
||
loadsp 8
|
||
im 0x1f
|
||
and
|
||
fast_neg
|
||
im _ashiftleftEnd
|
||
add
|
||
poppc
|
||
|
||
|
||
|
||
# opcode 44
|
||
# offset 0x0000 0180
|
||
.balign 32,0
|
||
_ashiftright:
|
||
loadsp 8
|
||
loadsp 8
|
||
lshiftright
|
||
|
||
; handle signed value
|
||
im -1
|
||
loadsp 12
|
||
im 0x1f
|
||
and
|
||
lshiftright
|
||
not ; now we have an integer on the stack with the signed
|
||
; bits in the right position
|
||
|
||
; mask these bits with the signed bit.
|
||
loadsp 16
|
||
not
|
||
flip
|
||
im 1
|
||
and
|
||
im -1
|
||
add
|
||
|
||
and
|
||
|
||
; stuff in the signed bits...
|
||
or
|
||
|
||
; store result into correct stack slot
|
||
storesp 12
|
||
|
||
; move up return value
|
||
storesp 4
|
||
poppc
|
||
|
||
# opcode 45
|
||
# offset 0x0000 01a0
|
||
.balign 32,0
|
||
_call:
|
||
; fn
|
||
loadsp 4
|
||
|
||
; return address
|
||
loadsp 4
|
||
|
||
; store return address
|
||
storesp 12
|
||
|
||
; fn to call
|
||
storesp 4
|
||
|
||
pushsp ; flush internal stack
|
||
popsp
|
||
|
||
poppc
|
||
|
||
_storehtail:
|
||
|
||
and
|
||
loadsp 12
|
||
im 3
|
||
and
|
||
fast_neg
|
||
im 2
|
||
add
|
||
im 3
|
||
ashiftleft
|
||
nop
|
||
ashiftleft
|
||
|
||
or
|
||
|
||
loadsp 8
|
||
im ~0x3
|
||
and
|
||
|
||
store
|
||
|
||
storesp 4
|
||
storesp 4
|
||
poppc
|
||
|
||
|
||
# opcode 46
|
||
# offset 0x0000 01c0
|
||
.balign 32,0
|
||
_eq:
|
||
loadsp 8
|
||
fast_neg
|
||
loadsp 8
|
||
add
|
||
|
||
not
|
||
loadsp 0
|
||
im 1
|
||
add
|
||
not
|
||
and
|
||
flip
|
||
im 1
|
||
and
|
||
|
||
storesp 12
|
||
storesp 4
|
||
poppc
|
||
|
||
# opcode 47
|
||
# offset 0x0000 01e0
|
||
.balign 32,0
|
||
_neq:
|
||
loadsp 8
|
||
fast_neg
|
||
loadsp 8
|
||
add
|
||
|
||
not
|
||
loadsp 0
|
||
im 1
|
||
add
|
||
not
|
||
and
|
||
flip
|
||
|
||
not
|
||
|
||
im 1
|
||
and
|
||
|
||
storesp 12
|
||
storesp 4
|
||
poppc
|
||
|
||
|
||
# opcode 48
|
||
# offset 0x0000 0200
|
||
.balign 32,0
|
||
_neg:
|
||
loadsp 4
|
||
not
|
||
im 1
|
||
add
|
||
storesp 8
|
||
|
||
poppc
|
||
|
||
|
||
# opcode 49
|
||
# offset 0x0000 0220
|
||
.balign 32,0
|
||
_sub:
|
||
loadsp 8
|
||
loadsp 8
|
||
fast_neg
|
||
add
|
||
storesp 12
|
||
|
||
storesp 4
|
||
|
||
poppc
|
||
|
||
|
||
# opcode 50
|
||
# offset 0x0000 0240
|
||
.balign 32,0
|
||
_xor:
|
||
loadsp 8
|
||
not
|
||
loadsp 8
|
||
and
|
||
|
||
loadsp 12
|
||
loadsp 12
|
||
not
|
||
and
|
||
|
||
or
|
||
|
||
storesp 12
|
||
storesp 4
|
||
poppc
|
||
|
||
# opcode 51
|
||
# offset 0x0000 0260
|
||
.balign 32,0
|
||
_loadb:
|
||
loadsp 4
|
||
im ~0x3
|
||
and
|
||
load
|
||
|
||
loadsp 8
|
||
im 3
|
||
and
|
||
fast_neg
|
||
im 3
|
||
add
|
||
; x8
|
||
addsp 0
|
||
addsp 0
|
||
addsp 0
|
||
|
||
lshiftright
|
||
|
||
im 0xff
|
||
and
|
||
storesp 8
|
||
|
||
poppc
|
||
|
||
|
||
# opcode 52
|
||
# offset 0x0000 0280
|
||
.balign 32,0
|
||
_storeb:
|
||
loadsp 4
|
||
im ~0x3
|
||
and
|
||
load
|
||
|
||
; mask away destination
|
||
im _mask
|
||
loadsp 12
|
||
im 3
|
||
and
|
||
addsp 0
|
||
addsp 0
|
||
add
|
||
load
|
||
|
||
and
|
||
|
||
|
||
im _storebtail
|
||
poppc
|
||
|
||
# opcode 53
|
||
# offset 0x0000 02a0
|
||
.balign 32,0
|
||
_div:
|
||
jmp ___div
|
||
|
||
# opcode 54
|
||
# offset 0x0000 02c0
|
||
.balign 32,0
|
||
_mod:
|
||
jmp ___mod
|
||
|
||
# opcode 55
|
||
# offset 0x0000 02e0
|
||
.balign 32,0
|
||
.globl _eqbranch
|
||
_eqbranch:
|
||
loadsp 8
|
||
|
||
; eq
|
||
|
||
not
|
||
loadsp 0
|
||
im 1
|
||
add
|
||
not
|
||
and
|
||
flip
|
||
im 1
|
||
and
|
||
|
||
; mask
|
||
im -1
|
||
add
|
||
loadsp 0
|
||
storesp 16
|
||
|
||
; no branch address
|
||
loadsp 4
|
||
|
||
and
|
||
|
||
; fetch boolean & neg mask
|
||
loadsp 12
|
||
not
|
||
|
||
; calc address & mask for branch
|
||
loadsp 8
|
||
loadsp 16
|
||
add
|
||
; subtract 1 to find PC of branch instruction
|
||
im -1
|
||
add
|
||
|
||
and
|
||
|
||
or
|
||
|
||
storesp 4
|
||
storesp 4
|
||
storesp 4
|
||
poppc
|
||
|
||
|
||
# opcode 56
|
||
# offset 0x0000 0300
|
||
.balign 32,0
|
||
.globl _neqbranch
|
||
_neqbranch:
|
||
loadsp 8
|
||
|
||
; neq
|
||
|
||
not
|
||
loadsp 0
|
||
im 1
|
||
add
|
||
not
|
||
and
|
||
flip
|
||
|
||
not
|
||
|
||
im 1
|
||
and
|
||
|
||
; mask
|
||
im -1
|
||
add
|
||
loadsp 0
|
||
storesp 16
|
||
|
||
; no branch address
|
||
loadsp 4
|
||
|
||
and
|
||
|
||
; fetch boolean & neg mask
|
||
loadsp 12
|
||
not
|
||
|
||
; calc address & mask for branch
|
||
loadsp 8
|
||
loadsp 16
|
||
add
|
||
; find address of branch instruction
|
||
im -1
|
||
add
|
||
|
||
and
|
||
|
||
or
|
||
|
||
storesp 4
|
||
storesp 4
|
||
storesp 4
|
||
poppc
|
||
|
||
# opcode 57
|
||
# offset 0x0000 0320
|
||
.balign 32,0
|
||
.globl _poppcrel
|
||
_poppcrel:
|
||
add
|
||
; address of poppcrel
|
||
im -1
|
||
add
|
||
poppc
|
||
|
||
# opcode 58
|
||
# offset 0x0000 0340
|
||
.balign 32,0
|
||
.globl _config
|
||
_config:
|
||
im 1
|
||
nop
|
||
im _hardware
|
||
store
|
||
storesp 4
|
||
poppc
|
||
|
||
# opcode 59
|
||
# offset 0x0000 0360
|
||
.balign 32,0
|
||
_pushpc:
|
||
loadsp 4
|
||
im 1
|
||
add
|
||
storesp 8
|
||
poppc
|
||
|
||
# opcode 60
|
||
# offset 0x0000 0380
|
||
.balign 32,0
|
||
_syscall_emulate:
|
||
.byte 0
|
||
|
||
# opcode 61
|
||
# offset 0x0000 03a0
|
||
.balign 32,0
|
||
_pushspadd:
|
||
pushsp
|
||
im 4
|
||
add
|
||
loadsp 8
|
||
addsp 0
|
||
addsp 0
|
||
add
|
||
storesp 8
|
||
|
||
poppc
|
||
|
||
# opcode 62
|
||
# offset 0x0000 03c0
|
||
.balign 32,0
|
||
_halfmult:
|
||
breakpoint
|
||
|
||
# opcode 63
|
||
# offset 0x0000 03e0
|
||
.balign 32,0
|
||
_callpcrel:
|
||
loadsp 4
|
||
loadsp 4
|
||
add
|
||
im -1
|
||
add
|
||
loadsp 4
|
||
|
||
storesp 12 ; return address
|
||
storesp 4
|
||
pushsp ; this will flush the internal stack.
|
||
popsp
|
||
poppc
|
||
|
||
.text
|
||
|
||
|
||
|
||
|
||
_ashiftleftBegin:
|
||
.rept 0x1f
|
||
addsp 0
|
||
.endr
|
||
_ashiftleftEnd:
|
||
storesp 12
|
||
storesp 4
|
||
poppc
|
||
|
||
_storebtail:
|
||
loadsp 12
|
||
im 0xff
|
||
and
|
||
loadsp 12
|
||
im 3
|
||
and
|
||
|
||
fast_neg
|
||
im 3
|
||
add
|
||
; x8
|
||
addsp 0
|
||
addsp 0
|
||
addsp 0
|
||
|
||
ashiftleft
|
||
|
||
or
|
||
|
||
loadsp 8
|
||
im ~0x3
|
||
and
|
||
|
||
store
|
||
|
||
storesp 4
|
||
storesp 4
|
||
poppc
|
||
|
||
|
||
|
||
|
||
; NB! this is not an EMULATE instruction. It is a varargs fn.
|
||
.globl _syscall
|
||
_syscall:
|
||
syscall
|
||
poppc
|
||
|
||
_slowmultImpl:
|
||
|
||
loadsp 8 ; A
|
||
loadsp 8 ; B
|
||
im 0 ; C
|
||
|
||
.LmoreMult:
|
||
mult1bit
|
||
|
||
; cutoff
|
||
loadsp 8
|
||
.byte (.LmoreMult-.Lbranch)&0x7f+0x80
|
||
.Lbranch:
|
||
neqbranch
|
||
|
||
storesp 4
|
||
storesp 4
|
||
storesp 12
|
||
storesp 4
|
||
poppc
|
||
|
||
___mod:
|
||
cimpl __modsi3
|
||
___div:
|
||
cimpl __divsi3
|
||
|
||
.globl ___zpu_interrupt_vector
|
||
.weak ___zpu_interrupt_vector
|
||
|
||
___zpu_interrupt_vector:
|
||
jsr _zpu_interrupt
|
||
poppc
|
||
|
||
.section ".rodata"
|
||
.balign 4,0
|
Also available in: Unified diff
Fork of firmware for 5200 - will be merged back in soon...