├── GCC └── VC4_PSPROTO │ ├── VC4 │ ├── code.bin │ ├── link.ld │ ├── make.sh │ ├── ps_protocol.bin │ ├── ps_protocol.c │ ├── ps_protocol.h │ ├── start.o │ └── start.s │ └── pistorm │ ├── .gitignore │ └── software │ ├── Makefile │ ├── a314 │ ├── a314.cc │ ├── a314.h │ ├── a314.o │ └── a314device │ │ ├── a314.h │ │ ├── a314driver.c │ │ ├── build.bat │ │ ├── debug.h │ │ ├── device.c │ │ ├── device.h │ │ ├── fix_mem_region.c │ │ ├── fix_mem_region.h │ │ ├── int_server.asm │ │ ├── proto_a314.h │ │ ├── protocol.h │ │ ├── romtag.asm │ │ ├── sockets.c │ │ ├── sockets.h │ │ ├── startup.c │ │ └── startup.h │ ├── code.bin │ ├── gayle.c │ ├── gayle.h │ ├── ide │ ├── ide.c │ ├── ide.h │ ├── ide.o │ ├── makedisk │ └── makedisk.c │ ├── m68k.h │ ├── m68k_in.c │ ├── m68kconf.h │ ├── m68kcpu.c │ ├── m68kcpu.h │ ├── m68kdasm.c │ ├── m68kfpu.c │ ├── m68kmake │ ├── m68kmake.c │ ├── m68kmmu.h │ ├── m68kops.c │ ├── m68kops.h │ ├── mailbox.c │ ├── mailbox.h │ ├── pistorm.c │ ├── ps_autoconfig.c │ ├── ps_autoconfig.h │ ├── ps_customchips.c │ ├── ps_customchips.h │ ├── ps_fastmem.c │ ├── ps_fastmem.h │ ├── ps_kickstart.c │ ├── ps_kickstart.h │ ├── ps_mappings.c │ ├── ps_mappings.h │ ├── ps_protocol.c │ ├── ps_protocol.c.arm │ ├── ps_protocol.c.save │ ├── ps_protocol.h │ ├── psconf.h │ └── softfloat │ ├── README.txt │ ├── mamesf.h │ ├── milieu.h │ ├── softfloat-macros │ ├── softfloat-specialize │ ├── softfloat.c │ ├── softfloat.h │ └── softfloat.o ├── Makefile ├── README.md ├── code.asm ├── code.asm.poke ├── mailbox.c ├── mailbox.h ├── main.c └── vasmvidcore /GCC/VC4_PSPROTO/VC4/code.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/captain-amygdala/VPU-example/577057b56d3f64027cb021fb86807f3d25beeee6/GCC/VC4_PSPROTO/VC4/code.bin -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/VC4/link.ld: -------------------------------------------------------------------------------- 1 | SECTIONS { 2 | . = 0x00; 3 | } 4 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/VC4/make.sh: -------------------------------------------------------------------------------- 1 | ./vc4-elf-as start.s -o start.o 2 | #./vc4-elf-gcc -nostartfiles -fpic -ffreestanding -nostdlib ps_protocol.c -o ps_protocol.s -S 3 | #./vc4-elf-as ps_protocol.s -o ps_protocol.bin -nostartfiles 4 | #./vc4-elf-gcc -nostartfiles -fpic -ffreestanding -nostdlib start.o ps_protocol.c -O3 -o ps_protocol.bin 5 | ./vc4-elf-gcc -nostartfiles -fpic -nostdlib start.o ps_protocol.c -O3 -T link.ld -o ps_protocol.bin 6 | ./vc4-elf-objcopy -O binary ps_protocol.bin code.bin 7 | scp code.bin pi@192.168.1.108:/home/pi/pistorm/software/code.bin 8 | #scp code.bin pi@192.168.1.108:/home/pi/VPU-example/code.bin 9 | #ssh -t pi@192.168.1.108 sudo reboot 10 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/VC4/ps_protocol.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/captain-amygdala/VPU-example/577057b56d3f64027cb021fb86807f3d25beeee6/GCC/VC4_PSPROTO/VC4/ps_protocol.bin -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/VC4/ps_protocol.c: -------------------------------------------------------------------------------- 1 | #include "ps_protocol.h" 2 | 3 | /* 4 | MBOX0 = ADDR 5 | MBOX1 = DATAL 6 | MBOX2 = DATAH 7 | MBOX3 = CSR 8 | 9 | CSR BITS: 10 | 11 | 0 START/BSY 12 | 1 R/_W 13 | 2 SIZE (8/16/32/64) 14 | 3 SIZE 15 | 4 STATUS_OP 16 | . 17 | . 18 | . 19 | */ 20 | 21 | #define cmd_w8 1 22 | #define cmd_r8 3 23 | #define cmd_w16 5 24 | #define cmd_r16 7 25 | #define cmd_w32 9 26 | #define cmd_r32 11 27 | #define cmd_w64 13 28 | #define cmd_r64 15 29 | #define cmd_stat 17 30 | #define cmd_ipl 19 31 | 32 | int main (void){ 33 | 34 | gpio = (unsigned int*)0x7e200000; 35 | mbox = (unsigned int*)0x7e0000a0; 36 | idle = 0xffffec; 37 | 38 | *(gdir0) = GPFSEL0_INPUT;*(gdir1) = GPFSEL1_INPUT;*(gdir2) = GPFSEL2_INPUT; 39 | 40 | unsigned int cmd; 41 | 42 | //asm("di"); 43 | 44 | for(;;) { 45 | 46 | cmd = *(mbox3); 47 | while (*(gplev) & (1 << PIN_TXN_IN_PROGRESS)) {} 48 | 49 | switch(cmd & 0x1f) { 50 | case cmd_r8: ps_read_8(*(mbox0));*(mbox3) = cmd &= ~(1 << 0);break; 51 | case cmd_r16:ps_read_16(*(mbox0));*(mbox3) = cmd &= ~(1 << 0);break; 52 | case cmd_r32:ps_read_32(*(mbox0));*(mbox3) = cmd &= ~(1 << 0);break; 53 | case cmd_r64:ps_read_32(*(mbox0));*(mbox3) = cmd &= ~(1 << 0);break; 54 | case cmd_w8: ps_write_8(*(mbox0),*(mbox1));*(mbox3) = cmd &= ~(1 << 0);break; 55 | case cmd_w16:ps_write_16(*(mbox0),*(mbox1));*(mbox3) = cmd &= ~(1 << 0);break; 56 | case cmd_w32:ps_write_32(*(mbox0),*(mbox1));*(mbox3) = cmd &= ~(1 << 0);break; 57 | case cmd_w64:ps_write_32(*(mbox0),*(mbox1));*(mbox3) = cmd &= ~(1 << 0);break; 58 | case cmd_stat:ps_read_status_reg();*(mbox3) = cmd &= ~(1 << 0);break; 59 | case cmd_ipl:*(mbox1) = *(gplev) & (1 << PIN_IPL_ZERO);*(mbox3) = cmd &= ~(1 << 0);break; 60 | default: break; 61 | } 62 | } 63 | } 64 | 65 | void ps_read_status_reg() { 66 | *(gset) = (REG_STATUS << PIN_A0); 67 | *(gset) = 1 << PIN_RD;*(gset) = 1 << PIN_RD;*(gset) = 1 << PIN_RD;*(gset) = 1 << PIN_RD; 68 | 69 | *(mbox1) = (*(gplev) >> 8) & 0xffff; 70 | *(gclr) = idle; 71 | } 72 | 73 | //WRITE 68k 74 | 75 | void ps_write_8(unsigned int address, unsigned int data) { 76 | 77 | if ((address & 1) == 0) 78 | data = data + (data << 8); // EVEN, A0=0,UDS 79 | else 80 | data = data & 0xff; // ODD , A0=1,LDS 81 | 82 | *(gdir0) = GPFSEL0_OUTPUT;*(gdir1) = GPFSEL1_OUTPUT;*(gdir2) = GPFSEL2_OUTPUT; 83 | 84 | *(gset) = ((data & 0xffff) << 8) | (REG_DATA << PIN_A0); 85 | *(gset) = 1 << PIN_WR;*(gclr) = 1 << PIN_WR;*(gclr) = idle; 86 | 87 | *(gset) = ((address & 0xffff) << 8) | (REG_ADDR_LO << PIN_A0); 88 | *(gset) = 1 << PIN_WR;*(gclr) = 1 << PIN_WR;*(gclr) = idle; 89 | 90 | *(gset) = ((0x0100 | (address >> 16)) << 8) | (REG_ADDR_HI << PIN_A0); 91 | *(gset) = 1 << PIN_WR;*(gclr) = 1 << PIN_WR;*(gclr) = idle; 92 | 93 | *(gdir0) = GPFSEL0_INPUT;*(gdir1) = GPFSEL1_INPUT;*(gdir2) = GPFSEL2_INPUT; 94 | 95 | // while (*(gplev) & (1 << PIN_TXN_IN_PROGRESS)) {} 96 | } 97 | 98 | void ps_write_16(unsigned int address, unsigned int data) { 99 | 100 | while (*(gplev) & (1 << PIN_TXN_IN_PROGRESS)) {} 101 | 102 | *(gdir0) = GPFSEL0_OUTPUT;*(gdir1) = GPFSEL1_OUTPUT;*(gdir2) = GPFSEL2_OUTPUT; 103 | 104 | *(gset) = ((data & 0xffff) << 8) | (REG_DATA << PIN_A0); 105 | *(gset) = 1 << PIN_WR;*(gclr) = 1 << PIN_WR;*(gclr) = idle; 106 | 107 | *(gset) = ((address & 0xffff) << 8) | (REG_ADDR_LO << PIN_A0); 108 | *(gset) = 1 << PIN_WR;*(gclr) = 1 << PIN_WR;*(gclr) = idle; 109 | 110 | *(gset) = ((0x0000 | (address >> 16)) << 8) | (REG_ADDR_HI << PIN_A0); 111 | *(gset) = 1 << PIN_WR;*(gclr) = 1 << PIN_WR;*(gclr) = idle; 112 | 113 | *(gdir0) = GPFSEL0_INPUT;*(gdir1) = GPFSEL1_INPUT;*(gdir2) = GPFSEL2_INPUT; 114 | 115 | // while (*(gplev) & (1 << PIN_TXN_IN_PROGRESS)) {} 116 | } 117 | 118 | void ps_write_32(unsigned int address, unsigned int data) { 119 | ps_write_16(address, data >> 16); 120 | while (*(gplev) & (1 << PIN_TXN_IN_PROGRESS)) {} 121 | ps_write_16(address + 2, data); 122 | } 123 | 124 | 125 | //READ 68k 126 | 127 | void ps_read_8(unsigned int address) { 128 | *(gdir0) = GPFSEL0_OUTPUT;*(gdir1) = GPFSEL1_OUTPUT;*(gdir2) = GPFSEL2_OUTPUT; 129 | 130 | *(gset) = ((address & 0xffff) << 8) | (REG_ADDR_LO << PIN_A0); 131 | *(gset) = 1 << PIN_WR;*(gclr) = 1 << PIN_WR;*(gclr) = idle; 132 | 133 | *(gset) = ((0x0300 | (address >> 16)) << 8) | (REG_ADDR_HI << PIN_A0); 134 | *(gset) = 1 << PIN_WR;*(gclr) = 1 << PIN_WR;*(gclr) = idle; 135 | 136 | *(gdir0) = GPFSEL0_INPUT;*(gdir1) = GPFSEL1_INPUT;*(gdir2) = GPFSEL2_INPUT; 137 | 138 | *(gset) = (REG_DATA << PIN_A0);*(gset) = 1 << PIN_RD; 139 | 140 | //TODO 141 | while (*(gplev) & (1 << PIN_TXN_IN_PROGRESS)) {} 142 | unsigned int value = *(gplev); 143 | 144 | *(gclr) = idle; 145 | 146 | value = (value >> 8) & 0xffff; 147 | 148 | if ((address & 1) == 0) 149 | *(mbox1) = (value >> 8) & 0xff; // EVEN, A0=0,UDS 150 | else 151 | *(mbox1) = value & 0xff; // ODD , A0=1,LDS 152 | } 153 | void ps_read_16(unsigned int address) { 154 | *(gdir0) = GPFSEL0_OUTPUT;*(gdir1) = GPFSEL1_OUTPUT;*(gdir2) = GPFSEL2_OUTPUT; 155 | 156 | *(gset) = ((address & 0xffff) << 8) | (REG_ADDR_LO << PIN_A0); 157 | *(gset) = 1 << PIN_WR;*(gclr) = 1 << PIN_WR;*(gclr) = idle; 158 | 159 | *(gset) = ((0x0200 | (address >> 16)) << 8) | (REG_ADDR_HI << PIN_A0); 160 | *(gset) = 1 << PIN_WR;*(gclr) = 1 << PIN_WR;*(gclr) = idle; 161 | 162 | *(gdir0) = GPFSEL0_INPUT;*(gdir1) = GPFSEL1_INPUT;*(gdir2) = GPFSEL2_INPUT; 163 | 164 | *(gset) = (REG_DATA << PIN_A0);*(gset) = 1 << PIN_RD; 165 | 166 | //TODO 167 | while (*(gplev) & (1 << PIN_TXN_IN_PROGRESS)) {} 168 | unsigned int value = *(gplev); 169 | 170 | *(gclr) = idle; 171 | *(mbox1) = (value >> 8) & 0xffff; 172 | } 173 | 174 | void ps_read_32(unsigned int address) { 175 | unsigned int a; 176 | unsigned int b; 177 | 178 | ps_read_16(address); 179 | a = *(mbox1); 180 | while (*(gplev) & (1 << PIN_TXN_IN_PROGRESS)) {} 181 | ps_read_16(address + 2); 182 | b = *(mbox1); 183 | 184 | *(mbox1) = (a << 16) | b; 185 | } 186 | 187 | 188 | 189 | 190 | 191 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/VC4/ps_protocol.h: -------------------------------------------------------------------------------- 1 | // SPDX-License-Identifier: MIT 2 | 3 | /* 4 | Code reorganized and rewritten by 5 | Niklas Ekström 2021 (https://github.com/niklasekstrom) 6 | */ 7 | 8 | #ifndef _PS_PROTOCOL_H 9 | #define _PS_PROTOCOL_H 10 | 11 | #define PIN_TXN_IN_PROGRESS 0 12 | #define PIN_IPL_ZERO 1 13 | #define PIN_A0 2 14 | #define PIN_A1 3 15 | #define PIN_CLK 4 16 | #define PIN_RESET 5 17 | #define PIN_RD 6 18 | #define PIN_WR 7 19 | #define PIN_D(x) (8 + x) 20 | 21 | #define REG_DATA 0 22 | #define REG_ADDR_LO 1 23 | #define REG_ADDR_HI 2 24 | #define REG_STATUS 3 25 | 26 | #define STATUS_BIT_INIT 1 27 | #define STATUS_BIT_RESET 2 28 | 29 | #define STATUS_MASK_IPL 0xe000 30 | #define STATUS_SHIFT_IPL 13 31 | 32 | //#define BCM2708_PERI_BASE 0x20000000 // pi0-1 33 | #define BCM2708_PERI_BASE 0x7E000000 // pi4 34 | //#define BCM2708_PERI_BASE 0x3F000000 // pi3 35 | //#define BCM2708_PERI_SIZE 0x01000000 36 | 37 | #define GPIO_ADDR 0x200000 /* GPIO controller */ 38 | #define GPCLK_ADDR 0x101000 39 | 40 | #define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */ 41 | #define GPCLK_BASE (BCM2708_PERI_BASE + 0x101000) 42 | 43 | #define CLK_PASSWD 0x5a000000 44 | #define CLK_GP0_CTL 0x070 45 | #define CLK_GP0_DIV 0x074 46 | 47 | // GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or 48 | // SET_GPIO_ALT(x,y) 49 | #define INP_GPIO(g) *(gpio + ((g) / 10)) &= ~(7 << (((g) % 10) * 3)) 50 | #define OUT_GPIO(g) *(gpio + ((g) / 10)) |= (1 << (((g) % 10) * 3)) 51 | #define SET_GPIO_ALT(g, a) \ 52 | *(gpio + (((g) / 10))) |= \ 53 | (((a) <= 3 ? (a) + 4 : (a) == 4 ? 3 : 2) << (((g) % 10) * 3)) 54 | 55 | #define GPIO_PULL *(gpio + 37) // Pull up/pull down 56 | #define GPIO_PULLCLK0 *(gpio + 38) // Pull up/pull down clock 57 | 58 | #define GPFSEL0_INPUT 0x00244240 59 | #define GPFSEL1_INPUT 0x00000000 60 | #define GPFSEL2_INPUT 0x00000000 61 | 62 | #define GPFSEL0_OUTPUT 0x09244240 63 | #define GPFSEL1_OUTPUT 0x09249249 64 | #define GPFSEL2_OUTPUT 0x00000249 65 | 66 | #define GPFSEL_OUTPUT \ 67 | *(gpio + 0) = GPFSEL0_OUTPUT; \ 68 | *(gpio + 1) = GPFSEL1_OUTPUT; \ 69 | *(gpio + 2) = GPFSEL2_OUTPUT; 70 | 71 | #define GPFSEL_INPUT \ 72 | *(gpio + 0) = GPFSEL0_INPUT; \ 73 | *(gpio + 1) = GPFSEL1_INPUT; \ 74 | *(gpio + 2) = GPFSEL2_INPUT; 75 | 76 | #define GPIO_WRITEREG(reg, val) \ 77 | *(gpio + 7) = (val << 8) | (reg << PIN_A0); \ 78 | *(gpio + 7) = 1 << PIN_WR; \ 79 | *(gpio + 10) = 1 << PIN_WR; \ 80 | *(gpio + 10) = 0xFFFFEC; 81 | 82 | #define GPIO_PIN_RD \ 83 | *(gpio + 7) = (REG_DATA << PIN_A0); \ 84 | *(gpio + 7) = 1 << PIN_RD; 85 | 86 | #define WAIT_TXN \ 87 | while (*(gpio + 13) & (1 << PIN_TXN_IN_PROGRESS)) {} 88 | 89 | #define END_TXN \ 90 | *(gpio + 10) = 0xFFFFEC; 91 | 92 | 93 | //VPU Stuff 94 | #define gset gpio+7 95 | #define gclr gpio+10 96 | #define gdir0 gpio 97 | #define gdir1 gpio+1 98 | #define gdir2 gpio+2 99 | #define gplev gpio+13 100 | #define mbox0 mbox 101 | #define mbox1 mbox+1 102 | #define mbox2 mbox+2 103 | #define mbox3 mbox+3 104 | #define mbox4 mbox+4 105 | #define mbox5 mbox+5 106 | #define mbox6 mbox+6 107 | #define mbox7 mbox+7 108 | 109 | volatile register unsigned int *mbox asm ("r23"); 110 | volatile register unsigned int *gpio asm ("r22"); 111 | volatile register unsigned int idle asm ("r21"); 112 | 113 | 114 | void ps_read_8(unsigned int address); 115 | void ps_read_16(unsigned int address); 116 | void ps_read_32(unsigned int address); 117 | 118 | 119 | void busyloop(void); 120 | 121 | 122 | void ps_write_8(unsigned int address, unsigned int data); 123 | void ps_write_16(unsigned int address, unsigned int data); 124 | void ps_write_32(unsigned int address, unsigned int data); 125 | 126 | void ps_read_status_reg(); 127 | void ps_write_status_reg(unsigned int value); 128 | 129 | void ps_setup_protocol(); 130 | void ps_reset_state_machine(); 131 | void ps_pulse_reset(); 132 | 133 | unsigned int ps_get_ipl_zero(); 134 | 135 | 136 | #endif /* _PS_PROTOCOL_H */ 137 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/VC4/start.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/captain-amygdala/VPU-example/577057b56d3f64027cb021fb86807f3d25beeee6/GCC/VC4_PSPROTO/VC4/start.o -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/VC4/start.s: -------------------------------------------------------------------------------- 1 | .global _start 2 | _start: 3 | mov sp,#0xffffffc 4 | b main 5 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/Makefile: -------------------------------------------------------------------------------- 1 | EXENAME = pistorm 2 | 3 | MAINFILES = pistorm.c ps_protocol.c ps_mappings.c ps_autoconfig.c ps_customchips.c ps_fastmem.c ps_kickstart.c gayle.c ide/ide.c mailbox.c 4 | MUSASHIFILES = m68kcpu.c softfloat/softfloat.c 5 | MUSASHIGENCFILES = m68kops.c 6 | MUSASHIGENHFILES = m68kops.h 7 | MUSASHIGENERATOR = m68kmake 8 | 9 | EXEPATH = ./ 10 | 11 | .CFILES = $(MAINFILES) $(MUSASHIFILES) $(MUSASHIGENCFILES) 12 | .OFILES = $(.CFILES:%.c=%.o) a314/a314.o 13 | 14 | CC = gcc 15 | CPP = g++ 16 | WARNINGS = -Wall -Wextra -pedantic 17 | CFLAGS = $(WARNINGS) -march=armv7 -O3 18 | #CFLAGS = $(WARNINGS) -O3 19 | LFLAGS = $(WARNINGS) 20 | 21 | TARGET = $(EXENAME)$(EXE) 22 | 23 | DELETEFILES = $(MUSASHIGENCFILES) $(MUSASHIGENHFILES) $(.OFILES) $(TARGET) $(MUSASHIGENERATOR)$(EXE) 24 | 25 | all: $(TARGET) 26 | 27 | clean: 28 | rm -f $(DELETEFILES) 29 | 30 | $(TARGET): $(MUSASHIGENHFILES) $(.OFILES) Makefile 31 | $(CC) -o $@ $(.OFILES) -O3 -pthread $(LFLAGS) -lm -lstdc++ 32 | 33 | a314/a314.o: a314/a314.cc a314/a314.h 34 | $(CPP) -c -o a314/a314.o -O3 a314/a314.cc 35 | 36 | $(MUSASHIGENCFILES) $(MUSASHIGENHFILES): $(MUSASHIGENERATOR)$(EXE) 37 | $(EXEPATH)$(MUSASHIGENERATOR)$(EXE) 38 | 39 | $(MUSASHIGENERATOR)$(EXE): $(MUSASHIGENERATOR).c 40 | $(CC) -o $(MUSASHIGENERATOR)$(EXE) $(MUSASHIGENERATOR).c 41 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/a314/a314.h: -------------------------------------------------------------------------------- 1 | #ifndef _A314_H 2 | #define _A314_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | int a314_init(); 9 | int a314_check_int2(); 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif 14 | 15 | #endif /* _A314_H */ 16 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/a314/a314.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/captain-amygdala/VPU-example/577057b56d3f64027cb021fb86807f3d25beeee6/GCC/VC4_PSPROTO/pistorm/software/a314/a314.o -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/a314/a314device/a314.h: -------------------------------------------------------------------------------- 1 | #ifndef DEVICES_A314_H 2 | #define DEVICES_A314_H 3 | 4 | #include 5 | 6 | #define A314_NAME "a314.device" 7 | 8 | #define A314_CONNECT (CMD_NONSTD+0) 9 | #define A314_READ (CMD_NONSTD+1) 10 | #define A314_WRITE (CMD_NONSTD+2) 11 | #define A314_EOS (CMD_NONSTD+3) 12 | #define A314_RESET (CMD_NONSTD+4) 13 | 14 | #define A314_CONNECT_OK 0 15 | #define A314_CONNECT_SOCKET_IN_USE 1 16 | #define A314_CONNECT_RESET 2 17 | #define A314_CONNECT_UNKNOWN_SERVICE 3 18 | 19 | #define A314_READ_OK 0 20 | #define A314_READ_EOS 1 21 | #define A314_READ_RESET 2 22 | 23 | #define A314_WRITE_OK 0 24 | #define A314_WRITE_EOS_SENT 1 25 | #define A314_WRITE_RESET 2 26 | 27 | #define A314_EOS_OK 0 28 | #define A314_EOS_EOS_SENT 1 29 | #define A314_EOS_RESET 2 30 | 31 | #define A314_RESET_OK 0 32 | 33 | #define MEMF_A314 (1<<7) 34 | 35 | struct A314_IORequest 36 | { 37 | struct IORequest a314_Request; 38 | ULONG a314_Socket; 39 | STRPTR a314_Buffer; 40 | WORD a314_Length; 41 | }; 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/a314/a314device/a314driver.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 Niklas Ekström 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | #include 20 | 21 | #include 22 | 23 | #include "a314.h" 24 | #include "debug.h" 25 | #include "device.h" 26 | #include "protocol.h" 27 | #include "sockets.h" 28 | #include "fix_mem_region.h" 29 | #include "startup.h" 30 | 31 | int used_in_r2a() 32 | { 33 | return (ca->r2a_tail - ca->r2a_head) & 255; 34 | } 35 | 36 | int used_in_a2r() 37 | { 38 | return (ca->a2r_tail - ca->a2r_head) & 255; 39 | } 40 | 41 | BOOL room_in_a2r(int len) 42 | { 43 | return used_in_a2r() + 3 + len <= 255; 44 | } 45 | 46 | void append_a2r_packet(UBYTE type, UBYTE stream_id, UBYTE length, UBYTE *data) 47 | { 48 | UBYTE index = ca->a2r_tail; 49 | ca->a2r_buffer[index++] = length; 50 | ca->a2r_buffer[index++] = type; 51 | ca->a2r_buffer[index++] = stream_id; 52 | for (int i = 0; i < (int)length; i++) 53 | ca->a2r_buffer[index++] = *data++; 54 | ca->a2r_tail = index; 55 | } 56 | 57 | void close_socket(struct Socket *s, BOOL should_send_reset) 58 | { 59 | debug_printf("Called close socket\n"); 60 | 61 | if (s->pending_connect != NULL) 62 | { 63 | struct A314_IORequest *ior = s->pending_connect; 64 | ior->a314_Request.io_Error = A314_CONNECT_RESET; 65 | ReplyMsg((struct Message *)ior); 66 | 67 | s->pending_connect = NULL; 68 | } 69 | 70 | if (s->pending_read != NULL) 71 | { 72 | struct A314_IORequest *ior = s->pending_read; 73 | ior->a314_Length = 0; 74 | ior->a314_Request.io_Error = A314_READ_RESET; 75 | ReplyMsg((struct Message *)ior); 76 | 77 | s->pending_read = NULL; 78 | } 79 | 80 | if (s->pending_write != NULL) 81 | { 82 | struct A314_IORequest *ior = s->pending_write; 83 | ior->a314_Length = 0; 84 | ior->a314_Request.io_Error = A314_WRITE_RESET; // A314_EOS_RESET == A314_WRITE_RESET 85 | ReplyMsg((struct Message *)ior); 86 | 87 | s->pending_write = NULL; 88 | } 89 | 90 | if (s->rq_head != NULL) 91 | { 92 | struct QueuedData *qd = s->rq_head; 93 | while (qd != NULL) 94 | { 95 | struct QueuedData *next = qd->next; 96 | FreeMem(qd, sizeof(struct QueuedData) + qd->length); 97 | qd = next; 98 | } 99 | s->rq_head = NULL; 100 | s->rq_tail = NULL; 101 | } 102 | 103 | remove_from_send_queue(s); 104 | 105 | // No operations can be pending when SOCKET_CLOSED is set. 106 | // However, may not be able to delete socket yet, because is waiting to send PKT_RESET. 107 | s->flags |= SOCKET_CLOSED; 108 | 109 | BOOL should_delete_socket = TRUE; 110 | 111 | if (should_send_reset) 112 | { 113 | if (send_queue_head == NULL && room_in_a2r(0)) 114 | { 115 | append_a2r_packet(PKT_RESET, s->stream_id, 0, NULL); 116 | } 117 | else 118 | { 119 | s->flags |= SOCKET_SHOULD_SEND_RESET; 120 | add_to_send_queue(s, 0); 121 | should_delete_socket = FALSE; 122 | } 123 | } 124 | 125 | if (should_delete_socket) 126 | delete_socket(s); 127 | } 128 | 129 | // When a message is received on R2A it is written to this buffer, 130 | // to avoid dealing with the issue that R2A is a circular buffer. 131 | // This is somewhat inefficient, so may want to change that to read from R2A directly. 132 | UBYTE received_packet[256]; 133 | 134 | static void handle_pkt_connect_response(UBYTE length, struct Socket *s) 135 | { 136 | debug_printf("Received a CONNECT RESPONSE packet from rpi\n"); 137 | 138 | if (s->pending_connect == NULL) 139 | { 140 | debug_printf("SERIOUS ERROR: received a CONNECT RESPONSE even though no connect was pending\n"); 141 | // Should reset stream? 142 | } 143 | else if (length != 1) 144 | { 145 | debug_printf("SERIOUS ERROR: received a CONNECT RESPONSE whose length was not 1\n"); 146 | // Should reset stream? 147 | } 148 | else 149 | { 150 | UBYTE result = received_packet[0]; 151 | if (result == 0) 152 | { 153 | struct A314_IORequest *ior = s->pending_connect; 154 | ior->a314_Request.io_Error = A314_CONNECT_OK; 155 | ReplyMsg((struct Message *)ior); 156 | 157 | s->pending_connect = NULL; 158 | } 159 | else 160 | { 161 | struct A314_IORequest *ior = s->pending_connect; 162 | ior->a314_Request.io_Error = A314_CONNECT_UNKNOWN_SERVICE; 163 | ReplyMsg((struct Message *)ior); 164 | 165 | s->pending_connect = NULL; 166 | 167 | close_socket(s, FALSE); 168 | } 169 | } 170 | } 171 | 172 | static void handle_pkt_data(UBYTE length, struct Socket *s) 173 | { 174 | debug_printf("Received a DATA packet from rpi\n"); 175 | 176 | if (s->pending_read != NULL) 177 | { 178 | struct A314_IORequest *ior = s->pending_read; 179 | 180 | if (ior->a314_Length < length) 181 | close_socket(s, TRUE); 182 | else 183 | { 184 | memcpy(ior->a314_Buffer, received_packet, length); 185 | ior->a314_Length = length; 186 | ior->a314_Request.io_Error = A314_READ_OK; 187 | ReplyMsg((struct Message *)ior); 188 | 189 | s->pending_read = NULL; 190 | } 191 | } 192 | else 193 | { 194 | struct QueuedData *qd = (struct QueuedData *)AllocMem(sizeof(struct QueuedData) + length, 0); 195 | qd->next = NULL, 196 | qd->length = length; 197 | memcpy(qd->data, received_packet, length); 198 | 199 | if (s->rq_head == NULL) 200 | s->rq_head = qd; 201 | else 202 | s->rq_tail->next = qd; 203 | s->rq_tail = qd; 204 | } 205 | } 206 | 207 | static void handle_pkt_eos(struct Socket *s) 208 | { 209 | debug_printf("Received a EOS packet from rpi\n"); 210 | 211 | s->flags |= SOCKET_RCVD_EOS_FROM_RPI; 212 | 213 | if (s->pending_read != NULL) 214 | { 215 | struct A314_IORequest *ior = s->pending_read; 216 | ior->a314_Length = 0; 217 | ior->a314_Request.io_Error = A314_READ_EOS; 218 | ReplyMsg((struct Message *)ior); 219 | 220 | s->pending_read = NULL; 221 | 222 | s->flags |= SOCKET_SENT_EOS_TO_APP; 223 | 224 | if (s->flags & SOCKET_SENT_EOS_TO_RPI) 225 | close_socket(s, FALSE); 226 | } 227 | } 228 | 229 | static void handle_r2a_packet(UBYTE type, UBYTE stream_id, UBYTE length) 230 | { 231 | struct Socket *s = find_socket_by_stream_id(stream_id); 232 | 233 | if (s != NULL && type == PKT_RESET) 234 | { 235 | debug_printf("Received a RESET packet from rpi\n"); 236 | close_socket(s, FALSE); 237 | return; 238 | } 239 | 240 | if (s == NULL || (s->flags & SOCKET_CLOSED)) 241 | { 242 | // Ignore this packet. The only packet that can do anything useful on a closed 243 | // channel is CONNECT, which is not handled at this time. 244 | return; 245 | } 246 | 247 | if (type == PKT_CONNECT_RESPONSE) 248 | { 249 | handle_pkt_connect_response(length, s); 250 | } 251 | else if (type == PKT_DATA) 252 | { 253 | handle_pkt_data(length, s); 254 | } 255 | else if (type == PKT_EOS) 256 | { 257 | handle_pkt_eos(s); 258 | } 259 | } 260 | 261 | void handle_packets_received_r2a() 262 | { 263 | while (used_in_r2a() != 0) 264 | { 265 | UBYTE index = ca->r2a_head; 266 | 267 | UBYTE len = ca->r2a_buffer[index++]; 268 | UBYTE type = ca->r2a_buffer[index++]; 269 | UBYTE stream_id = ca->r2a_buffer[index++]; 270 | 271 | for (int i = 0; i < len; i++) 272 | received_packet[i] = ca->r2a_buffer[index++]; 273 | 274 | ca->r2a_head = index; 275 | 276 | handle_r2a_packet(type, stream_id, len); 277 | } 278 | } 279 | 280 | void handle_room_in_a2r() 281 | { 282 | while (send_queue_head != NULL) 283 | { 284 | struct Socket *s = send_queue_head; 285 | 286 | if (!room_in_a2r(s->send_queue_required_length)) 287 | break; 288 | 289 | remove_from_send_queue(s); 290 | 291 | if (s->pending_connect != NULL) 292 | { 293 | struct A314_IORequest *ior = s->pending_connect; 294 | int len = ior->a314_Length; 295 | append_a2r_packet(PKT_CONNECT, s->stream_id, (UBYTE)len, ior->a314_Buffer); 296 | } 297 | else if (s->pending_write != NULL) 298 | { 299 | struct A314_IORequest *ior = s->pending_write; 300 | int len = ior->a314_Length; 301 | 302 | if (ior->a314_Request.io_Command == A314_WRITE) 303 | { 304 | append_a2r_packet(PKT_DATA, s->stream_id, (UBYTE)len, ior->a314_Buffer); 305 | 306 | ior->a314_Request.io_Error = A314_WRITE_OK; 307 | ReplyMsg((struct Message *)ior); 308 | 309 | s->pending_write = NULL; 310 | } 311 | else // A314_EOS 312 | { 313 | append_a2r_packet(PKT_EOS, s->stream_id, 0, NULL); 314 | 315 | ior->a314_Request.io_Error = A314_EOS_OK; 316 | ReplyMsg((struct Message *)ior); 317 | 318 | s->pending_write = NULL; 319 | 320 | s->flags |= SOCKET_SENT_EOS_TO_RPI; 321 | 322 | if (s->flags & SOCKET_SENT_EOS_TO_APP) 323 | close_socket(s, FALSE); 324 | } 325 | } 326 | else if (s->flags & SOCKET_SHOULD_SEND_RESET) 327 | { 328 | append_a2r_packet(PKT_RESET, s->stream_id, 0, NULL); 329 | delete_socket(s); 330 | } 331 | else 332 | { 333 | debug_printf("SERIOUS ERROR: Was in send queue but has nothing to send\n"); 334 | } 335 | } 336 | } 337 | 338 | static void handle_app_connect(struct A314_IORequest *ior, struct Socket *s) 339 | { 340 | debug_printf("Received a CONNECT request from application\n"); 341 | 342 | if (s != NULL) 343 | { 344 | ior->a314_Request.io_Error = A314_CONNECT_SOCKET_IN_USE; 345 | ReplyMsg((struct Message *)ior); 346 | } 347 | else if (ior->a314_Length + 3 > 255) 348 | { 349 | ior->a314_Request.io_Error = A314_CONNECT_RESET; 350 | ReplyMsg((struct Message *)ior); 351 | } 352 | else 353 | { 354 | s = create_socket(ior->a314_Request.io_Message.mn_ReplyPort->mp_SigTask, ior->a314_Socket); 355 | 356 | s->pending_connect = ior; 357 | s->flags = 0; 358 | 359 | int len = ior->a314_Length; 360 | if (send_queue_head == NULL && room_in_a2r(len)) 361 | { 362 | append_a2r_packet(PKT_CONNECT, s->stream_id, (UBYTE)len, ior->a314_Buffer); 363 | } 364 | else 365 | { 366 | add_to_send_queue(s, len); 367 | } 368 | } 369 | } 370 | 371 | static void handle_app_read(struct A314_IORequest *ior, struct Socket *s) 372 | { 373 | debug_printf("Received a READ request from application\n"); 374 | 375 | if (s == NULL || (s->flags & SOCKET_CLOSED)) 376 | { 377 | ior->a314_Length = 0; 378 | ior->a314_Request.io_Error = A314_READ_RESET; 379 | ReplyMsg((struct Message *)ior); 380 | } 381 | else 382 | { 383 | if (s->pending_connect != NULL || s->pending_read != NULL) 384 | { 385 | ior->a314_Length = 0; 386 | ior->a314_Request.io_Error = A314_READ_RESET; 387 | ReplyMsg((struct Message *)ior); 388 | 389 | close_socket(s, TRUE); 390 | } 391 | else if (s->rq_head != NULL) 392 | { 393 | struct QueuedData *qd = s->rq_head; 394 | int len = qd->length; 395 | 396 | if (ior->a314_Length < len) 397 | { 398 | ior->a314_Length = 0; 399 | ior->a314_Request.io_Error = A314_READ_RESET; 400 | ReplyMsg((struct Message *)ior); 401 | 402 | close_socket(s, TRUE); 403 | } 404 | else 405 | { 406 | s->rq_head = qd->next; 407 | if (s->rq_head == NULL) 408 | s->rq_tail = NULL; 409 | 410 | memcpy(ior->a314_Buffer, qd->data, len); 411 | FreeMem(qd, sizeof(struct QueuedData) + len); 412 | 413 | ior->a314_Length = len; 414 | ior->a314_Request.io_Error = A314_READ_OK; 415 | ReplyMsg((struct Message *)ior); 416 | } 417 | } 418 | else if (s->flags & SOCKET_RCVD_EOS_FROM_RPI) 419 | { 420 | ior->a314_Length = 0; 421 | ior->a314_Request.io_Error = A314_READ_EOS; 422 | ReplyMsg((struct Message *)ior); 423 | 424 | s->flags |= SOCKET_SENT_EOS_TO_APP; 425 | 426 | if (s->flags & SOCKET_SENT_EOS_TO_RPI) 427 | close_socket(s, FALSE); 428 | } 429 | else 430 | s->pending_read = ior; 431 | } 432 | } 433 | 434 | static void handle_app_write(struct A314_IORequest *ior, struct Socket *s) 435 | { 436 | debug_printf("Received a WRITE request from application\n"); 437 | 438 | if (s == NULL || (s->flags & SOCKET_CLOSED)) 439 | { 440 | ior->a314_Length = 0; 441 | ior->a314_Request.io_Error = A314_WRITE_RESET; 442 | ReplyMsg((struct Message *)ior); 443 | } 444 | else 445 | { 446 | int len = ior->a314_Length; 447 | if (s->pending_connect != NULL || s->pending_write != NULL || (s->flags & SOCKET_RCVD_EOS_FROM_APP) || len + 3 > 255) 448 | { 449 | ior->a314_Length = 0; 450 | ior->a314_Request.io_Error = A314_WRITE_RESET; 451 | ReplyMsg((struct Message *)ior); 452 | 453 | close_socket(s, TRUE); 454 | } 455 | else 456 | { 457 | if (send_queue_head == NULL && room_in_a2r(len)) 458 | { 459 | append_a2r_packet(PKT_DATA, s->stream_id, (UBYTE)len, ior->a314_Buffer); 460 | 461 | ior->a314_Request.io_Error = A314_WRITE_OK; 462 | ReplyMsg((struct Message *)ior); 463 | } 464 | else 465 | { 466 | s->pending_write = ior; 467 | add_to_send_queue(s, len); 468 | } 469 | } 470 | } 471 | } 472 | 473 | static void handle_app_eos(struct A314_IORequest *ior, struct Socket *s) 474 | { 475 | debug_printf("Received an EOS request from application\n"); 476 | 477 | if (s == NULL || (s->flags & SOCKET_CLOSED)) 478 | { 479 | ior->a314_Request.io_Error = A314_EOS_RESET; 480 | ReplyMsg((struct Message *)ior); 481 | } 482 | else 483 | { 484 | if (s->pending_connect != NULL || s->pending_write != NULL || (s->flags & SOCKET_RCVD_EOS_FROM_APP)) 485 | { 486 | ior->a314_Length = 0; 487 | ior->a314_Request.io_Error = A314_EOS_RESET; 488 | ReplyMsg((struct Message *)ior); 489 | 490 | close_socket(s, TRUE); 491 | } 492 | else 493 | { 494 | s->flags |= SOCKET_RCVD_EOS_FROM_APP; 495 | 496 | if (send_queue_head == NULL && room_in_a2r(0)) 497 | { 498 | append_a2r_packet(PKT_EOS, s->stream_id, 0, NULL); 499 | 500 | ior->a314_Request.io_Error = A314_EOS_OK; 501 | ReplyMsg((struct Message *)ior); 502 | 503 | s->flags |= SOCKET_SENT_EOS_TO_RPI; 504 | 505 | if (s->flags & SOCKET_SENT_EOS_TO_APP) 506 | close_socket(s, FALSE); 507 | } 508 | else 509 | { 510 | s->pending_write = ior; 511 | add_to_send_queue(s, 0); 512 | } 513 | } 514 | } 515 | } 516 | 517 | static void handle_app_reset(struct A314_IORequest *ior, struct Socket *s) 518 | { 519 | debug_printf("Received a RESET request from application\n"); 520 | 521 | if (s == NULL || (s->flags & SOCKET_CLOSED)) 522 | { 523 | ior->a314_Request.io_Error = A314_RESET_OK; 524 | ReplyMsg((struct Message *)ior); 525 | } 526 | else 527 | { 528 | ior->a314_Request.io_Error = A314_RESET_OK; 529 | ReplyMsg((struct Message *)ior); 530 | 531 | close_socket(s, TRUE); 532 | } 533 | } 534 | 535 | static void handle_app_request(struct A314_IORequest *ior) 536 | { 537 | struct Socket *s = find_socket(ior->a314_Request.io_Message.mn_ReplyPort->mp_SigTask, ior->a314_Socket); 538 | 539 | switch (ior->a314_Request.io_Command) 540 | { 541 | case A314_CONNECT: 542 | handle_app_connect(ior, s); 543 | break; 544 | case A314_READ: 545 | handle_app_read(ior, s); 546 | break; 547 | case A314_WRITE: 548 | handle_app_write(ior, s); 549 | break; 550 | case A314_EOS: 551 | handle_app_eos(ior, s); 552 | break; 553 | case A314_RESET: 554 | handle_app_reset(ior, s); 555 | break; 556 | default: 557 | ior->a314_Request.io_Error = IOERR_NOCMD; 558 | ReplyMsg((struct Message *)ior); 559 | break; 560 | } 561 | } 562 | 563 | void task_main() 564 | { 565 | while (TRUE) 566 | { 567 | debug_printf("Waiting for signal\n"); 568 | 569 | ULONG signal = Wait(SIGF_MSGPORT | SIGF_INT); 570 | 571 | UBYTE prev_a2r_tail = ca->a2r_tail; 572 | UBYTE prev_r2a_head = ca->r2a_head; 573 | 574 | if (signal & SIGF_MSGPORT) 575 | { 576 | ca->a_enable = 0; 577 | 578 | struct Message *msg; 579 | while (msg = GetMsg(&task_mp)) 580 | handle_app_request((struct A314_IORequest *)msg); 581 | } 582 | 583 | UBYTE a_enable = 0; 584 | while (a_enable == 0) 585 | { 586 | handle_packets_received_r2a(); 587 | handle_room_in_a2r(); 588 | 589 | UBYTE r_events = 0; 590 | if (ca->a2r_tail != prev_a2r_tail) 591 | r_events |= R_EVENT_A2R_TAIL; 592 | if (ca->r2a_head != prev_r2a_head) 593 | r_events |= R_EVENT_R2A_HEAD; 594 | 595 | UBYTE discard_value = ca->a_events; 596 | 597 | if (ca->r2a_head == ca->r2a_tail) 598 | { 599 | if (send_queue_head == NULL) 600 | a_enable = A_EVENT_R2A_TAIL; 601 | else if (!room_in_a2r(send_queue_head->send_queue_required_length)) 602 | a_enable = A_EVENT_R2A_TAIL | A_EVENT_A2R_HEAD; 603 | 604 | if (a_enable != 0) 605 | { 606 | ca->a_enable = a_enable; 607 | if (r_events != 0) 608 | ca->r_events = r_events; 609 | } 610 | } 611 | } 612 | } 613 | 614 | // There is currently no way to unload a314.device. 615 | 616 | //debug_printf("Shutting down\n"); 617 | 618 | //RemIntServer(INTB_PORTS, &ports_interrupt); 619 | //RemIntServer(INTB_VERTB, &vertb_interrupt); 620 | //FreeMem(ca, sizeof(struct ComArea)); 621 | 622 | // Stack and task structure should be reclaimed. 623 | } 624 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/a314/a314device/build.bat: -------------------------------------------------------------------------------- 1 | vc romtag.asm a314driver.c device.c startup.c fix_mem_region.c sockets.c int_server.asm -O3 -nostdlib -o a314.device 2 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/a314/a314device/debug.h: -------------------------------------------------------------------------------- 1 | #define DEBUG 0 2 | //#define debug_printf(...) do { if (DEBUG) fprintf(stdout, __VA_ARGS__); } while (0) 3 | #define debug_printf(...) 4 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/a314/a314device/device.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "device.h" 10 | #include "a314.h" 11 | #include "startup.h" 12 | #include "fix_mem_region.h" 13 | 14 | char device_name[] = A314_NAME; 15 | char id_string[] = A314_NAME " 1.1 (28 Nov 2020)"; 16 | 17 | struct ExecBase *SysBase; 18 | BPTR saved_seg_list; 19 | BOOL running = FALSE; 20 | 21 | static struct Library *init_device(__reg("a6") struct ExecBase *sys_base, __reg("a0") BPTR seg_list, __reg("d0") struct Library *dev) 22 | { 23 | SysBase = *(struct ExecBase **)4; 24 | saved_seg_list = seg_list; 25 | 26 | // We are being called from InitResident() in initializers.asm. 27 | // MakeLibrary() was executed before we got here. 28 | 29 | dev->lib_Node.ln_Type = NT_DEVICE; 30 | dev->lib_Node.ln_Name = device_name; 31 | dev->lib_Flags = LIBF_SUMUSED | LIBF_CHANGED; 32 | dev->lib_Version = 1; 33 | dev->lib_Revision = 0; 34 | dev->lib_IdString = (APTR)id_string; 35 | 36 | // AddDevice() is executed after we return. 37 | return dev; 38 | } 39 | 40 | static BPTR expunge(__reg("a6") struct Library *dev) 41 | { 42 | // There is currently no support for unloading a314.device. 43 | 44 | if (TRUE) //dev->lib_OpenCnt != 0) 45 | { 46 | dev->lib_Flags |= LIBF_DELEXP; 47 | return 0; 48 | } 49 | 50 | /* 51 | BPTR seg_list = saved_seg_list; 52 | Remove(&dev->lib_Node); 53 | FreeMem((char *)dev - dev->lib_NegSize, dev->lib_NegSize + dev->lib_PosSize); 54 | return seg_list; 55 | */ 56 | } 57 | 58 | static void open(__reg("a6") struct Library *dev, __reg("a1") struct A314_IORequest *ior, __reg("d0") ULONG unitnum, __reg("d1") ULONG flags) 59 | { 60 | dev->lib_OpenCnt++; 61 | 62 | if (dev->lib_OpenCnt == 1 && !running) 63 | { 64 | if (!task_start()) 65 | { 66 | ior->a314_Request.io_Error = IOERR_OPENFAIL; 67 | ior->a314_Request.io_Message.mn_Node.ln_Type = NT_REPLYMSG; 68 | dev->lib_OpenCnt--; 69 | return; 70 | } 71 | running = TRUE; 72 | } 73 | 74 | ior->a314_Request.io_Error = 0; 75 | ior->a314_Request.io_Message.mn_Node.ln_Type = NT_REPLYMSG; 76 | } 77 | 78 | static BPTR close(__reg("a6") struct Library *dev, __reg("a1") struct A314_IORequest *ior) 79 | { 80 | ior->a314_Request.io_Device = NULL; 81 | ior->a314_Request.io_Unit = NULL; 82 | 83 | dev->lib_OpenCnt--; 84 | 85 | if (dev->lib_OpenCnt == 0 && (dev->lib_Flags & LIBF_DELEXP)) 86 | return expunge(dev); 87 | 88 | return 0; 89 | } 90 | 91 | static void begin_io(__reg("a6") struct Library *dev, __reg("a1") struct A314_IORequest *ior) 92 | { 93 | PutMsg(&task_mp, (struct Message *)ior); 94 | ior->a314_Request.io_Flags &= ~IOF_QUICK; 95 | } 96 | 97 | static ULONG abort_io(__reg("a6") struct Library *dev, __reg("a1") struct A314_IORequest *ior) 98 | { 99 | // There is currently no support for aborting an IORequest. 100 | return IOERR_NOCMD; 101 | } 102 | 103 | static ULONG device_vectors[] = 104 | { 105 | (ULONG)open, 106 | (ULONG)close, 107 | (ULONG)expunge, 108 | 0, 109 | (ULONG)begin_io, 110 | (ULONG)abort_io, 111 | (ULONG)translate_address_a314, 112 | -1, 113 | }; 114 | 115 | ULONG auto_init_tables[] = 116 | { 117 | sizeof(struct Library), 118 | (ULONG)device_vectors, 119 | 0, 120 | (ULONG)init_device, 121 | }; 122 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/a314/a314device/device.h: -------------------------------------------------------------------------------- 1 | extern char device_name[]; 2 | extern char id_string[]; 3 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/a314/a314device/fix_mem_region.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "a314.h" 8 | #include "fix_mem_region.h" 9 | #include "protocol.h" 10 | 11 | struct MemChunkList 12 | { 13 | struct MemChunk *first; 14 | struct MemChunk *last; 15 | ULONG free; 16 | }; 17 | 18 | void add_chunk(struct MemChunkList *l, struct MemChunk *mc) 19 | { 20 | if (l->first == NULL) 21 | l->first = mc; 22 | else 23 | l->last->mc_Next = mc; 24 | l->last = mc; 25 | l->free += mc->mc_Bytes; 26 | } 27 | 28 | struct MemHeader *split_region(struct MemHeader *lower, ULONG split_at) 29 | { 30 | struct MemHeader *upper = (struct MemHeader *)AllocMem(sizeof(struct MemHeader), MEMF_PUBLIC | MEMF_CLEAR); 31 | 32 | struct MemChunkList ll = {NULL, NULL, 0}; 33 | struct MemChunkList ul = {NULL, NULL, 0}; 34 | 35 | struct MemChunk *mc = lower->mh_First; 36 | 37 | while (mc != NULL) 38 | { 39 | struct MemChunk *next_chunk = mc->mc_Next; 40 | mc->mc_Next = NULL; 41 | 42 | ULONG start = (ULONG)mc; 43 | ULONG end = start + mc->mc_Bytes; 44 | 45 | if (end <= split_at) 46 | add_chunk(&ll, mc); 47 | else if (split_at <= start) 48 | add_chunk(&ul, mc); 49 | else 50 | { 51 | mc->mc_Bytes = split_at - start; 52 | add_chunk(&ll, mc); 53 | 54 | struct MemChunk *new_chunk = (struct MemChunk *)split_at; 55 | new_chunk->mc_Next = NULL; 56 | new_chunk->mc_Bytes = end - split_at; 57 | add_chunk(&ul, new_chunk); 58 | } 59 | mc = next_chunk; 60 | } 61 | 62 | upper->mh_Node.ln_Type = NT_MEMORY; 63 | upper->mh_Node.ln_Pri = lower->mh_Node.ln_Pri; 64 | upper->mh_Node.ln_Name = lower->mh_Node.ln_Name; // Use a custom name? 65 | upper->mh_Attributes = lower->mh_Attributes; 66 | 67 | lower->mh_First = ll.first; 68 | upper->mh_First = ul.first; 69 | 70 | upper->mh_Lower = (APTR)split_at; 71 | upper->mh_Upper = lower->mh_Upper; 72 | lower->mh_Upper = (APTR)split_at; 73 | 74 | lower->mh_Free = ll.free; 75 | upper->mh_Free = ul.free; 76 | 77 | return upper; 78 | } 79 | 80 | BOOL overlap(struct MemHeader *mh, ULONG lower, ULONG upper) 81 | { 82 | return lower < (ULONG)(mh->mh_Upper) && (ULONG)(mh->mh_Lower) < upper; 83 | } 84 | 85 | void mark_region_a314(ULONG address, ULONG size) 86 | { 87 | struct List *memlist = &(SysBase->MemList); 88 | 89 | for (struct Node *node = memlist->lh_Head; node->ln_Succ != NULL; node = node->ln_Succ) 90 | { 91 | struct MemHeader *mh = (struct MemHeader *)node; 92 | if (overlap(mh, address, address + size)) 93 | { 94 | if ((ULONG)mh->mh_Lower < address) 95 | { 96 | mh->mh_Attributes &= ~MEMF_A314; 97 | mh = split_region(mh, address); 98 | } 99 | else 100 | Remove((struct Node *)mh); 101 | 102 | if (address + size < (ULONG)mh->mh_Upper) 103 | { 104 | struct MemHeader *new_mh = split_region(mh, address + size); 105 | new_mh->mh_Attributes &= ~MEMF_A314; 106 | Enqueue(memlist, (struct Node *)new_mh); 107 | } 108 | 109 | mh->mh_Attributes |= MEMF_A314; 110 | Enqueue(memlist, (struct Node *)mh); 111 | return; 112 | } 113 | } 114 | } 115 | 116 | BOOL fix_memory() 117 | { 118 | Forbid(); 119 | mark_region_a314(ca->mem_base, ca->mem_size); 120 | Permit(); 121 | return TRUE; 122 | } 123 | 124 | ULONG translate_address_a314(__reg("a0") void *address) 125 | { 126 | ULONG offset = (ULONG)address - ca->mem_base; 127 | if (offset < ca->mem_size) 128 | return offset; 129 | return -1; 130 | } 131 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/a314/a314device/fix_mem_region.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern ULONG translate_address_a314(__reg("a0") void *address); 4 | extern BOOL fix_memory(); 5 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/a314/a314device/int_server.asm: -------------------------------------------------------------------------------- 1 | XDEF _IntServer 2 | CODE 3 | 4 | SIGB_INT equ 14 5 | SIGF_INT equ (1 << SIGB_INT) 6 | 7 | ; a1 points to interrupt_data 8 | _IntServer: move.l 4(a1),a5 ; interrupt_data.ca 9 | 10 | move.b 0(a5),d0 ; A_EVENTS 11 | and.b 1(a5),d0 ; A_ENABLE 12 | beq.s should_not_signal 13 | 14 | move.b #0,1(a5) 15 | 16 | move.l $4.w,a6 17 | move.l #SIGF_INT,d0 18 | move.l 0(a1),a1 ; interrupt_data.task 19 | jsr -324(a6) ; Signal() 20 | 21 | should_not_signal: 22 | moveq #0,d0 23 | rts 24 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/a314/a314device/proto_a314.h: -------------------------------------------------------------------------------- 1 | #ifndef PROTO_A314_H 2 | #define PROTO_A314_H 3 | 4 | extern struct Library *A314Base; 5 | 6 | ULONG __TranslateAddressA314(__reg("a6") void *, __reg("a0") void *)="\tjsr\t-42(a6)"; 7 | #define TranslateAddressA314(address) __TranslateAddressA314(A314Base, address) 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/a314/a314device/protocol.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Packet types that are sent across the physical channel. 4 | #define PKT_DRIVER_STARTED 1 5 | #define PKT_DRIVER_SHUTTING_DOWN 2 6 | #define PKT_SETTINGS 3 7 | #define PKT_CONNECT 4 8 | #define PKT_CONNECT_RESPONSE 5 9 | #define PKT_DATA 6 10 | #define PKT_EOS 7 11 | #define PKT_RESET 8 12 | 13 | // Events that are communicated via IRQ from Amiga to Raspberry. 14 | #define R_EVENT_A2R_TAIL 1 15 | #define R_EVENT_R2A_HEAD 2 16 | #define R_EVENT_STARTED 4 17 | 18 | // Events that are communicated from Raspberry to Amiga. 19 | #define A_EVENT_R2A_TAIL 1 20 | #define A_EVENT_A2R_HEAD 2 21 | 22 | // The communication area, used to create the physical channel. 23 | struct ComArea 24 | { 25 | volatile UBYTE a_events; 26 | volatile UBYTE a_enable; 27 | volatile UBYTE r_events; 28 | volatile UBYTE r_enable; 29 | 30 | ULONG mem_base; 31 | ULONG mem_size; 32 | 33 | volatile UBYTE a2r_tail; 34 | volatile UBYTE r2a_head; 35 | volatile UBYTE r2a_tail; 36 | volatile UBYTE a2r_head; 37 | 38 | UBYTE a2r_buffer[256]; 39 | UBYTE r2a_buffer[256]; 40 | }; 41 | 42 | extern struct ComArea *ca; 43 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/a314/a314device/romtag.asm: -------------------------------------------------------------------------------- 1 | RTC_MATCHWORD: equ $4afc 2 | RTF_AUTOINIT: equ (1<<7) 3 | NT_DEVICE: equ 3 4 | VERSION: equ 1 5 | PRIORITY: equ 0 6 | 7 | section code,code 8 | 9 | moveq #-1,d0 10 | rts 11 | 12 | romtag: 13 | dc.w RTC_MATCHWORD 14 | dc.l romtag 15 | dc.l endcode 16 | dc.b RTF_AUTOINIT 17 | dc.b VERSION 18 | dc.b NT_DEVICE 19 | dc.b PRIORITY 20 | dc.l _device_name 21 | dc.l _id_string 22 | dc.l _auto_init_tables 23 | endcode: 24 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/a314/a314device/sockets.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "sockets.h" 4 | 5 | struct List active_sockets; 6 | 7 | struct Socket *send_queue_head = NULL; 8 | struct Socket *send_queue_tail = NULL; 9 | 10 | static UBYTE next_stream_id = 1; 11 | 12 | extern void NewList(struct List *l); 13 | 14 | void init_sockets() 15 | { 16 | NewList(&active_sockets); 17 | } 18 | 19 | struct Socket *find_socket(void *sig_task, ULONG socket) 20 | { 21 | for (struct Node *node = active_sockets.lh_Head; node->ln_Succ != NULL; node = node->ln_Succ) 22 | { 23 | struct Socket *s = (struct Socket *)node; 24 | if (s->sig_task == sig_task && s->socket == socket) 25 | return s; 26 | } 27 | return NULL; 28 | } 29 | 30 | struct Socket *find_socket_by_stream_id(UBYTE stream_id) 31 | { 32 | for (struct Node *node = active_sockets.lh_Head; node->ln_Succ != NULL; node = node->ln_Succ) 33 | { 34 | struct Socket *s = (struct Socket *)node; 35 | if (s->stream_id == stream_id) 36 | return s; 37 | } 38 | return NULL; 39 | } 40 | 41 | static UBYTE allocate_stream_id() 42 | { 43 | // Bug: If all stream ids are allocated then this loop won't terminate. 44 | 45 | while (1) 46 | { 47 | UBYTE stream_id = next_stream_id; 48 | next_stream_id += 2; 49 | if (find_socket_by_stream_id(stream_id) == NULL) 50 | return stream_id; 51 | } 52 | } 53 | 54 | static void free_stream_id(UBYTE stream_id) 55 | { 56 | // Currently do nothing. 57 | // Could speed up allocate_stream_id using a bitmap? 58 | } 59 | 60 | struct Socket *create_socket(struct Task *task, ULONG id) 61 | { 62 | struct Socket *s = (struct Socket *)AllocMem(sizeof(struct Socket), MEMF_CLEAR); 63 | s->sig_task = task; 64 | s->socket = id; 65 | s->stream_id = allocate_stream_id(); 66 | AddTail(&active_sockets, (struct Node *)s); 67 | return s; 68 | } 69 | 70 | void delete_socket(struct Socket *s) 71 | { 72 | Remove((struct Node *)s); 73 | free_stream_id(s->stream_id); 74 | FreeMem(s, sizeof(struct Socket)); 75 | } 76 | 77 | void add_to_send_queue(struct Socket *s, UWORD required_length) 78 | { 79 | s->send_queue_required_length = required_length; 80 | s->next_in_send_queue = NULL; 81 | 82 | if (send_queue_head == NULL) 83 | send_queue_head = s; 84 | else 85 | send_queue_tail->next_in_send_queue = s; 86 | send_queue_tail = s; 87 | 88 | s->flags |= SOCKET_IN_SEND_QUEUE; 89 | } 90 | 91 | void remove_from_send_queue(struct Socket *s) 92 | { 93 | if (s->flags & SOCKET_IN_SEND_QUEUE) 94 | { 95 | if (send_queue_head == s) 96 | { 97 | send_queue_head = s->next_in_send_queue; 98 | if (send_queue_head == NULL) 99 | send_queue_tail = NULL; 100 | } 101 | else 102 | { 103 | struct Socket *curr = send_queue_head; 104 | while (curr->next_in_send_queue != s) 105 | curr = curr->next_in_send_queue; 106 | 107 | curr->next_in_send_queue = s->next_in_send_queue; 108 | if (send_queue_tail == s) 109 | send_queue_tail = curr; 110 | } 111 | 112 | s->next_in_send_queue = NULL; 113 | s->flags &= ~SOCKET_IN_SEND_QUEUE; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/a314/a314device/sockets.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Used to store received data until application asks for it using a A314_READ. 5 | struct QueuedData 6 | { 7 | struct QueuedData *next; 8 | UWORD length; 9 | UBYTE data[]; 10 | }; 11 | 12 | // Socket flags, these are bit masks, can have many of them. 13 | #define SOCKET_RCVD_EOS_FROM_APP 0x0004 14 | #define SOCKET_RCVD_EOS_FROM_RPI 0x0008 15 | #define SOCKET_SENT_EOS_TO_APP 0x0010 16 | #define SOCKET_SENT_EOS_TO_RPI 0x0020 17 | #define SOCKET_CLOSED 0x0040 18 | #define SOCKET_SHOULD_SEND_RESET 0x0080 19 | #define SOCKET_IN_SEND_QUEUE 0x0100 20 | 21 | struct Socket 22 | { 23 | struct MinNode node; 24 | 25 | void *sig_task; 26 | ULONG socket; 27 | 28 | UBYTE stream_id; 29 | UBYTE pad1; 30 | 31 | UWORD flags; 32 | 33 | struct A314_IORequest *pending_connect; 34 | struct A314_IORequest *pending_read; 35 | struct A314_IORequest *pending_write; 36 | 37 | struct Socket *next_in_send_queue; 38 | UWORD send_queue_required_length; 39 | 40 | // Data that is received on the stream, but the application didn't read yet. 41 | struct QueuedData *rq_head; 42 | struct QueuedData *rq_tail; 43 | }; 44 | 45 | extern struct Socket *send_queue_head; 46 | extern struct Socket *send_queue_tail; 47 | 48 | extern void init_sockets(); 49 | 50 | extern struct Socket *create_socket(struct Task *task, ULONG id); 51 | extern void delete_socket(struct Socket *s); 52 | 53 | extern struct Socket *find_socket(void *sig_task, ULONG socket); 54 | extern struct Socket *find_socket_by_stream_id(UBYTE stream_id); 55 | 56 | extern void add_to_send_queue(struct Socket *s, UWORD required_length); 57 | extern void remove_from_send_queue(struct Socket *s); 58 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/a314/a314device/startup.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | #include "a314.h" 12 | #include "device.h" 13 | #include "protocol.h" 14 | #include "startup.h" 15 | #include "fix_mem_region.h" 16 | #include "debug.h" 17 | 18 | #define A314_MANUFACTURER 0x07db 19 | #define A314_PRODUCT 0xa3 20 | 21 | #define TASK_PRIORITY 80 22 | #define TASK_STACK_SIZE 1024 23 | 24 | struct ExpansionBase *ExpansionBase; 25 | struct MsgPort task_mp; 26 | struct Task *task; 27 | struct ComArea *ca; 28 | 29 | struct InterruptData 30 | { 31 | struct Task *task; 32 | struct ComArea *ca; 33 | }; 34 | 35 | struct InterruptData interrupt_data; 36 | struct Interrupt ports_interrupt; 37 | 38 | extern void task_main(); 39 | extern void init_sockets(); 40 | extern void IntServer(); 41 | 42 | void NewList(struct List *l) 43 | { 44 | l->lh_Head = (struct Node *)&(l->lh_Tail); 45 | l->lh_Tail = NULL; 46 | l->lh_TailPred = (struct Node *)&(l->lh_Head); 47 | } 48 | 49 | static struct Task *create_task(char *name, long priority, char *initialPC, unsigned long stacksize) 50 | { 51 | char *stack = AllocMem(stacksize, MEMF_CLEAR); 52 | if (stack == NULL) 53 | return NULL; 54 | 55 | struct Task *tc = AllocMem(sizeof(struct Task), MEMF_CLEAR | MEMF_PUBLIC); 56 | if (tc == NULL) 57 | { 58 | FreeMem(stack, stacksize); 59 | return NULL; 60 | } 61 | 62 | tc->tc_Node.ln_Type = NT_TASK; 63 | tc->tc_Node.ln_Pri = priority; 64 | tc->tc_Node.ln_Name = name; 65 | tc->tc_SPLower = (APTR)stack; 66 | tc->tc_SPUpper = (APTR)(stack + stacksize); 67 | tc->tc_SPReg = (APTR)(stack + stacksize); 68 | 69 | AddTask(tc, initialPC, 0); 70 | return tc; 71 | } 72 | 73 | static void init_message_port() 74 | { 75 | task_mp.mp_Node.ln_Name = device_name; 76 | task_mp.mp_Node.ln_Pri = 0; 77 | task_mp.mp_Node.ln_Type = NT_MSGPORT; 78 | task_mp.mp_Flags = PA_SIGNAL; 79 | task_mp.mp_SigBit = SIGB_MSGPORT; 80 | task_mp.mp_SigTask = task; 81 | NewList(&(task_mp.mp_MsgList)); 82 | } 83 | 84 | static void add_interrupt_handler() 85 | { 86 | interrupt_data.task = task; 87 | interrupt_data.ca = ca; 88 | 89 | ports_interrupt.is_Node.ln_Type = NT_INTERRUPT; 90 | ports_interrupt.is_Node.ln_Pri = 0; 91 | ports_interrupt.is_Node.ln_Name = device_name; 92 | ports_interrupt.is_Data = (APTR)&interrupt_data; 93 | ports_interrupt.is_Code = IntServer; 94 | 95 | AddIntServer(INTB_PORTS, &ports_interrupt); 96 | } 97 | 98 | BOOL task_start() 99 | { 100 | ExpansionBase = (struct ExpansionBase *)OpenLibrary(EXPANSIONNAME, 0); 101 | if (!ExpansionBase) 102 | return FALSE; 103 | 104 | struct ConfigDev *cd = FindConfigDev(NULL, A314_MANUFACTURER, A314_PRODUCT); 105 | if (!cd) 106 | { 107 | CloseLibrary((struct Library *)ExpansionBase); 108 | return FALSE; 109 | } 110 | 111 | ca = (struct ComArea *)cd->cd_BoardAddr; 112 | 113 | if (!fix_memory()) 114 | return FALSE; 115 | 116 | task = create_task(device_name, TASK_PRIORITY, (void *)task_main, TASK_STACK_SIZE); 117 | if (task == NULL) 118 | { 119 | debug_printf("Unable to create task\n"); 120 | return FALSE; 121 | } 122 | 123 | init_message_port(); 124 | init_sockets(); 125 | 126 | ca->a_enable = 0; 127 | unsigned char discard_value = ca->a_events; 128 | 129 | ca->r_events = R_EVENT_STARTED; 130 | 131 | add_interrupt_handler(); 132 | 133 | ca->a_enable = A_EVENT_R2A_TAIL; 134 | 135 | return TRUE; 136 | } 137 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/a314/a314device/startup.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define SIGB_INT 14 6 | #define SIGB_MSGPORT 15 7 | 8 | #define SIGF_INT (1 << SIGB_INT) 9 | #define SIGF_MSGPORT (1 << SIGB_MSGPORT) 10 | 11 | extern struct Task *task; 12 | extern struct MsgPort task_mp; 13 | 14 | extern BOOL task_start(); 15 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/code.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/captain-amygdala/VPU-example/577057b56d3f64027cb021fb86807f3d25beeee6/GCC/VC4_PSPROTO/pistorm/software/code.bin -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/gayle.c: -------------------------------------------------------------------------------- 1 | // 2 | // Gayle.c 3 | // Omega 4 | // 5 | // Created by Matt Parsons on 06/03/2019. 6 | // Copyright © 2019 Matt Parsons. All rights reserved. 7 | // 8 | // Changes made 2020 by Niklas Ekström to better fit PiStorm. 9 | 10 | // Write Byte to Gayle Space 0xda9000 (0x0000c3) 11 | // Read Byte From Gayle Space 0xda9000 12 | // Read Byte From Gayle Space 0xdaa000 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "ide/ide.h" 20 | #include "ps_mappings.h" 21 | 22 | #define CLOCKBASE 0xDC0000 23 | 24 | //#define GSTATUS 0xda201c 25 | //#define GCLOW 0xda2010 26 | //#define GDH 0xda2018 27 | 28 | // Gayle Addresses 29 | 30 | // Gayle IDE Reads 31 | #define GERROR 0xda2004 // Error 32 | #define GSTATUS 0xda201c // Status 33 | // Gayle IDE Writes 34 | #define GFEAT 0xda2004 // Write : Feature 35 | #define GCMD 0xda201c // Write : Command 36 | // Gayle IDE RW 37 | #define GDATA 0xda2000 // Data 38 | #define GSECTCNT 0xda2008 // SectorCount 39 | #define GSECTNUM 0xda200c // SectorNumber 40 | #define GCYLLOW 0xda2010 // CylinderLow 41 | #define GCYLHIGH 0xda2014 // CylinderHigh 42 | #define GDEVHEAD 0xda2018 // Device/Head 43 | #define GCTRL 0xda3018 // Control 44 | // Gayle Ident 45 | #define GIDENT 0xDE1000 46 | 47 | // Gayle IRQ/CC 48 | #define GCS 0xDA8000 // Card Control 49 | #define GIRQ 0xDA9000 // IRQ 50 | #define GINT 0xDAA000 // Int enable 51 | #define GCONF 0xDAB000 // Gayle Config 52 | 53 | /* DA8000 */ 54 | #define GAYLE_CS_IDE 0x80 /* IDE int status */ 55 | #define GAYLE_CS_CCDET 0x40 /* credit card detect */ 56 | #define GAYLE_CS_BVD1 0x20 /* battery voltage detect 1 */ 57 | #define GAYLE_CS_SC 0x20 /* credit card status change */ 58 | #define GAYLE_CS_BVD2 0x10 /* battery voltage detect 2 */ 59 | #define GAYLE_CS_DA 0x10 /* digital audio */ 60 | #define GAYLE_CS_WR 0x08 /* write enable (1 == enabled) */ 61 | #define GAYLE_CS_BSY 0x04 /* credit card busy */ 62 | #define GAYLE_CS_IRQ 0x04 /* interrupt request */ 63 | #define GAYLE_CS_DAEN 0x02 /* enable digital audio */ 64 | #define GAYLE_CS_DIS 0x01 /* disable PCMCIA slot */ 65 | 66 | /* DA9000 */ 67 | #define GAYLE_IRQ_IDE 0x80 68 | #define GAYLE_IRQ_CCDET 0x40 /* credit card detect */ 69 | #define GAYLE_IRQ_BVD1 0x20 /* battery voltage detect 1 */ 70 | #define GAYLE_IRQ_SC 0x20 /* credit card status change */ 71 | #define GAYLE_IRQ_BVD2 0x10 /* battery voltage detect 2 */ 72 | #define GAYLE_IRQ_DA 0x10 /* digital audio */ 73 | #define GAYLE_IRQ_WR 0x08 /* write enable (1 == enabled) */ 74 | #define GAYLE_IRQ_BSY 0x04 /* credit card busy */ 75 | #define GAYLE_IRQ_IRQ 0x04 /* interrupt request */ 76 | #define GAYLE_IRQ_RESET 0x02 /* reset machine after CCDET change */ 77 | #define GAYLE_IRQ_BERR 0x01 /* generate bus error after CCDET change */ 78 | 79 | /* DAA000 */ 80 | #define GAYLE_INT_IDE 0x80 /* IDE interrupt enable */ 81 | #define GAYLE_INT_CCDET 0x40 /* credit card detect change enable */ 82 | #define GAYLE_INT_BVD1 0x20 /* battery voltage detect 1 change enable */ 83 | #define GAYLE_INT_SC 0x20 /* credit card status change enable */ 84 | #define GAYLE_INT_BVD2 0x10 /* battery voltage detect 2 change enable */ 85 | #define GAYLE_INT_DA 0x10 /* digital audio change enable */ 86 | #define GAYLE_INT_WR 0x08 /* write enable change enabled */ 87 | #define GAYLE_INT_BSY 0x04 /* credit card busy */ 88 | #define GAYLE_INT_IRQ 0x04 /* credit card interrupt request */ 89 | #define GAYLE_INT_BVD_LEV 0x02 /* BVD int level, 0=lev2,1=lev6 */ 90 | #define GAYLE_INT_BSY_LEV 0x01 /* BSY int level, 0=lev2,1=lev6 */ 91 | 92 | static int counter; 93 | static uint8_t gayle_irq; 94 | static uint8_t gayle_int; 95 | static uint8_t gayle_cs; 96 | static uint8_t gayle_cs_mask; 97 | static uint8_t gayle_cfg; 98 | static struct ide_controller *ide0; 99 | static int fd; 100 | 101 | static void gayle_write_8(unsigned int address, unsigned int value) { 102 | switch (address) { 103 | case GFEAT: 104 | ide_write8(ide0, ide_feature_w, value); 105 | break; 106 | 107 | case GCMD: 108 | ide_write8(ide0, ide_command_w, value); 109 | break; 110 | 111 | case GSECTCNT: 112 | ide_write8(ide0, ide_sec_count, value); 113 | break; 114 | 115 | case GSECTNUM: 116 | ide_write8(ide0, ide_sec_num, value); 117 | break; 118 | 119 | case GCYLLOW: 120 | ide_write8(ide0, ide_cyl_low, value); 121 | break; 122 | 123 | case GCYLHIGH: 124 | ide_write8(ide0, ide_cyl_hi, value); 125 | break; 126 | 127 | case GDEVHEAD: 128 | ide_write8(ide0, ide_dev_head, value); 129 | break; 130 | 131 | case GCTRL: 132 | ide_write8(ide0, ide_devctrl_w, value); 133 | break; 134 | 135 | case GIDENT: 136 | counter = 0; 137 | // printf("Write Byte to Gayle Ident 0x%06x (0x%06x)\n",address,value); 138 | break; 139 | 140 | case GIRQ: 141 | // printf("Write Byte to Gayle GIRQ 0x%06x (0x%06x)\n",address,value); 142 | gayle_irq = (gayle_irq & value) | (value & (GAYLE_IRQ_RESET | GAYLE_IRQ_BERR)); 143 | break; 144 | 145 | case GCS: 146 | printf("Write Byte to Gayle GCS 0x%06x (0x%06x)\n", address, value); 147 | gayle_cs_mask = value & ~3; 148 | gayle_cs &= ~3; 149 | gayle_cs |= value & 3; 150 | break; 151 | 152 | case GINT: 153 | printf("Write Byte to Gayle GINT 0x%06x (0x%06x)\n", address, value); 154 | gayle_int = value; 155 | break; 156 | 157 | case GCONF: 158 | printf("Write Byte to Gayle GCONF 0x%06x (0x%06x)\n", address, value); 159 | gayle_cfg = value; 160 | break; 161 | 162 | default: 163 | printf("Write Byte to Gayle Space 0x%06x (0x%06x)\n", address, value); 164 | break; 165 | } 166 | } 167 | 168 | static void gayle_write_16(unsigned int address, unsigned int value) { 169 | switch (address) { 170 | case GDATA: 171 | ide_write16(ide0, ide_data, value); 172 | break; 173 | 174 | default: 175 | printf("Write Word to Gayle Space 0x%06x (0x%06x)\n", address, value); 176 | break; 177 | } 178 | } 179 | 180 | static void gayle_write_32(unsigned int address, unsigned int value) { 181 | switch (address) { 182 | default: 183 | printf("Write Long to Gayle Space 0x%06x (0x%06x)\n", address, value); 184 | break; 185 | } 186 | } 187 | 188 | static unsigned int gayle_read_8(unsigned int address) { 189 | switch (address) { 190 | case GERROR: 191 | return ide_read8(ide0, ide_error_r); 192 | 193 | case GSTATUS: 194 | return ide_read8(ide0, ide_status_r); 195 | 196 | case GSECTCNT: 197 | return ide_read8(ide0, ide_sec_count); 198 | 199 | case GSECTNUM: 200 | return ide_read8(ide0, ide_sec_num); 201 | 202 | case GCYLLOW: 203 | return ide_read8(ide0, ide_cyl_low); 204 | 205 | case GCYLHIGH: 206 | return ide_read8(ide0, ide_cyl_hi); 207 | 208 | case GDEVHEAD: 209 | return ide_read8(ide0, ide_dev_head); 210 | 211 | case GCTRL: 212 | return ide_read8(ide0, ide_altst_r); 213 | 214 | case GIDENT: { 215 | uint8_t val; 216 | // printf("Read Byte from Gayle Ident 0x%06x (0x%06x)\n",address,counter); 217 | if (counter == 0 || counter == 1 || counter == 3) { 218 | val = 0x80; // 80; to enable gayle 219 | } else { 220 | val = 0x00; 221 | } 222 | counter++; 223 | return val; 224 | } 225 | 226 | case GIRQ: 227 | // printf("Read Byte From GIRQ Space 0x%06x\n",gayle_irq); 228 | if (ide0->drive->intrq) { 229 | // printf("IDE IRQ: %x\n",irq); 230 | return 0x80; // gayle_irq; 231 | } 232 | return 0; 233 | 234 | case GCS: { 235 | printf("Read Byte From GCS Space 0x%06x\n", 0x1234); 236 | uint8_t v; 237 | v = gayle_cs_mask | gayle_cs; 238 | return v; 239 | } 240 | 241 | case GINT: 242 | // printf("Read Byte From GINT Space 0x%06x\n",gayle_int); 243 | return gayle_int; 244 | 245 | case GCONF: 246 | printf("Read Byte From GCONF Space 0x%06x\n", gayle_cfg & 0x0f); 247 | return gayle_cfg & 0x0f; 248 | 249 | default: 250 | printf("Read Byte From Gayle Space 0x%06x\n", address); 251 | return 0xFF; 252 | } 253 | } 254 | 255 | static unsigned int gayle_read_16(unsigned int address) { 256 | switch (address) { 257 | case GDATA: { 258 | uint16_t value; 259 | value = ide_read16(ide0, ide_data); 260 | // value = (value << 8) | (value >> 8); 261 | return value; 262 | } 263 | 264 | default: 265 | printf("Read Word From Gayle Space 0x%06x\n", address); 266 | return 0x8000; 267 | } 268 | } 269 | 270 | static unsigned int gayle_read_32(unsigned int address) { 271 | switch (address) { 272 | default: 273 | printf("Read Long From Gayle Space 0x%06x\n", address); 274 | return 0x8000; 275 | } 276 | } 277 | 278 | unsigned int check_gayle_irq() { 279 | if (gayle_int & (1 << 7)) 280 | return ide0->drive->intrq; 281 | 282 | return 0; 283 | } 284 | 285 | int init_gayle(const char image_name[]) { 286 | ide0 = ide_allocate("cf"); 287 | 288 | fd = open(image_name, O_RDWR); 289 | if (fd < 0) { 290 | printf("HDD Image %s failed open\n", image_name); 291 | return -1; 292 | } 293 | 294 | ide_attach(ide0, 0, fd); 295 | ide_reset_begin(ide0); 296 | printf("HDD Image %s attached\n", image_name); 297 | 298 | struct ps_device gayle_device = { 299 | gayle_read_8, gayle_read_16, gayle_read_32, 300 | gayle_write_8, gayle_write_16, gayle_write_32}; 301 | 302 | uint32_t devno = ps_add_device(&gayle_device); 303 | ps_add_range(devno, 0xda0000, 0x10000); 304 | ps_add_range(devno, 0xde0000, 0x10000); 305 | return 0; 306 | } 307 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/gayle.h: -------------------------------------------------------------------------------- 1 | // 2 | // Gayle.h 3 | // Omega 4 | // 5 | // Created by Matt Parsons on 06/03/2019. 6 | // Copyright © 2019 Matt Parsons. All rights reserved. 7 | // 8 | 9 | #ifndef Gayle_h 10 | #define Gayle_h 11 | 12 | int init_gayle(const char image_name[]); 13 | unsigned int check_gayle_irq(); 14 | 15 | #endif /* Gayle_h */ 16 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/ide/ide.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define ACME_ROADRUNNER 1 /* 504MB classic IDE drive */ 4 | #define ACME_COYOTE 2 /* 20MB early IDE drive */ 5 | #define ACME_NEMESIS 3 /* 20MB LBA capable drive */ 6 | #define ACME_ULTRASONICUS 4 /* 40MB LBA capable drive */ 7 | #define ACME_ACCELLERATTI 5 /* 128MB LBA capable drive */ 8 | #define ACME_ZIPPIBUS 6 /* 256MB LBA capable drive */ 9 | 10 | #define MAX_DRIVE_TYPE 6 11 | 12 | #define ide_data 0 13 | #define ide_error_r 1 14 | #define ide_feature_w 1 15 | #define ide_sec_count 2 16 | #define ide_sec_num 3 17 | #define ide_lba_low 3 18 | #define ide_cyl_low 4 19 | #define ide_lba_mid 4 20 | #define ide_cyl_hi 5 21 | #define ide_lba_hi 5 22 | #define ide_dev_head 6 23 | #define ide_lba_top 6 24 | #define ide_status_r 7 25 | #define ide_command_w 7 26 | #define ide_altst_r 8 27 | #define ide_devctrl_w 8 28 | #define ide_data_latch 9 29 | 30 | struct ide_taskfile { 31 | uint16_t data; 32 | uint8_t error; 33 | uint8_t feature; 34 | uint8_t count; 35 | uint8_t lba1; 36 | uint8_t lba2; 37 | uint8_t lba3; 38 | uint8_t lba4; 39 | uint8_t status; 40 | uint8_t command; 41 | uint8_t devctrl; 42 | struct ide_drive *drive; 43 | }; 44 | 45 | struct ide_drive { 46 | struct ide_controller *controller; 47 | struct ide_taskfile taskfile; 48 | unsigned int present:1, intrq:1, failed:1, lba:1, eightbit:1; 49 | uint16_t cylinders; 50 | uint8_t heads, sectors; 51 | uint8_t data[512]; 52 | uint16_t identify[256]; 53 | uint8_t *dptr; 54 | int state; 55 | int fd; 56 | off_t offset; 57 | int length; 58 | }; 59 | 60 | struct ide_controller { 61 | struct ide_drive drive[2]; 62 | int selected; 63 | const char *name; 64 | uint16_t data_latch; 65 | }; 66 | 67 | extern const uint8_t ide_magic[8]; 68 | 69 | void ide_reset_begin(struct ide_controller *c); 70 | uint8_t ide_read8(struct ide_controller *c, uint8_t r); 71 | void ide_write8(struct ide_controller *c, uint8_t r, uint8_t v); 72 | uint16_t ide_read16(struct ide_controller *c, uint8_t r); 73 | void ide_write16(struct ide_controller *c, uint8_t r, uint16_t v); 74 | uint8_t ide_read_latched(struct ide_controller *c, uint8_t r); 75 | void ide_write_latched(struct ide_controller *c, uint8_t r, uint8_t v); 76 | 77 | struct ide_controller *ide_allocate(const char *name); 78 | int ide_attach(struct ide_controller *c, int drive, int fd); 79 | void ide_detach(struct ide_drive *d); 80 | void ide_free(struct ide_controller *c); 81 | 82 | int ide_make_drive(uint8_t type, int fd); 83 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/ide/ide.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/captain-amygdala/VPU-example/577057b56d3f64027cb021fb86807f3d25beeee6/GCC/VC4_PSPROTO/pistorm/software/ide/ide.o -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/ide/makedisk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/captain-amygdala/VPU-example/577057b56d3f64027cb021fb86807f3d25beeee6/GCC/VC4_PSPROTO/pistorm/software/ide/makedisk -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/ide/makedisk.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "ide.h" 6 | 7 | int main(int argc, const char *argv[]) 8 | { 9 | int t, fd; 10 | if (argc != 3) { 11 | fprintf(stderr, "%s [type] [path]\n", argv[0]); 12 | exit(1); 13 | } 14 | t = atoi(argv[1]); 15 | if (t < 1 || t > MAX_DRIVE_TYPE) { 16 | fprintf(stderr, "%s: unknown drive type.\n", argv[0]); 17 | exit(1); 18 | } 19 | fd = open(argv[2], O_WRONLY|O_TRUNC|O_CREAT|O_EXCL, 0666); 20 | if (fd == -1) { 21 | perror(argv[2]); 22 | exit(1); 23 | } 24 | if (ide_make_drive(t, fd) < 0) { 25 | perror(argv[2]); 26 | exit(1); 27 | } 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/m68k.h: -------------------------------------------------------------------------------- 1 | /* ======================================================================== */ 2 | /* ========================= LICENSING & COPYRIGHT ======================== */ 3 | /* ======================================================================== */ 4 | /* 5 | * MUSASHI 6 | * Version 3.32 7 | * 8 | * A portable Motorola M680x0 processor emulation engine. 9 | * Copyright Karl Stenerud. All rights reserved. 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in 19 | * all copies or substantial portions of the Software. 20 | 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | * THE SOFTWARE. 28 | */ 29 | 30 | #ifndef M68K__HEADER 31 | #define M68K__HEADER 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | #ifndef ARRAY_LENGTH 38 | #define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0])) 39 | #endif 40 | 41 | #ifndef FALSE 42 | #define FALSE 0 43 | #define TRUE 1 44 | #endif 45 | 46 | /* ======================================================================== */ 47 | /* ============================= CONFIGURATION ============================ */ 48 | /* ======================================================================== */ 49 | 50 | /* Import the configuration for this build */ 51 | #ifdef MUSASHI_CNF 52 | #include MUSASHI_CNF 53 | #else 54 | #include "m68kconf.h" 55 | #endif 56 | 57 | /* ======================================================================== */ 58 | /* ============================ GENERAL DEFINES =========================== */ 59 | 60 | /* ======================================================================== */ 61 | 62 | /* There are 7 levels of interrupt to the 68K. 63 | * A transition from < 7 to 7 will cause a non-maskable interrupt (NMI). 64 | */ 65 | #define M68K_IRQ_NONE 0 66 | #define M68K_IRQ_1 1 67 | #define M68K_IRQ_2 2 68 | #define M68K_IRQ_3 3 69 | #define M68K_IRQ_4 4 70 | #define M68K_IRQ_5 5 71 | #define M68K_IRQ_6 6 72 | #define M68K_IRQ_7 7 73 | 74 | 75 | /* Special interrupt acknowledge values. 76 | * Use these as special returns from the interrupt acknowledge callback 77 | * (specified later in this header). 78 | */ 79 | 80 | /* Causes an interrupt autovector (0x18 + interrupt level) to be taken. 81 | * This happens in a real 68K if VPA or AVEC is asserted during an interrupt 82 | * acknowledge cycle instead of DTACK. 83 | */ 84 | #define M68K_INT_ACK_AUTOVECTOR 0xffffffff 85 | 86 | /* Causes the spurious interrupt vector (0x18) to be taken 87 | * This happens in a real 68K if BERR is asserted during the interrupt 88 | * acknowledge cycle (i.e. no devices responded to the acknowledge). 89 | */ 90 | #define M68K_INT_ACK_SPURIOUS 0xfffffffe 91 | 92 | 93 | /* CPU types for use in m68k_set_cpu_type() */ 94 | enum 95 | { 96 | M68K_CPU_TYPE_INVALID, 97 | M68K_CPU_TYPE_68000, 98 | M68K_CPU_TYPE_68010, 99 | M68K_CPU_TYPE_68EC020, 100 | M68K_CPU_TYPE_68020, 101 | M68K_CPU_TYPE_68EC030, 102 | M68K_CPU_TYPE_68030, 103 | M68K_CPU_TYPE_68EC040, 104 | M68K_CPU_TYPE_68LC040, 105 | M68K_CPU_TYPE_68040, 106 | M68K_CPU_TYPE_SCC68070 107 | }; 108 | 109 | /* Registers used by m68k_get_reg() and m68k_set_reg() */ 110 | typedef enum 111 | { 112 | /* Real registers */ 113 | M68K_REG_D0, /* Data registers */ 114 | M68K_REG_D1, 115 | M68K_REG_D2, 116 | M68K_REG_D3, 117 | M68K_REG_D4, 118 | M68K_REG_D5, 119 | M68K_REG_D6, 120 | M68K_REG_D7, 121 | M68K_REG_A0, /* Address registers */ 122 | M68K_REG_A1, 123 | M68K_REG_A2, 124 | M68K_REG_A3, 125 | M68K_REG_A4, 126 | M68K_REG_A5, 127 | M68K_REG_A6, 128 | M68K_REG_A7, 129 | M68K_REG_PC, /* Program Counter */ 130 | M68K_REG_SR, /* Status Register */ 131 | M68K_REG_SP, /* The current Stack Pointer (located in A7) */ 132 | M68K_REG_USP, /* User Stack Pointer */ 133 | M68K_REG_ISP, /* Interrupt Stack Pointer */ 134 | M68K_REG_MSP, /* Master Stack Pointer */ 135 | M68K_REG_SFC, /* Source Function Code */ 136 | M68K_REG_DFC, /* Destination Function Code */ 137 | M68K_REG_VBR, /* Vector Base Register */ 138 | M68K_REG_CACR, /* Cache Control Register */ 139 | M68K_REG_CAAR, /* Cache Address Register */ 140 | 141 | /* Assumed registers */ 142 | /* These are cheat registers which emulate the 1-longword prefetch 143 | * present in the 68000 and 68010. 144 | */ 145 | M68K_REG_PREF_ADDR, /* Last prefetch address */ 146 | M68K_REG_PREF_DATA, /* Last prefetch data */ 147 | 148 | /* Convenience registers */ 149 | M68K_REG_PPC, /* Previous value in the program counter */ 150 | M68K_REG_IR, /* Instruction register */ 151 | M68K_REG_CPU_TYPE /* Type of CPU being run */ 152 | } m68k_register_t; 153 | 154 | /* ======================================================================== */ 155 | /* ====================== FUNCTIONS CALLED BY THE CPU ===================== */ 156 | /* ======================================================================== */ 157 | 158 | /* You will have to implement these functions */ 159 | 160 | /* read/write functions called by the CPU to access memory. 161 | * while values used are 32 bits, only the appropriate number 162 | * of bits are relevant (i.e. in write_memory_8, only the lower 8 bits 163 | * of value should be written to memory). 164 | * 165 | * NOTE: I have separated the immediate and PC-relative memory fetches 166 | * from the other memory fetches because some systems require 167 | * differentiation between PROGRAM and DATA fetches (usually 168 | * for security setups such as encryption). 169 | * This separation can either be achieved by setting 170 | * M68K_SEPARATE_READS in m68kconf.h and defining 171 | * the read functions, or by setting M68K_EMULATE_FC and 172 | * making a function code callback function. 173 | * Using the callback offers better emulation coverage 174 | * because you can also monitor whether the CPU is in SYSTEM or 175 | * USER mode, but it is also slower. 176 | */ 177 | 178 | /* Read from anywhere */ 179 | unsigned int m68k_read_memory_8(unsigned int address); 180 | unsigned int m68k_read_memory_16(unsigned int address); 181 | unsigned int m68k_read_memory_32(unsigned int address); 182 | 183 | /* Read data immediately following the PC */ 184 | unsigned int m68k_read_immediate_16(unsigned int address); 185 | unsigned int m68k_read_immediate_32(unsigned int address); 186 | 187 | /* Read data relative to the PC */ 188 | unsigned int m68k_read_pcrelative_8(unsigned int address); 189 | unsigned int m68k_read_pcrelative_16(unsigned int address); 190 | unsigned int m68k_read_pcrelative_32(unsigned int address); 191 | 192 | /* Memory access for the disassembler */ 193 | unsigned int m68k_read_disassembler_8 (unsigned int address); 194 | unsigned int m68k_read_disassembler_16 (unsigned int address); 195 | unsigned int m68k_read_disassembler_32 (unsigned int address); 196 | 197 | /* Write to anywhere */ 198 | void m68k_write_memory_8(unsigned int address, unsigned int value); 199 | void m68k_write_memory_16(unsigned int address, unsigned int value); 200 | void m68k_write_memory_32(unsigned int address, unsigned int value); 201 | 202 | /* Special call to simulate undocumented 68k behavior when move.l with a 203 | * predecrement destination mode is executed. 204 | * To simulate real 68k behavior, first write the high word to 205 | * [address+2], and then write the low word to [address]. 206 | * 207 | * Enable this functionality with M68K_SIMULATE_PD_WRITES in m68kconf.h. 208 | */ 209 | void m68k_write_memory_32_pd(unsigned int address, unsigned int value); 210 | 211 | 212 | 213 | /* ======================================================================== */ 214 | /* ============================== CALLBACKS =============================== */ 215 | /* ======================================================================== */ 216 | 217 | /* These functions allow you to set callbacks to the host when specific events 218 | * occur. Note that you must enable the corresponding value in m68kconf.h 219 | * in order for these to do anything useful. 220 | * Note: I have defined default callbacks which are used if you have enabled 221 | * the corresponding #define in m68kconf.h but either haven't assigned a 222 | * callback or have assigned a callback of NULL. 223 | */ 224 | 225 | /* Set the callback for an interrupt acknowledge. 226 | * You must enable M68K_EMULATE_INT_ACK in m68kconf.h. 227 | * The CPU will call the callback with the interrupt level being acknowledged. 228 | * The host program must return either a vector from 0x02-0xff, or one of the 229 | * special interrupt acknowledge values specified earlier in this header. 230 | * If this is not implemented, the CPU will always assume an autovectored 231 | * interrupt, and will automatically clear the interrupt request when it 232 | * services the interrupt. 233 | * Default behavior: return M68K_INT_ACK_AUTOVECTOR. 234 | */ 235 | void m68k_set_int_ack_callback(int (*callback)(int int_level)); 236 | 237 | 238 | /* Set the callback for a breakpoint acknowledge (68010+). 239 | * You must enable M68K_EMULATE_BKPT_ACK in m68kconf.h. 240 | * The CPU will call the callback with whatever was in the data field of the 241 | * BKPT instruction for 68020+, or 0 for 68010. 242 | * Default behavior: do nothing. 243 | */ 244 | void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data)); 245 | 246 | 247 | /* Set the callback for the RESET instruction. 248 | * You must enable M68K_EMULATE_RESET in m68kconf.h. 249 | * The CPU calls this callback every time it encounters a RESET instruction. 250 | * Default behavior: do nothing. 251 | */ 252 | void m68k_set_reset_instr_callback(void (*callback)(void)); 253 | 254 | 255 | /* Set the callback for informing of a large PC change. 256 | * You must enable M68K_MONITOR_PC in m68kconf.h. 257 | * The CPU calls this callback with the new PC value every time the PC changes 258 | * by a large value (currently set for changes by longwords). 259 | * Default behavior: do nothing. 260 | */ 261 | void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc)); 262 | 263 | /* Set the callback for the TAS instruction. 264 | * You must enable M68K_TAS_HAS_CALLBACK in m68kconf.h. 265 | * The CPU calls this callback every time it encounters a TAS instruction. 266 | * Default behavior: return 1, allow writeback. 267 | */ 268 | void m68k_set_tas_instr_callback(int (*callback)(void)); 269 | 270 | /* Set the callback for illegal instructions. 271 | * You must enable M68K_ILLG_HAS_CALLBACK in m68kconf.h. 272 | * The CPU calls this callback every time it encounters an illegal instruction 273 | * which must return 1 if it handles the instruction normally or 0 if it's really an illegal instruction. 274 | * Default behavior: return 0, exception will occur. 275 | */ 276 | void m68k_set_illg_instr_callback(int (*callback)(int)); 277 | 278 | /* Set the callback for CPU function code changes. 279 | * You must enable M68K_EMULATE_FC in m68kconf.h. 280 | * The CPU calls this callback with the function code before every memory 281 | * access to set the CPU's function code according to what kind of memory 282 | * access it is (supervisor/user, program/data and such). 283 | * Default behavior: do nothing. 284 | */ 285 | void m68k_set_fc_callback(void (*callback)(unsigned int new_fc)); 286 | 287 | 288 | /* Set a callback for the instruction cycle of the CPU. 289 | * You must enable M68K_INSTRUCTION_HOOK in m68kconf.h. 290 | * The CPU calls this callback just before fetching the opcode in the 291 | * instruction cycle. 292 | * Default behavior: do nothing. 293 | */ 294 | void m68k_set_instr_hook_callback(void (*callback)(unsigned int pc)); 295 | 296 | 297 | 298 | /* ======================================================================== */ 299 | /* ====================== FUNCTIONS TO ACCESS THE CPU ===================== */ 300 | /* ======================================================================== */ 301 | 302 | /* Use this function to set the CPU type you want to emulate. 303 | * Currently supported types are: M68K_CPU_TYPE_68000, M68K_CPU_TYPE_68010, 304 | * M68K_CPU_TYPE_EC020, and M68K_CPU_TYPE_68020. 305 | */ 306 | void m68k_set_cpu_type(unsigned int cpu_type); 307 | 308 | /* Do whatever initialisations the core requires. Should be called 309 | * at least once at init time. 310 | */ 311 | void m68k_init(void); 312 | 313 | /* Pulse the RESET pin on the CPU. 314 | * You *MUST* reset the CPU at least once to initialize the emulation 315 | * Note: If you didn't call m68k_set_cpu_type() before resetting 316 | * the CPU for the first time, the CPU will be set to 317 | * M68K_CPU_TYPE_68000. 318 | */ 319 | void m68k_pulse_reset(void); 320 | 321 | /* execute num_cycles worth of instructions. returns number of cycles used */ 322 | int m68k_execute(int num_cycles); 323 | 324 | /* These functions let you read/write/modify the number of cycles left to run 325 | * while m68k_execute() is running. 326 | * These are useful if the 68k accesses a memory-mapped port on another device 327 | * that requires immediate processing by another CPU. 328 | */ 329 | int m68k_cycles_run(void); /* Number of cycles run so far */ 330 | int m68k_cycles_remaining(void); /* Number of cycles left */ 331 | void m68k_modify_timeslice(int cycles); /* Modify cycles left */ 332 | void m68k_end_timeslice(void); /* End timeslice now */ 333 | 334 | /* Set the IPL0-IPL2 pins on the CPU (IRQ). 335 | * A transition from < 7 to 7 will cause a non-maskable interrupt (NMI). 336 | * Setting IRQ to 0 will clear an interrupt request. 337 | */ 338 | void m68k_set_irq(unsigned int int_level); 339 | 340 | /* Set the virtual irq lines, where the highest level 341 | * active line is automatically selected. If you use this function, 342 | * do not use m68k_set_irq. 343 | */ 344 | void m68k_set_virq(unsigned int level, unsigned int active); 345 | unsigned int m68k_get_virq(unsigned int level); 346 | 347 | /* Halt the CPU as if you pulsed the HALT pin. */ 348 | void m68k_pulse_halt(void); 349 | 350 | 351 | /* Trigger a bus error exception */ 352 | void m68k_pulse_bus_error(void); 353 | 354 | 355 | /* Context switching to allow multiple CPUs */ 356 | 357 | /* Get the size of the cpu context in bytes */ 358 | unsigned int m68k_context_size(void); 359 | 360 | /* Get a cpu context */ 361 | unsigned int m68k_get_context(void* dst); 362 | 363 | /* set the current cpu context */ 364 | void m68k_set_context(void* dst); 365 | 366 | /* Register the CPU state information */ 367 | void m68k_state_register(const char *type, int index); 368 | 369 | 370 | /* Peek at the internals of a CPU context. This can either be a context 371 | * retrieved using m68k_get_context() or the currently running context. 372 | * If context is NULL, the currently running CPU context will be used. 373 | */ 374 | unsigned int m68k_get_reg(void* context, m68k_register_t reg); 375 | 376 | /* Poke values into the internals of the currently running CPU context */ 377 | void m68k_set_reg(m68k_register_t reg, unsigned int value); 378 | 379 | /* Check if an instruction is valid for the specified CPU type */ 380 | unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cpu_type); 381 | 382 | /* Disassemble 1 instruction using the epecified CPU type at pc. Stores 383 | * disassembly in str_buff and returns the size of the instruction in bytes. 384 | */ 385 | unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_type); 386 | 387 | /* Same as above but accepts raw opcode data directly rather than fetching 388 | * via the read/write interfaces. 389 | */ 390 | unsigned int m68k_disassemble_raw(char* str_buff, unsigned int pc, const unsigned char* opdata, const unsigned char* argdata, unsigned int cpu_type); 391 | 392 | 393 | /* ======================================================================== */ 394 | /* ============================== MAME STUFF ============================== */ 395 | /* ======================================================================== */ 396 | 397 | #if M68K_COMPILE_FOR_MAME == OPT_ON 398 | #include "m68kmame.h" 399 | #endif /* M68K_COMPILE_FOR_MAME */ 400 | 401 | 402 | /* ======================================================================== */ 403 | /* ============================== END OF FILE ============================= */ 404 | /* ======================================================================== */ 405 | 406 | #ifdef __cplusplus 407 | } 408 | #endif 409 | 410 | 411 | #endif /* M68K__HEADER */ 412 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/m68kconf.h: -------------------------------------------------------------------------------- 1 | /* ======================================================================== */ 2 | /* ========================= LICENSING & COPYRIGHT ======================== */ 3 | /* ======================================================================== */ 4 | /* 5 | * MUSASHI 6 | * Version 3.32 7 | * 8 | * A portable Motorola M680x0 processor emulation engine. 9 | * Copyright Karl Stenerud. All rights reserved. 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * furnished to do so, subject to the following conditions: 17 | * 18 | * The above copyright notice and this permission notice shall be included in 19 | * all copies or substantial portions of the Software. 20 | 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | * THE SOFTWARE. 28 | */ 29 | 30 | 31 | 32 | #ifndef M68KCONF__HEADER 33 | #define M68KCONF__HEADER 34 | 35 | 36 | /* Configuration switches. 37 | * Use OPT_SPECIFY_HANDLER for configuration options that allow callbacks. 38 | * OPT_SPECIFY_HANDLER causes the core to link directly to the function 39 | * or macro you specify, rather than using callback functions whose pointer 40 | * must be passed in using m68k_set_xxx_callback(). 41 | */ 42 | #define OPT_OFF 0 43 | #define OPT_ON 1 44 | #define OPT_SPECIFY_HANDLER 2 45 | 46 | 47 | /* ======================================================================== */ 48 | /* ============================== MAME STUFF ============================== */ 49 | /* ======================================================================== */ 50 | 51 | /* If you're compiling this for MAME, only change M68K_COMPILE_FOR_MAME 52 | * to OPT_ON and use m68kmame.h to configure the 68k core. 53 | */ 54 | #ifndef M68K_COMPILE_FOR_MAME 55 | #define M68K_COMPILE_FOR_MAME OPT_OFF 56 | #endif /* M68K_COMPILE_FOR_MAME */ 57 | 58 | 59 | #if M68K_COMPILE_FOR_MAME == OPT_OFF 60 | 61 | 62 | /* ======================================================================== */ 63 | /* ============================= CONFIGURATION ============================ */ 64 | /* ======================================================================== */ 65 | 66 | /* Turn ON if you want to use the following M68K variants */ 67 | #define M68K_EMULATE_010 OPT_ON 68 | #define M68K_EMULATE_EC020 OPT_ON 69 | #define M68K_EMULATE_020 OPT_ON 70 | #define M68K_EMULATE_030 OPT_OFF 71 | #define M68K_EMULATE_040 OPT_OFF 72 | 73 | 74 | /* If ON, the CPU will call m68k_read_immediate_xx() for immediate addressing 75 | * and m68k_read_pcrelative_xx() for PC-relative addressing. 76 | * If off, all read requests from the CPU will be redirected to m68k_read_xx() 77 | */ 78 | #define M68K_SEPARATE_READS OPT_OFF 79 | 80 | /* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a 81 | * predecrement destination EA mode instead of m68k_write_32(). 82 | * To simulate real 68k behavior, m68k_write_32_pd() must first write the high 83 | * word to [address+2], and then write the low word to [address]. 84 | */ 85 | #define M68K_SIMULATE_PD_WRITES OPT_OFF 86 | 87 | /* If ON, CPU will call the interrupt acknowledge callback when it services an 88 | * interrupt. 89 | * If off, all interrupts will be autovectored and all interrupt requests will 90 | * auto-clear when the interrupt is serviced. 91 | */ 92 | #define M68K_EMULATE_INT_ACK OPT_OFF 93 | #define M68K_INT_ACK_CALLBACK(A) cpu_irq_ack(A) 94 | 95 | 96 | /* If ON, CPU will call the breakpoint acknowledge callback when it encounters 97 | * a breakpoint instruction and it is running a 68010+. 98 | */ 99 | #define M68K_EMULATE_BKPT_ACK OPT_OFF 100 | #define M68K_BKPT_ACK_CALLBACK() your_bkpt_ack_handler_function() 101 | 102 | 103 | /* If ON, the CPU will monitor the trace flags and take trace exceptions 104 | */ 105 | #define M68K_EMULATE_TRACE OPT_OFF 106 | 107 | 108 | /* If ON, CPU will call the output reset callback when it encounters a reset 109 | * instruction. 110 | */ 111 | #define M68K_EMULATE_RESET OPT_SPECIFY_HANDLER 112 | #define M68K_RESET_CALLBACK() cpu_pulse_reset() 113 | 114 | /* If ON, CPU will call the callback when it encounters a cmpi.l #v, dn 115 | * instruction. 116 | */ 117 | #define M68K_CMPILD_HAS_CALLBACK OPT_OFF 118 | #define M68K_CMPILD_CALLBACK(v,r) your_cmpild_handler_function(v,r) 119 | 120 | 121 | /* If ON, CPU will call the callback when it encounters a rte 122 | * instruction. 123 | */ 124 | #define M68K_RTE_HAS_CALLBACK OPT_OFF 125 | #define M68K_RTE_CALLBACK() your_rte_handler_function() 126 | 127 | /* If ON, CPU will call the callback when it encounters a tas 128 | * instruction. 129 | */ 130 | #define M68K_TAS_HAS_CALLBACK OPT_OFF 131 | #define M68K_TAS_CALLBACK() your_tas_handler_function() 132 | 133 | /* If ON, CPU will call the callback when it encounters an illegal instruction 134 | * passing the opcode as argument. If the callback returns 1, then it's considered 135 | * as a normal instruction, and the illegal exception in canceled. If it returns 0, 136 | * the exception occurs normally. 137 | * The callback looks like int callback(int opcode) 138 | * You should put OPT_SPECIFY_HANDLER here if you cant to use it, otherwise it will 139 | * use a dummy default handler and you'll have to call m68k_set_illg_instr_callback explicitely 140 | */ 141 | #define M68K_ILLG_HAS_CALLBACK OPT_OFF 142 | #define M68K_ILLG_CALLBACK(opcode) op_illg(opcode) 143 | 144 | /* If ON, CPU will call the set fc callback on every memory access to 145 | * differentiate between user/supervisor, program/data access like a real 146 | * 68000 would. This should be enabled and the callback should be set if you 147 | * want to properly emulate the m68010 or higher. (moves uses function codes 148 | * to read/write data from different address spaces) 149 | */ 150 | #define M68K_EMULATE_FC OPT_OFF 151 | #define M68K_SET_FC_CALLBACK(A) cpu_set_fc(A) 152 | 153 | /* If ON, CPU will call the pc changed callback when it changes the PC by a 154 | * large value. This allows host programs to be nicer when it comes to 155 | * fetching immediate data and instructions on a banked memory system. 156 | */ 157 | #define M68K_MONITOR_PC OPT_OFF 158 | #define M68K_SET_PC_CALLBACK(A) your_pc_changed_handler_function(A) 159 | 160 | 161 | /* If ON, CPU will call the instruction hook callback before every 162 | * instruction. 163 | */ 164 | #define M68K_INSTRUCTION_HOOK OPT_OFF 165 | #define M68K_INSTRUCTION_CALLBACK(pc) cpu_instr_callback(pc) 166 | 167 | 168 | /* If ON, the CPU will emulate the 4-byte prefetch queue of a real 68000 */ 169 | #define M68K_EMULATE_PREFETCH OPT_ON 170 | 171 | 172 | /* If ON, the CPU will generate address error exceptions if it tries to 173 | * access a word or longword at an odd address. 174 | * NOTE: This is only emulated properly for 68000 mode. 175 | */ 176 | #define M68K_EMULATE_ADDRESS_ERROR OPT_OFF 177 | 178 | 179 | /* Turn ON to enable logging of illegal instruction calls. 180 | * M68K_LOG_FILEHANDLE must be #defined to a stdio file stream. 181 | * Turn on M68K_LOG_1010_1111 to log all 1010 and 1111 calls. 182 | */ 183 | #define M68K_LOG_ENABLE OPT_OFF 184 | #define M68K_LOG_1010_1111 OPT_OFF 185 | #define M68K_LOG_FILEHANDLE some_file_handle 186 | 187 | 188 | #define M68K_EMULATE_PMMU OPT_ON 189 | 190 | 191 | /* If ON, store the D/A registers before start of new instruction. 192 | * This is used to retry the instruction in case of a bus error. 193 | */ 194 | #define M68K_DA_SAVE OPT_OFF 195 | 196 | /* ----------------------------- COMPATIBILITY ---------------------------- */ 197 | 198 | /* The following options set optimizations that violate the current ANSI 199 | * standard, but will be compliant under the forthcoming C9X standard. 200 | */ 201 | 202 | 203 | /* If ON, the enulation core will use 64-bit integers to speed up some 204 | * operations. 205 | */ 206 | #define M68K_USE_64_BIT OPT_ON 207 | 208 | void cpu_pulse_reset(); 209 | 210 | 211 | 212 | #endif /* M68K_COMPILE_FOR_MAME */ 213 | 214 | /* ======================================================================== */ 215 | /* ============================== END OF FILE ============================= */ 216 | /* =======================================x================================= */ 217 | 218 | #endif /* M68KCONF__HEADER */ 219 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/m68kmake: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/captain-amygdala/VPU-example/577057b56d3f64027cb021fb86807f3d25beeee6/GCC/VC4_PSPROTO/pistorm/software/m68kmake -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/m68kmmu.h: -------------------------------------------------------------------------------- 1 | /* 2 | m68kmmu.h - PMMU implementation for 68851/68030/68040 3 | 4 | By R. Belmont 5 | 6 | Copyright Nicola Salmoria and the MAME Team. 7 | Visit http://mamedev.org for licensing and usage restrictions. 8 | */ 9 | 10 | /* 11 | pmmu_translate_addr: perform 68851/68030-style PMMU address translation 12 | */ 13 | uint pmmu_translate_addr(uint addr_in) 14 | { 15 | uint32 addr_out, tbl_entry = 0, tbl_entry2, tamode = 0, tbmode = 0, tcmode = 0; 16 | uint root_aptr, root_limit, tofs, is, abits, bbits, cbits; 17 | uint resolved, tptr, shift; 18 | 19 | resolved = 0; 20 | addr_out = addr_in; 21 | 22 | // if SRP is enabled and we're in supervisor mode, use it 23 | if ((m68ki_cpu.mmu_tc & 0x02000000) && (m68ki_get_sr() & 0x2000)) 24 | { 25 | root_aptr = m68ki_cpu.mmu_srp_aptr; 26 | root_limit = m68ki_cpu.mmu_srp_limit; 27 | } 28 | else // else use the CRP 29 | { 30 | root_aptr = m68ki_cpu.mmu_crp_aptr; 31 | root_limit = m68ki_cpu.mmu_crp_limit; 32 | } 33 | 34 | // get initial shift (# of top bits to ignore) 35 | is = (m68ki_cpu.mmu_tc>>16) & 0xf; 36 | abits = (m68ki_cpu.mmu_tc>>12)&0xf; 37 | bbits = (m68ki_cpu.mmu_tc>>8)&0xf; 38 | cbits = (m68ki_cpu.mmu_tc>>4)&0xf; 39 | 40 | // fprintf(stderr,"PMMU: tcr %08x limit %08x aptr %08x is %x abits %d bbits %d cbits %d\n", m68ki_cpu.mmu_tc, root_limit, root_aptr, is, abits, bbits, cbits); 41 | 42 | // get table A offset 43 | tofs = (addr_in<>(32-abits); 44 | 45 | // find out what format table A is 46 | switch (root_limit & 3) 47 | { 48 | case 0: // invalid, should cause MMU exception 49 | case 1: // page descriptor, should cause direct mapping 50 | fatalerror("680x0 PMMU: Unhandled root mode\n"); 51 | break; 52 | 53 | case 2: // valid 4 byte descriptors 54 | tofs *= 4; 55 | // fprintf(stderr,"PMMU: reading table A entry at %08x\n", tofs + (root_aptr & 0xfffffffc)); 56 | tbl_entry = m68k_read_memory_32( tofs + (root_aptr & 0xfffffffc)); 57 | tamode = tbl_entry & 3; 58 | // fprintf(stderr,"PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tamode, tofs); 59 | break; 60 | 61 | case 3: // valid 8 byte descriptors 62 | tofs *= 8; 63 | // fprintf(stderr,"PMMU: reading table A entries at %08x\n", tofs + (root_aptr & 0xfffffffc)); 64 | tbl_entry2 = m68k_read_memory_32( tofs + (root_aptr & 0xfffffffc)); 65 | tbl_entry = m68k_read_memory_32( tofs + (root_aptr & 0xfffffffc)+4); 66 | tamode = tbl_entry2 & 3; 67 | // fprintf(stderr,"PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tamode, tofs); 68 | break; 69 | } 70 | 71 | // get table B offset and pointer 72 | tofs = (addr_in<<(is+abits))>>(32-bbits); 73 | tptr = tbl_entry & 0xfffffff0; 74 | 75 | // find out what format table B is, if any 76 | switch (tamode) 77 | { 78 | case 0: // invalid, should cause MMU exception 79 | fatalerror("680x0 PMMU: Unhandled Table A mode %d (addr_in %08x)\n", tamode, addr_in); 80 | break; 81 | 82 | case 2: // 4-byte table B descriptor 83 | tofs *= 4; 84 | // fprintf(stderr,"PMMU: reading table B entry at %08x\n", tofs + tptr); 85 | tbl_entry = m68k_read_memory_32( tofs + tptr); 86 | tbmode = tbl_entry & 3; 87 | // fprintf(stderr,"PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs); 88 | break; 89 | 90 | case 3: // 8-byte table B descriptor 91 | tofs *= 8; 92 | // fprintf(stderr,"PMMU: reading table B entries at %08x\n", tofs + tptr); 93 | tbl_entry2 = m68k_read_memory_32( tofs + tptr); 94 | tbl_entry = m68k_read_memory_32( tofs + tptr + 4); 95 | tbmode = tbl_entry2 & 3; 96 | // fprintf(stderr,"PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs); 97 | break; 98 | 99 | case 1: // early termination descriptor 100 | tbl_entry &= 0xffffff00; 101 | 102 | shift = is+abits; 103 | addr_out = ((addr_in<>shift) + tbl_entry; 104 | resolved = 1; 105 | break; 106 | } 107 | 108 | // if table A wasn't early-out, continue to process table B 109 | if (!resolved) 110 | { 111 | // get table C offset and pointer 112 | tofs = (addr_in<<(is+abits+bbits))>>(32-cbits); 113 | tptr = tbl_entry & 0xfffffff0; 114 | 115 | switch (tbmode) 116 | { 117 | case 0: // invalid, should cause MMU exception 118 | fatalerror("680x0 PMMU: Unhandled Table B mode %d (addr_in %08x PC %x)\n", tbmode, addr_in, REG_PC); 119 | break; 120 | 121 | case 2: // 4-byte table C descriptor 122 | tofs *= 4; 123 | // fprintf(stderr,"PMMU: reading table C entry at %08x\n", tofs + tptr); 124 | tbl_entry = m68k_read_memory_32(tofs + tptr); 125 | tcmode = tbl_entry & 3; 126 | // fprintf(stderr,"PMMU: addr %08x entry %08x mode %x tofs %x\n", addr_in, tbl_entry, tbmode, tofs); 127 | break; 128 | 129 | case 3: // 8-byte table C descriptor 130 | tofs *= 8; 131 | // fprintf(stderr,"PMMU: reading table C entries at %08x\n", tofs + tptr); 132 | tbl_entry2 = m68k_read_memory_32(tofs + tptr); 133 | tbl_entry = m68k_read_memory_32(tofs + tptr + 4); 134 | tcmode = tbl_entry2 & 3; 135 | // fprintf(stderr,"PMMU: addr %08x entry %08x entry2 %08x mode %x tofs %x\n", addr_in, tbl_entry, tbl_entry2, tbmode, tofs); 136 | break; 137 | 138 | case 1: // termination descriptor 139 | tbl_entry &= 0xffffff00; 140 | 141 | shift = is+abits+bbits; 142 | addr_out = ((addr_in<>shift) + tbl_entry; 143 | resolved = 1; 144 | break; 145 | } 146 | } 147 | 148 | if (!resolved) 149 | { 150 | switch (tcmode) 151 | { 152 | case 0: // invalid, should cause MMU exception 153 | case 2: // 4-byte ??? descriptor 154 | case 3: // 8-byte ??? descriptor 155 | fatalerror("680x0 PMMU: Unhandled Table B mode %d (addr_in %08x PC %x)\n", tbmode, addr_in, REG_PC); 156 | break; 157 | 158 | case 1: // termination descriptor 159 | tbl_entry &= 0xffffff00; 160 | 161 | shift = is+abits+bbits+cbits; 162 | addr_out = ((addr_in<>shift) + tbl_entry; 163 | resolved = 1; 164 | break; 165 | } 166 | } 167 | 168 | 169 | // fprintf(stderr,"PMMU: [%08x] => [%08x]\n", addr_in, addr_out); 170 | 171 | return addr_out; 172 | } 173 | 174 | /* 175 | 176 | m68881_mmu_ops: COP 0 MMU opcode handling 177 | 178 | */ 179 | 180 | void m68881_mmu_ops() 181 | { 182 | uint16 modes; 183 | uint32 ea = m68ki_cpu.ir & 0x3f; 184 | uint64 temp64; 185 | 186 | // catch the 2 "weird" encodings up front (PBcc) 187 | if ((m68ki_cpu.ir & 0xffc0) == 0xf0c0) 188 | { 189 | fprintf(stderr,"680x0: unhandled PBcc\n"); 190 | return; 191 | } 192 | else if ((m68ki_cpu.ir & 0xffc0) == 0xf080) 193 | { 194 | fprintf(stderr,"680x0: unhandled PBcc\n"); 195 | return; 196 | } 197 | else // the rest are 1111000xxxXXXXXX where xxx is the instruction family 198 | { 199 | switch ((m68ki_cpu.ir>>9) & 0x7) 200 | { 201 | case 0: 202 | modes = OPER_I_16(); 203 | 204 | if ((modes & 0xfde0) == 0x2000) // PLOAD 205 | { 206 | fprintf(stderr,"680x0: unhandled PLOAD\n"); 207 | return; 208 | } 209 | else if ((modes & 0xe200) == 0x2000) // PFLUSH 210 | { 211 | fprintf(stderr,"680x0: unhandled PFLUSH PC=%x\n", REG_PC); 212 | return; 213 | } 214 | else if (modes == 0xa000) // PFLUSHR 215 | { 216 | fprintf(stderr,"680x0: unhandled PFLUSHR\n"); 217 | return; 218 | } 219 | else if (modes == 0x2800) // PVALID (FORMAT 1) 220 | { 221 | fprintf(stderr,"680x0: unhandled PVALID1\n"); 222 | return; 223 | } 224 | else if ((modes & 0xfff8) == 0x2c00) // PVALID (FORMAT 2) 225 | { 226 | fprintf(stderr,"680x0: unhandled PVALID2\n"); 227 | return; 228 | } 229 | else if ((modes & 0xe000) == 0x8000) // PTEST 230 | { 231 | fprintf(stderr,"680x0: unhandled PTEST\n"); 232 | return; 233 | } 234 | else 235 | { 236 | switch ((modes>>13) & 0x7) 237 | { 238 | case 0: // MC68030/040 form with FD bit 239 | case 2: // MC68881 form, FD never set 240 | if (modes & 0x200) 241 | { 242 | switch ((modes>>10) & 7) 243 | { 244 | case 0: // translation control register 245 | WRITE_EA_32(ea, m68ki_cpu.mmu_tc); 246 | break; 247 | 248 | case 2: // supervisor root pointer 249 | WRITE_EA_64(ea, (uint64)m68ki_cpu.mmu_srp_limit<<32 | (uint64)m68ki_cpu.mmu_srp_aptr); 250 | break; 251 | 252 | case 3: // CPU root pointer 253 | WRITE_EA_64(ea, (uint64)m68ki_cpu.mmu_crp_limit<<32 | (uint64)m68ki_cpu.mmu_crp_aptr); 254 | break; 255 | 256 | default: 257 | fprintf(stderr,"680x0: PMOVE from unknown MMU register %x, PC %x\n", (modes>>10) & 7, REG_PC); 258 | break; 259 | } 260 | } 261 | else 262 | { 263 | switch ((modes>>10) & 7) 264 | { 265 | case 0: // translation control register 266 | m68ki_cpu.mmu_tc = READ_EA_32(ea); 267 | 268 | if (m68ki_cpu.mmu_tc & 0x80000000) 269 | { 270 | m68ki_cpu.pmmu_enabled = 1; 271 | } 272 | else 273 | { 274 | m68ki_cpu.pmmu_enabled = 0; 275 | } 276 | break; 277 | 278 | case 2: // supervisor root pointer 279 | temp64 = READ_EA_64(ea); 280 | m68ki_cpu.mmu_srp_limit = (temp64>>32) & 0xffffffff; 281 | m68ki_cpu.mmu_srp_aptr = temp64 & 0xffffffff; 282 | break; 283 | 284 | case 3: // CPU root pointer 285 | temp64 = READ_EA_64(ea); 286 | m68ki_cpu.mmu_crp_limit = (temp64>>32) & 0xffffffff; 287 | m68ki_cpu.mmu_crp_aptr = temp64 & 0xffffffff; 288 | break; 289 | 290 | default: 291 | fprintf(stderr,"680x0: PMOVE to unknown MMU register %x, PC %x\n", (modes>>10) & 7, REG_PC); 292 | break; 293 | } 294 | } 295 | break; 296 | 297 | case 3: // MC68030 to/from status reg 298 | if (modes & 0x200) 299 | { 300 | WRITE_EA_32(ea, m68ki_cpu.mmu_sr); 301 | } 302 | else 303 | { 304 | m68ki_cpu.mmu_sr = READ_EA_32(ea); 305 | } 306 | break; 307 | 308 | default: 309 | fprintf(stderr,"680x0: unknown PMOVE mode %x (modes %04x) (PC %x)\n", (modes>>13) & 0x7, modes, REG_PC); 310 | break; 311 | } 312 | } 313 | break; 314 | 315 | default: 316 | fprintf(stderr,"680x0: unknown PMMU instruction group %d\n", (m68ki_cpu.ir>>9) & 0x7); 317 | break; 318 | } 319 | } 320 | } 321 | 322 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/m68kops.h: -------------------------------------------------------------------------------- 1 | #ifndef M68KOPS__HEADER 2 | #define M68KOPS__HEADER 3 | 4 | /* ======================================================================== */ 5 | /* ============================ OPCODE HANDLERS =========================== */ 6 | /* ======================================================================== */ 7 | 8 | 9 | /* Build the opcode handler table */ 10 | void m68ki_build_opcode_table(void); 11 | 12 | extern void (*m68ki_instruction_jump_table[0x10000])(void); /* opcode handler jump table */ 13 | extern unsigned char m68ki_cycles[][0x10000]; 14 | 15 | 16 | /* ======================================================================== */ 17 | /* ============================== END OF FILE ============================= */ 18 | /* ======================================================================== */ 19 | 20 | #endif /* M68KOPS__HEADER */ 21 | 22 | 23 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/mailbox.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012, Broadcom Europe Ltd. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the copyright holder nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include "mailbox.h" 39 | 40 | #define PAGE_SIZE (4*1024) 41 | 42 | void *mapmem(unsigned base, unsigned size) 43 | { 44 | int mem_fd; 45 | unsigned offset = base % PAGE_SIZE; 46 | base = base - offset; 47 | size = size + offset; 48 | /* open /dev/mem */ 49 | if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { 50 | printf("can't open /dev/mem\nThis program should be run as root. Try prefixing command with: sudo\n"); 51 | exit (-1); 52 | } 53 | void *mem = mmap( 54 | 0, 55 | size, 56 | PROT_READ|PROT_WRITE, 57 | MAP_SHARED/*|MAP_FIXED*/, 58 | mem_fd, 59 | base); 60 | #ifdef DEBUG 61 | printf("base=0x%x, mem=%p\n", base, mem); 62 | #endif 63 | if (mem == MAP_FAILED) { 64 | printf("mmap error %d\n", (int)mem); 65 | exit (-1); 66 | } 67 | close(mem_fd); 68 | return (char *)mem + offset; 69 | } 70 | 71 | void unmapmem(void *addr, unsigned size) 72 | { 73 | unsigned offset = (unsigned)addr % PAGE_SIZE; 74 | addr = (char *)addr - offset; 75 | size = size + offset; 76 | int s = munmap(addr, size); 77 | if (s != 0) { 78 | printf("munmap error %d\n", s); 79 | exit (-1); 80 | } 81 | } 82 | 83 | /* 84 | * use ioctl to send mbox property message 85 | */ 86 | 87 | static int mbox_property(int file_desc, void *buf) 88 | { 89 | int ret_val = ioctl(file_desc, IOCTL_MBOX_PROPERTY, buf); 90 | 91 | if (ret_val < 0) { 92 | printf("ioctl_set_msg failed:%d\n", ret_val); 93 | } 94 | 95 | #ifdef DEBUG 96 | unsigned *p = buf; int i; unsigned size = *(unsigned *)buf; 97 | for (i=0; i 29 | 30 | #define MAJOR_NUM 100 31 | #define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) 32 | #define DEVICE_FILE_NAME "/dev/vcio" 33 | 34 | int mbox_open(); 35 | void mbox_close(int file_desc); 36 | 37 | unsigned get_version(int file_desc); 38 | unsigned mem_alloc(int file_desc, unsigned size, unsigned align, unsigned flags); 39 | unsigned mem_free(int file_desc, unsigned handle); 40 | unsigned mem_lock(int file_desc, unsigned handle); 41 | unsigned mem_unlock(int file_desc, unsigned handle); 42 | void *mapmem(unsigned base, unsigned size); 43 | void unmapmem(void *addr, unsigned size); 44 | 45 | unsigned execute_code(int file_desc, unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5); 46 | unsigned execute_vpu1(int file_desc, unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5); 47 | unsigned execute_qpu(int file_desc, unsigned num_qpus, unsigned control, unsigned noflush, unsigned timeout); 48 | unsigned qpu_enable(int file_desc, unsigned enable); 49 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/pistorm.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2020 Claude Schwarz 3 | * 4 | * Niklas Ekström 2020 - reorganized source code 5 | */ 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #include "a314/a314.h" 17 | #include "gayle.h" 18 | #include "m68k.h" 19 | #include "ps_autoconfig.h" 20 | #include "ps_customchips.h" 21 | #include "ps_fastmem.h" 22 | #include "ps_kickstart.h" 23 | #include "ps_mappings.h" 24 | #include "ps_protocol.h" 25 | #include "psconf.h" 26 | 27 | int use_gayle_emulation; 28 | 29 | static void parse_args(int argc, char *argv[]) { 30 | use_gayle_emulation = 1; 31 | 32 | for (int i = 1; i < argc; i++) { 33 | if (strcmp(argv[i], "--disable-gayle") == 0) { 34 | use_gayle_emulation = 0; 35 | } 36 | } 37 | } 38 | 39 | int main(int argc, char *argv[]) { 40 | printf("PiStorm 68k accelerator\n"); 41 | printf("Copyright 2020 Claude Schwarz\n"); 42 | 43 | parse_args(argc, argv); 44 | 45 | const struct sched_param priority = {99}; 46 | sched_setscheduler(0, SCHED_FIFO, &priority); 47 | mlockall(MCL_CURRENT); 48 | 49 | init_mappings(); 50 | init_autoconfig(); 51 | init_fastmem(); 52 | init_customchips(); 53 | 54 | ps_setup_protocol(); 55 | ps_reset_state_machine(); 56 | ps_pulse_reset(); 57 | 58 | usleep(1500); 59 | 60 | m68k_init(); 61 | m68k_set_cpu_type(M68K_CPU_TYPE_68000); 62 | m68k_pulse_reset(); 63 | 64 | int res = init_kickstart(); 65 | if (res == 0) 66 | m68k_set_reg(M68K_REG_PC, KICK_BASE + 2); 67 | 68 | if (use_gayle_emulation) 69 | init_gayle("hd0.img"); 70 | 71 | #if A314_ENABLED 72 | res = a314_init(); 73 | if (res < 0) { 74 | printf("Unable to initialize A314 emulation\n"); 75 | } 76 | #endif 77 | 78 | while (1) { 79 | ps_update_irq(); 80 | m68k_execute(1000); 81 | } 82 | 83 | return 0; 84 | } 85 | 86 | void cpu_pulse_reset() { 87 | ps_pulse_reset(); 88 | } 89 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/ps_autoconfig.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "ps_mappings.h" 5 | #include "psconf.h" 6 | 7 | #define AUTOCONFIG_BASE 0xe80000 8 | #define AUTOCONFIG_SIZE (64 * 1024) 9 | 10 | struct autoconfig_pic { 11 | unsigned char *rom; 12 | unsigned int rom_size; 13 | int configured; 14 | unsigned int base; 15 | void (*done_callback)(int configured, unsigned int base); 16 | }; 17 | 18 | static struct autoconfig_pic pics[MAX_AUTOCONFIG_PICS]; 19 | static int pic_count = 0; 20 | static int current_pic = 0; 21 | 22 | static unsigned int ac_read_memory_8(unsigned int address) { 23 | if (current_pic == pic_count) { 24 | return 0; 25 | } 26 | 27 | struct autoconfig_pic *pic = &pics[current_pic]; 28 | address -= AUTOCONFIG_BASE; 29 | 30 | unsigned char val = 0; 31 | if ((address & 1) == 0 && (address / 2) < pic->rom_size) 32 | val = pic->rom[address / 2]; 33 | val <<= 4; 34 | if (address != 0 && address != 2 && address != 40 && address != 42) 35 | val ^= 0xf0; 36 | return (unsigned int)val; 37 | } 38 | 39 | static void ac_write_memory_8(unsigned int address, unsigned int value) { 40 | if (current_pic == pic_count) { 41 | return; 42 | } 43 | 44 | struct autoconfig_pic *pic = &pics[current_pic]; 45 | address -= AUTOCONFIG_BASE; 46 | int done = 0; 47 | 48 | if (address == 0x4a) { // base[19:16] 49 | pic->base = (value & 0xf0) << (16 - 4); 50 | } else if (address == 0x48) { // base[23:20] 51 | pic->base &= 0xff0fffff; 52 | pic->base |= (value & 0xf0) << (20 - 4); 53 | pic->configured = 1; 54 | done = 1; 55 | } else if (address == 0x4c) { // shut up 56 | done = 1; 57 | } 58 | 59 | if (done) { 60 | pic->done_callback(pic->configured, pic->base); 61 | current_pic++; 62 | } 63 | } 64 | 65 | static unsigned int ac_ignore_read(__attribute__((unused)) unsigned int address) { 66 | return 0; 67 | } 68 | 69 | static void ac_ignore_write(__attribute__((unused)) unsigned int address, __attribute__((unused)) unsigned int value) { 70 | } 71 | 72 | void add_autoconfig_pic(unsigned char *rom, int rom_size, void (*done_callback)(int configured, unsigned int base)) { 73 | if (pic_count == MAX_AUTOCONFIG_PICS) { 74 | printf("Error: too many autoconfig PICs, max=%d\n", MAX_AUTOCONFIG_PICS); 75 | exit(-1); 76 | } 77 | 78 | int index = pic_count; 79 | pics[index].rom = rom; 80 | pics[index].rom_size = rom_size; 81 | pics[index].configured = 0; 82 | pics[index].base = 0; 83 | pics[index].done_callback = done_callback; 84 | pic_count++; 85 | } 86 | 87 | void init_autoconfig() { 88 | struct ps_device ac_device = { 89 | ac_read_memory_8, ac_ignore_read, ac_ignore_read, 90 | ac_write_memory_8, ac_ignore_write, ac_ignore_write}; 91 | 92 | unsigned int devno = ps_add_device(&ac_device); 93 | ps_add_range(devno, AUTOCONFIG_BASE, AUTOCONFIG_SIZE); 94 | } 95 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/ps_autoconfig.h: -------------------------------------------------------------------------------- 1 | #ifndef _PS_AUTOCONFIG_H 2 | #define _PS_AUTOCONFIG_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #define AC_MEM_SIZE_8MB 0 9 | #define AC_MEM_SIZE_64KB 1 10 | #define AC_MEM_SIZE_128KB 2 11 | #define AC_MEM_SIZE_256KB 3 12 | #define AC_MEM_SIZE_512KB 4 13 | #define AC_MEM_SIZE_1MB 5 14 | #define AC_MEM_SIZE_2MB 6 15 | #define AC_MEM_SIZE_4MB 7 16 | 17 | void init_autoconfig(); 18 | void add_autoconfig_pic(unsigned char *rom, unsigned int rom_size, 19 | void (*done_callback)(int configured, unsigned int base)); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | 25 | #endif /* _PS_AUTOCONFIG_H */ 26 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/ps_customchips.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "a314/a314.h" 4 | #include "gayle.h" 5 | #include "m68k.h" 6 | #include "ps_mappings.h" 7 | #include "ps_protocol.h" 8 | #include "psconf.h" 9 | 10 | #define INTENAR 0xdff01c 11 | #define INTREQR 0xdff01e 12 | #define INTENA 0xdff09a 13 | #define INTREQ 0xdff09c 14 | 15 | #define INTF_SETCLR 0x8000 16 | #define INTF_INTEN 0x4000 17 | #define INTF_PORTS 0x0008 18 | 19 | static unsigned int intena_shadow = 0; 20 | 21 | #define INT2_ENABLED ((intena_shadow & (INTF_INTEN | INTF_PORTS)) == (INTF_INTEN | INTF_PORTS)) 22 | 23 | static unsigned int emu_int2_req() { 24 | return check_gayle_irq() 25 | #if A314_ENABLED 26 | || a314_check_int2() 27 | #endif 28 | ; 29 | } 30 | 31 | static unsigned int read_intenar() { 32 | unsigned int value = ps_read_16(INTENAR); 33 | intena_shadow = value; 34 | return value; 35 | } 36 | 37 | static unsigned int read_intreqr() { 38 | unsigned int value = ps_read_16(INTREQR); 39 | 40 | if (emu_int2_req()) 41 | value |= INTF_PORTS; 42 | 43 | return value; 44 | } 45 | 46 | static void write_intena(unsigned int value) { 47 | ps_write_16(INTENA, value); 48 | 49 | if (value & INTF_SETCLR) 50 | intena_shadow |= value & (~INTF_SETCLR); 51 | else 52 | intena_shadow &= ~value; 53 | } 54 | 55 | void ps_update_irq() { 56 | unsigned int ipl = 0; 57 | 58 | if (!ps_get_ipl_zero()) { 59 | unsigned int status = ps_read_status_reg(); 60 | ipl = (status & 0xe000) >> 13; 61 | } 62 | 63 | if (ipl < 2 && INT2_ENABLED && emu_int2_req()) { 64 | ipl = 2; 65 | } 66 | 67 | m68k_set_irq(ipl); 68 | } 69 | 70 | static unsigned int cc_read_8(unsigned int address) { 71 | return ps_read_8(address); 72 | } 73 | 74 | static unsigned int cc_read_16(unsigned int address) { 75 | if (address == INTENAR) 76 | return read_intenar(); 77 | else if (address == INTREQR) 78 | return read_intreqr(); 79 | else 80 | return ps_read_16(address); 81 | } 82 | 83 | static unsigned int cc_read_32(unsigned int address) { 84 | unsigned int a = cc_read_16(address); 85 | unsigned int b = cc_read_16(address + 2); 86 | return (a << 16) | b; 87 | } 88 | 89 | static void cc_write_8(unsigned int address, unsigned int value) { 90 | ps_write_8(address, value); 91 | } 92 | 93 | static void cc_write_16(unsigned int address, unsigned int value) { 94 | if (address == INTENA) 95 | write_intena(value); 96 | else 97 | ps_write_16(address, value); 98 | } 99 | 100 | static void cc_write_32(unsigned int address, unsigned int value) { 101 | cc_write_16(address, value >> 16); 102 | cc_write_16(address + 2, value); 103 | } 104 | 105 | int init_customchips() { 106 | struct ps_device cc_device = { 107 | cc_read_8, cc_read_16, cc_read_32, 108 | cc_write_8, cc_write_16, cc_write_32}; 109 | 110 | uint32_t devno = ps_add_device(&cc_device); 111 | ps_add_range(devno, 0xdf0000, 0x10000); 112 | return 0; 113 | } 114 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/ps_customchips.h: -------------------------------------------------------------------------------- 1 | #ifndef _PS_CUSTOMCHIPS_H 2 | #define _PS_CUSTOMCHIPS_H 3 | 4 | int init_customchips(); 5 | void ps_update_irq(); 6 | 7 | #endif /* _PS_CUSTOMCHIPS_H */ 8 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/ps_fastmem.c: -------------------------------------------------------------------------------- 1 | #include "ps_fastmem.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "ps_autoconfig.h" 11 | #include "ps_mappings.h" 12 | #include "ps_protocol.h" 13 | #include "psconf.h" 14 | 15 | unsigned char fastmem[FASTMEM_SIZE]; 16 | 17 | #if !FASTMEM_FASTPATH 18 | static unsigned int fastmem_read_8(unsigned int address) { 19 | return fastmem[address - FASTMEM_BASE]; 20 | } 21 | 22 | static unsigned int fastmem_read_16(unsigned int address) { 23 | return be16toh(*(uint16_t *)&fastmem[address - FASTMEM_BASE]); 24 | } 25 | 26 | static unsigned int fastmem_read_32(unsigned int address) { 27 | return be32toh(*(uint32_t *)&fastmem[address - FASTMEM_BASE]); 28 | } 29 | 30 | static void fastmem_write_8(unsigned int address, unsigned int value) { 31 | fastmem[address - FASTMEM_BASE] = value; 32 | } 33 | 34 | static void fastmem_write_16(unsigned int address, unsigned int value) { 35 | *(uint16_t *)&fastmem[address - FASTMEM_BASE] = htobe16(value); 36 | } 37 | 38 | static void fastmem_write_32(unsigned int address, unsigned int value) { 39 | *(uint32_t *)&fastmem[address - FASTMEM_BASE] = htobe32(value); 40 | } 41 | #endif 42 | 43 | static unsigned char ac_rom[] = { 44 | 0xe, AC_MEM_SIZE_8MB, // 00/02, link into memory free list, 8 MB 45 | 0x6, 0x9, // 04/06, product id 46 | 0x8, 0x0, // 08/0a, preference to 8 MB space 47 | 0x0, 0x0, // 0c/0e, reserved 48 | 0x0, 0x7, 0xd, 0xb, // 10/12/14/16, mfg id 49 | 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x2, 0x0 // 18/.../26, serial 50 | }; 51 | 52 | static void done_callback(int configured, unsigned int base) { 53 | if (!configured) { 54 | printf("Error: autoconfig did not map fastmem\n"); 55 | exit(-1); 56 | } 57 | 58 | if (base != FASTMEM_BASE) { 59 | printf("Error: autoconfig mapped fastmem at address %08x, should be %08x\n", 60 | base, FASTMEM_BASE); 61 | exit(-1); 62 | } 63 | } 64 | 65 | void init_fastmem() { 66 | #if !FASTMEM_FASTPATH 67 | struct ps_device fastmem_device = { 68 | fastmem_read_8, fastmem_read_16, fastmem_read_32, 69 | fastmem_write_8, fastmem_write_16, fastmem_write_32}; 70 | 71 | unsigned int devno = ps_add_device(&fastmem_device); 72 | ps_add_range(devno, FASTMEM_BASE, FASTMEM_SIZE); 73 | #endif 74 | 75 | #if FASTMEM_AUTOCONFIG 76 | add_autoconfig_pic(ac_rom, sizeof(ac_rom), done_callback); 77 | #endif 78 | } 79 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/ps_fastmem.h: -------------------------------------------------------------------------------- 1 | #ifndef _PS_FASTMEM_H 2 | #define _PS_FASTMEM_H 3 | 4 | #include "psconf.h" 5 | 6 | extern unsigned char fastmem[FASTMEM_SIZE]; 7 | 8 | void init_fastmem(); 9 | 10 | #endif /* _PS_FASTMEM_H */ 11 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/ps_kickstart.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "ps_mappings.h" 11 | #include "psconf.h" 12 | 13 | static uint8_t kickstart[KICK_SIZE]; 14 | 15 | static int load_kick_rom() { 16 | int fd = open("kick.rom", O_RDONLY); 17 | if (fd < 1) { 18 | printf("Failed loading kick.rom, using motherboard kickstart\n"); 19 | return -1; 20 | } 21 | 22 | int size = (int)lseek(fd, 0, SEEK_END); 23 | lseek(fd, 0, SEEK_SET); 24 | 25 | int bytes_read = (int)read(fd, &kickstart, size); 26 | close(fd); 27 | 28 | if (bytes_read != size) { 29 | printf("Failed loading kick.rom, using motherboard kickstart\n"); 30 | return -2; 31 | } 32 | 33 | if (size == 256 * 1024) { 34 | memcpy(&kickstart[size], &kickstart[0], size); 35 | } 36 | 37 | printf("Loaded kick.rom with size %d kib\n", size / 1024); 38 | return 0; 39 | } 40 | 41 | static unsigned int ks_read_8(unsigned int address) { 42 | return kickstart[address - KICK_BASE]; 43 | } 44 | 45 | static unsigned int ks_read_16(unsigned int address) { 46 | return be16toh(*(uint16_t *)&kickstart[address - KICK_BASE]); 47 | } 48 | 49 | static unsigned int ks_read_32(unsigned int address) { 50 | return be32toh(*(uint32_t *)&kickstart[address - KICK_BASE]); 51 | } 52 | 53 | static void ks_write_fail(unsigned int address, unsigned int value) { 54 | printf("Warning: ignored write to kickstart, address=%08x, value=%08x\n", address, value); 55 | } 56 | 57 | int init_kickstart() { 58 | if (load_kick_rom() < 0) 59 | return -1; 60 | 61 | struct ps_device ks_device = { 62 | ks_read_8, ks_read_16, ks_read_32, 63 | ks_write_fail, ks_write_fail, ks_write_fail}; 64 | 65 | uint32_t devno = ps_add_device(&ks_device); 66 | ps_add_range(devno, KICK_BASE, KICK_SIZE); 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/ps_kickstart.h: -------------------------------------------------------------------------------- 1 | #ifndef _PS_KICKSTART_H 2 | #define _PS_KICKSTART_H 3 | 4 | int init_kickstart(); 5 | 6 | #endif /* _PS_KICKSTART_H */ 7 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/ps_mappings.c: -------------------------------------------------------------------------------- 1 | #include "ps_mappings.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "ps_fastmem.h" 11 | #include "ps_protocol.h" 12 | #include "psconf.h" 13 | 14 | static struct ps_device devices[MAX_MAPPING_DEVICES]; 15 | static int devices_size = 0; 16 | 17 | #if USE_MAPPING_TABLE 18 | static unsigned char range_mapping[256]; 19 | #endif 20 | 21 | #if USE_MAPPING_LIST 22 | struct mapping_list_entry { 23 | unsigned int start; 24 | unsigned int end; 25 | struct ps_device *device; 26 | }; 27 | 28 | static struct mapping_list_entry mapping_list[MAX_MAPPING_LIST_LENGTH]; 29 | static int mapping_list_size = 0; 30 | #endif 31 | 32 | unsigned int m68k_read_memory_8(unsigned int address) { 33 | #if FASTMEM_FASTPATH 34 | if (address >= FASTMEM_BASE && address < FASTMEM_BASE + FASTMEM_SIZE) { 35 | return fastmem[address - FASTMEM_BASE]; 36 | } 37 | #endif 38 | 39 | #if USE_MAPPING_TABLE 40 | unsigned int devno = range_mapping[(address >> 16) & 0xff]; 41 | return devices[devno].read_8(address); 42 | #endif 43 | 44 | #if USE_MAPPING_LIST 45 | for (int i = 0; i < mapping_list_size; i++) { 46 | struct mapping_list_entry *e = &mapping_list[i]; 47 | if (address >= e->start && address <= e->end) 48 | return e->device->read_8(address); 49 | } 50 | return ps_read_8(address); 51 | #endif 52 | } 53 | 54 | unsigned int m68k_read_memory_16(unsigned int address) { 55 | #if FASTMEM_FASTPATH 56 | if (address >= FASTMEM_BASE && address < FASTMEM_BASE + FASTMEM_SIZE) { 57 | return be16toh(*(uint16_t *)&fastmem[address - FASTMEM_BASE]); 58 | } 59 | #endif 60 | 61 | #if USE_MAPPING_TABLE 62 | unsigned int devno = range_mapping[(address >> 16) & 0xff]; 63 | return devices[devno].read_16(address); 64 | #endif 65 | 66 | #if USE_MAPPING_LIST 67 | for (int i = 0; i < mapping_list_size; i++) { 68 | struct mapping_list_entry *e = &mapping_list[i]; 69 | if (address >= e->start && address <= e->end) 70 | return e->device->read_16(address); 71 | } 72 | return ps_read_16(address); 73 | #endif 74 | } 75 | 76 | unsigned int m68k_read_memory_32(unsigned int address) { 77 | #if FASTMEM_FASTPATH 78 | if (address >= FASTMEM_BASE && address < FASTMEM_BASE + FASTMEM_SIZE) { 79 | return be32toh(*(uint32_t *)&fastmem[address - FASTMEM_BASE]); 80 | } 81 | #endif 82 | 83 | #if USE_MAPPING_TABLE 84 | unsigned int devno = range_mapping[(address >> 16) & 0xff]; 85 | return devices[devno].read_32(address); 86 | #endif 87 | 88 | #if USE_MAPPING_LIST 89 | for (int i = 0; i < mapping_list_size; i++) { 90 | struct mapping_list_entry *e = &mapping_list[i]; 91 | if (address >= e->start && address <= e->end) 92 | return e->device->read_32(address); 93 | } 94 | return ps_read_32(address); 95 | #endif 96 | } 97 | 98 | void m68k_write_memory_8(unsigned int address, unsigned int value) { 99 | #if FASTMEM_FASTPATH 100 | if (address >= FASTMEM_BASE && address < FASTMEM_BASE + FASTMEM_SIZE) { 101 | fastmem[address - FASTMEM_BASE] = value; 102 | return; 103 | } 104 | #endif 105 | 106 | #if USE_MAPPING_TABLE 107 | unsigned int devno = range_mapping[(address >> 16) & 0xff]; 108 | devices[devno].write_8(address, value); 109 | return; 110 | #endif 111 | 112 | #if USE_MAPPING_LIST 113 | for (int i = 0; i < mapping_list_size; i++) { 114 | struct mapping_list_entry *e = &mapping_list[i]; 115 | if (address >= e->start && address <= e->end) { 116 | e->device->write_8(address, value); 117 | return; 118 | } 119 | } 120 | ps_write_8(address, value); 121 | #endif 122 | } 123 | 124 | void m68k_write_memory_16(unsigned int address, unsigned int value) { 125 | #if FASTMEM_FASTPATH 126 | if (address >= FASTMEM_BASE && address < FASTMEM_BASE + FASTMEM_SIZE) { 127 | *(uint16_t *)&fastmem[address - FASTMEM_BASE] = htobe16(value); 128 | return; 129 | } 130 | #endif 131 | 132 | #if USE_MAPPING_TABLE 133 | unsigned int devno = range_mapping[(address >> 16) & 0xff]; 134 | devices[devno].write_16(address, value); 135 | return; 136 | #endif 137 | 138 | #if USE_MAPPING_LIST 139 | for (int i = 0; i < mapping_list_size; i++) { 140 | struct mapping_list_entry *e = &mapping_list[i]; 141 | if (address >= e->start && address <= e->end) { 142 | e->device->write_16(address, value); 143 | return; 144 | } 145 | } 146 | ps_write_16(address, value); 147 | #endif 148 | } 149 | 150 | void m68k_write_memory_32(unsigned int address, unsigned int value) { 151 | #if FASTMEM_FASTPATH 152 | if (address >= FASTMEM_BASE && address < FASTMEM_BASE + FASTMEM_SIZE) { 153 | *(uint32_t *)&fastmem[address - FASTMEM_BASE] = htobe32(value); 154 | return; 155 | } 156 | #endif 157 | 158 | #if USE_MAPPING_TABLE 159 | unsigned int devno = range_mapping[(address >> 16) & 0xff]; 160 | devices[devno].write_32(address, value); 161 | return; 162 | #endif 163 | 164 | #if USE_MAPPING_LIST 165 | for (int i = 0; i < mapping_list_size; i++) { 166 | struct mapping_list_entry *e = &mapping_list[i]; 167 | if (address >= e->start && address <= e->end) { 168 | e->device->write_32(address, value); 169 | return; 170 | } 171 | } 172 | ps_write_32(address, value); 173 | #endif 174 | } 175 | 176 | int ps_add_device(struct ps_device *device) { 177 | if (devices_size == MAX_MAPPING_DEVICES) { 178 | printf("Error: Too many mapped devices, max = %d\n", MAX_MAPPING_DEVICES); 179 | exit(-1); 180 | } 181 | 182 | int devno = devices_size; 183 | devices_size++; 184 | 185 | memcpy(&devices[devno], device, sizeof(struct ps_device)); 186 | return devno; 187 | } 188 | 189 | void ps_add_range(unsigned char devno, unsigned int base, unsigned int size) { 190 | if ((base & 0xffff) != 0 || (size & 0xffff) != 0) { 191 | printf("Error: mappings must be 64 kB aligned\n"); 192 | exit(-1); 193 | } 194 | 195 | if (size == 0) { 196 | printf("Error: mappings cannot be zero size\n"); 197 | exit(-1); 198 | } 199 | 200 | #if USE_MAPPING_TABLE 201 | int start = base >> 16; 202 | int count = size >> 16; 203 | 204 | if (start > 255 || start + count > 256) { 205 | printf("Error: mapping table can only use the first 16 MB\n"); 206 | exit(-1); 207 | } 208 | 209 | for (int i = 0; i < count; i++) 210 | range_mapping[start + i] = devno; 211 | #endif 212 | 213 | #if USE_MAPPING_LIST 214 | if (mapping_list_size == MAX_MAPPING_LIST_LENGTH) { 215 | printf("Error: Out of mapping list entries, max=%d\n", MAX_MAPPING_LIST_LENGTH); 216 | exit(-1); 217 | } 218 | 219 | struct mapping_list_entry *entry = &mapping_list[mapping_list_size]; 220 | entry->start = base; 221 | entry->end = base + size - 1; 222 | entry->device = &devices[devno]; 223 | mapping_list_size++; 224 | #endif 225 | } 226 | 227 | void init_mappings() { 228 | struct ps_device mobo_device = { 229 | ps_read_8, ps_read_16, ps_read_32, 230 | ps_write_8, ps_write_16, ps_write_32}; 231 | 232 | uint32_t devno = ps_add_device(&mobo_device); 233 | assert(devno == 0); 234 | 235 | #if USE_MAPPING_TABLE 236 | memset(range_mapping, 0, sizeof(range_mapping)); 237 | #endif 238 | } 239 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/ps_mappings.h: -------------------------------------------------------------------------------- 1 | #ifndef _PS_MAPPINGS_H 2 | #define _PS_MAPPINGS_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | struct ps_device { 9 | unsigned int (*read_8)(unsigned int address); 10 | unsigned int (*read_16)(unsigned int address); 11 | unsigned int (*read_32)(unsigned int address); 12 | void (*write_8)(unsigned int address, unsigned int value); 13 | void (*write_16)(unsigned int address, unsigned int value); 14 | void (*write_32)(unsigned int address, unsigned int value); 15 | }; 16 | 17 | int ps_add_device(struct ps_device *device); 18 | void ps_add_range(unsigned char devno, unsigned int base, unsigned int size); 19 | 20 | void init_mappings(); 21 | 22 | #ifdef __cplusplus 23 | } 24 | #endif 25 | 26 | #endif /* _PS_MAPPINGS_H */ 27 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/ps_protocol.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "mailbox.h" 13 | 14 | 15 | #define BUS_TO_PHYS(x) ((x)&~0xC0000000) 16 | #define CODESIZE 16384 17 | 18 | int mailbox; 19 | unsigned handle; 20 | unsigned ptr; 21 | uint8_t *program; 22 | 23 | 24 | #define PIN_TXN_IN_PROGRESS 0 25 | #define PIN_IPL_ZERO 1 26 | #define PIN_A0 2 27 | #define PIN_A1 3 28 | #define PIN_CLK 4 29 | #define PIN_UNUSED 5 30 | #define PIN_RD 6 31 | #define PIN_WR 7 32 | #define PIN_D(x) (8 + x) 33 | 34 | #define REG_DATA 0 35 | #define REG_ADDR_LO 1 36 | #define REG_ADDR_HI 2 37 | #define REG_STATUS 3 38 | 39 | #define STATUS_BIT_INIT 1 40 | #define STATUS_BIT_RESET 2 41 | 42 | #define STATUS_MASK_IPL 0xe000 43 | #define STATUS_SHIFT_IPL 13 44 | 45 | //#define BCM2708_PERI_BASE 0x20000000 // pi0-1 46 | //#define BCM2708_PERI_BASE 0xFE000000 // pi4 47 | #define BCM2708_PERI_BASE 0x3F000000 // pi3 48 | #define BCM2708_PERI_SIZE 0x00F00000 49 | 50 | #define GPIO_ADDR 0x200000 /* GPIO controller */ 51 | #define GPCLK_ADDR 0x101000 52 | 53 | #define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */ 54 | #define GPCLK_BASE (BCM2708_PERI_BASE + 0x101000) 55 | 56 | #define CLK_PASSWD 0x5a000000 57 | #define CLK_GP0_CTL 0x070 58 | #define CLK_GP0_DIV 0x074 59 | 60 | // GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or 61 | // SET_GPIO_ALT(x,y) 62 | #define INP_GPIO(g) *(gpio + ((g) / 10)) &= ~(7 << (((g) % 10) * 3)) 63 | #define OUT_GPIO(g) *(gpio + ((g) / 10)) |= (1 << (((g) % 10) * 3)) 64 | #define SET_GPIO_ALT(g, a) \ 65 | *(gpio + (((g) / 10))) |= \ 66 | (((a) <= 3 ? (a) + 4 : (a) == 4 ? 3 : 2) << (((g) % 10) * 3)) 67 | 68 | #define GPIO_PULL *(gpio + 37) // Pull up/pull down 69 | #define GPIO_PULLCLK0 *(gpio + 38) // Pull up/pull down clock 70 | 71 | #define GPFSEL0_INPUT 0x0024c240 72 | #define GPFSEL1_INPUT 0x00000000 73 | #define GPFSEL2_INPUT 0x00000000 74 | 75 | #define GPFSEL0_OUTPUT 0x0924c240 76 | #define GPFSEL1_OUTPUT 0x09249249 77 | #define GPFSEL2_OUTPUT 0x00000249 78 | 79 | volatile unsigned int *gpio; 80 | volatile unsigned int *gpclk; 81 | 82 | //register volatile unsigned int *mbox asm ("r28"); 83 | volatile unsigned int *mbox; 84 | volatile unsigned int *mbox3; 85 | 86 | #define MBOX_ADDR 0x000000a0 87 | #define cmd_w8 1 88 | #define cmd_r8 3 89 | #define cmd_w16 5 90 | #define cmd_r16 7 91 | #define cmd_w32 9 92 | #define cmd_r32 11 93 | #define cmd_w64 13 94 | #define cmd_r64 15 95 | #define cmd_stat 17 96 | #define cmd_ipl 19 97 | 98 | unsigned int gpfsel0; 99 | unsigned int gpfsel1; 100 | unsigned int gpfsel2; 101 | 102 | unsigned int gpfsel0_o; 103 | unsigned int gpfsel1_o; 104 | unsigned int gpfsel2_o; 105 | 106 | static void setup_io() { 107 | int fd = open("/dev/mem", O_RDWR | O_SYNC); 108 | if (fd < 0) { 109 | printf("Unable to open /dev/mem. Run as root using sudo?\n"); 110 | exit(-1); 111 | } 112 | 113 | void *gpio_map = mmap( 114 | NULL, // Any adddress in our space will do 115 | BCM2708_PERI_SIZE, // Map length 116 | PROT_READ | PROT_WRITE, // Enable reading & writting to mapped memory 117 | MAP_SHARED, // Shared with other processes 118 | fd, // File to map 119 | BCM2708_PERI_BASE // Offset to GPIO peripheral 120 | ); 121 | 122 | //close(fd); 123 | 124 | if (gpio_map == MAP_FAILED) { 125 | printf("gpio mmap failed, errno = %d\n", errno); 126 | exit(-1); 127 | } 128 | 129 | gpio = ((volatile unsigned *)gpio_map) + GPIO_ADDR / 4; 130 | gpclk = ((volatile unsigned *)gpio_map) + GPCLK_ADDR / 4; 131 | //mbox = ((volatile unsigned *)gpio_map) + MBOX_ADDR / 4; 132 | 133 | 134 | void *mbox_map = mmap( 135 | NULL, // Any adddress in our space will do 136 | 1024, // Map length 137 | PROT_READ | PROT_WRITE, // Enable reading & writting to mapped memory 138 | MAP_SHARED, // Shared with other processes 139 | fd, // File to map 140 | BCM2708_PERI_BASE // Offset to GPIO peripheral 141 | ); 142 | 143 | close(fd); 144 | 145 | if (mbox_map == MAP_FAILED) { 146 | printf("mbox mmap failed, errno = %d\n", errno); 147 | exit(-1); 148 | } 149 | mbox = ((volatile unsigned *)mbox_map) + MBOX_ADDR / 4; 150 | 151 | 152 | mailbox = mbox_open(); 153 | handle = mem_alloc(mailbox, CODESIZE, 8, 4); 154 | ptr = mem_lock(mailbox, handle); 155 | program = mapmem(BUS_TO_PHYS(ptr), CODESIZE); 156 | 157 | int mfd = 0; 158 | mfd = open("code.bin", O_RDONLY); 159 | if (mfd < 1) { 160 | printf("Failed loading code.bin\n"); 161 | exit(0); 162 | } else { 163 | int size = (int)lseek(mfd, 0, SEEK_END); 164 | if (size > CODESIZE){ 165 | printf("VPU binary exceeds maximum codesize\n"); 166 | exit(0); 167 | } 168 | lseek(mfd, 0, SEEK_SET); 169 | read(mfd, program, size); 170 | printf("Loaded VPU1 code.bin with size %d byte\n", size); 171 | } 172 | 173 | printf("Execute VPU1, return R0 = 0x%08x\n", execute_vpu1(mailbox, ptr, 0, 0, 0, 0, 0, 0)); 174 | 175 | } 176 | 177 | static void setup_gpclk() { 178 | // Enable 200MHz CLK output on GPIO4, adjust divider and pll source depending 179 | // on pi model 180 | *(gpclk + (CLK_GP0_CTL / 4)) = CLK_PASSWD | (1 << 5); 181 | usleep(10); 182 | while ((*(gpclk + (CLK_GP0_CTL / 4))) & (1 << 7)) 183 | ; 184 | usleep(100); 185 | *(gpclk + (CLK_GP0_DIV / 4)) = 186 | CLK_PASSWD | (6 << 12); // divider , 6=200MHz on pi3 187 | usleep(10); 188 | *(gpclk + (CLK_GP0_CTL / 4)) = 189 | CLK_PASSWD | 5 | (1 << 4); // pll? 6=plld, 5=pllc 190 | usleep(10); 191 | while (((*(gpclk + (CLK_GP0_CTL / 4))) & (1 << 7)) == 0) 192 | ; 193 | usleep(100); 194 | 195 | SET_GPIO_ALT(PIN_CLK, 0); // gpclk0 196 | } 197 | 198 | void ps_setup_protocol() { 199 | setup_io(); 200 | setup_gpclk(); 201 | 202 | *(gpio + 10) = 0xffffec; 203 | 204 | *(gpio + 0) = GPFSEL0_INPUT; 205 | *(gpio + 1) = GPFSEL1_INPUT; 206 | *(gpio + 2) = GPFSEL2_INPUT; 207 | } 208 | 209 | void ps_write_8(unsigned int address, unsigned int data) { 210 | *(mbox + 0) = address; 211 | *(mbox + 1) = data; 212 | *(mbox + 3) = cmd_w8; 213 | while (*(mbox+3) & (1 << 0)) 214 | ; 215 | } 216 | void ps_write_16(unsigned int address, unsigned int data) { 217 | 218 | *(mbox + 0) = address; 219 | *(mbox + 1) = data; 220 | *(mbox + 3) = cmd_w16; 221 | while (*(mbox+3) & (1 << 0)) 222 | ; 223 | } 224 | 225 | /* 226 | void ps_write_32(unsigned int address, unsigned int value) { 227 | ps_write_16(address, value >> 16); 228 | ps_write_16(address + 2, value); 229 | } 230 | */ 231 | 232 | 233 | void ps_write_32(unsigned int address, unsigned int data) { 234 | *(mbox + 0) = address; 235 | *(mbox + 1) = data; 236 | *(mbox + 3) = cmd_w32; 237 | while (*(mbox + 3) & (1 << 0)) 238 | ; 239 | } 240 | 241 | 242 | unsigned int ps_read_8(unsigned int address) { 243 | *(mbox + 0) = address; 244 | *(mbox + 3) = cmd_r8; 245 | while (*(mbox+3) & (1 << 0)) 246 | ; 247 | return *(mbox + 1); 248 | } 249 | 250 | unsigned int ps_read_16(unsigned int address) { 251 | *(mbox + 0) = address; 252 | *(mbox + 3) = cmd_r16; 253 | while (*(mbox+3) & (1 << 0)) 254 | ; 255 | return *(mbox + 1); 256 | } 257 | 258 | 259 | /* 260 | unsigned int ps_read_32(unsigned int address) { 261 | unsigned int a = ps_read_16(address); 262 | unsigned int b = ps_read_16(address + 2); 263 | return (a << 16) | b; 264 | } 265 | */ 266 | 267 | 268 | unsigned int ps_read_32(unsigned int address) { 269 | *(mbox + 0) = address; 270 | *(mbox + 3) = cmd_r32; 271 | while (*(mbox + 3) & (1 << 0)) 272 | ; 273 | return *(mbox + 1); 274 | } 275 | 276 | 277 | void ps_write_status_reg(unsigned int value) { 278 | *(gpio + 0) = GPFSEL0_OUTPUT; 279 | *(gpio + 1) = GPFSEL1_OUTPUT; 280 | *(gpio + 2) = GPFSEL2_OUTPUT; 281 | 282 | *(gpio + 7) = ((value & 0xffff) << 8) | (REG_STATUS << PIN_A0); 283 | 284 | *(gpio + 7) = 1 << PIN_WR; 285 | *(gpio + 7) = 1 << PIN_WR; // delay 286 | *(gpio + 10) = 1 << PIN_WR; 287 | *(gpio + 10) = 0xffffec; 288 | 289 | *(gpio + 0) = GPFSEL0_INPUT; 290 | *(gpio + 1) = GPFSEL1_INPUT; 291 | *(gpio + 2) = GPFSEL2_INPUT; 292 | } 293 | 294 | 295 | unsigned int ps_read_status_reg() { 296 | 297 | *(mbox + 3) = cmd_stat; 298 | while (*(mbox + 3) & (1 << 0)) 299 | ; 300 | return *(mbox + 1); 301 | } 302 | 303 | void ps_reset_state_machine() { 304 | ps_write_status_reg(STATUS_BIT_INIT); 305 | usleep(1500); 306 | ps_write_status_reg(0); 307 | usleep(100); 308 | } 309 | 310 | void ps_pulse_reset() { 311 | ps_write_status_reg(0); 312 | usleep(100000); 313 | ps_write_status_reg(STATUS_BIT_RESET); 314 | } 315 | 316 | unsigned int ps_get_ipl_zero() { 317 | *(mbox + 3) = cmd_ipl; 318 | while (*(mbox + 3) & (1 << 0)) 319 | ; 320 | return *(mbox + 1); 321 | } 322 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/ps_protocol.c.arm: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define PIN_TXN_IN_PROGRESS 0 12 | #define PIN_IPL_ZERO 1 13 | #define PIN_A0 2 14 | #define PIN_A1 3 15 | #define PIN_CLK 4 16 | #define PIN_UNUSED 5 17 | #define PIN_RD 6 18 | #define PIN_WR 7 19 | #define PIN_D(x) (8 + x) 20 | 21 | #define REG_DATA 0 22 | #define REG_ADDR_LO 1 23 | #define REG_ADDR_HI 2 24 | #define REG_STATUS 3 25 | 26 | #define STATUS_BIT_INIT 1 27 | #define STATUS_BIT_RESET 2 28 | 29 | #define STATUS_MASK_IPL 0xe000 30 | #define STATUS_SHIFT_IPL 13 31 | 32 | //#define BCM2708_PERI_BASE 0x20000000 // pi0-1 33 | //#define BCM2708_PERI_BASE 0xFE000000 // pi4 34 | #define BCM2708_PERI_BASE 0x3F000000 // pi3 35 | #define BCM2708_PERI_SIZE 0x01000000 36 | 37 | #define GPIO_ADDR 0x200000 /* GPIO controller */ 38 | #define GPCLK_ADDR 0x101000 39 | 40 | #define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */ 41 | #define GPCLK_BASE (BCM2708_PERI_BASE + 0x101000) 42 | 43 | #define CLK_PASSWD 0x5a000000 44 | #define CLK_GP0_CTL 0x070 45 | #define CLK_GP0_DIV 0x074 46 | 47 | // GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or 48 | // SET_GPIO_ALT(x,y) 49 | #define INP_GPIO(g) *(gpio + ((g) / 10)) &= ~(7 << (((g) % 10) * 3)) 50 | #define OUT_GPIO(g) *(gpio + ((g) / 10)) |= (1 << (((g) % 10) * 3)) 51 | #define SET_GPIO_ALT(g, a) \ 52 | *(gpio + (((g) / 10))) |= \ 53 | (((a) <= 3 ? (a) + 4 : (a) == 4 ? 3 : 2) << (((g) % 10) * 3)) 54 | 55 | #define GPIO_PULL *(gpio + 37) // Pull up/pull down 56 | #define GPIO_PULLCLK0 *(gpio + 38) // Pull up/pull down clock 57 | 58 | #define GPFSEL0_INPUT 0x0024c240 59 | #define GPFSEL1_INPUT 0x00000000 60 | #define GPFSEL2_INPUT 0x00000000 61 | 62 | #define GPFSEL0_OUTPUT 0x0924c240 63 | #define GPFSEL1_OUTPUT 0x09249249 64 | #define GPFSEL2_OUTPUT 0x00000249 65 | 66 | volatile unsigned int *gpio; 67 | volatile unsigned int *gpclk; 68 | 69 | unsigned int gpfsel0; 70 | unsigned int gpfsel1; 71 | unsigned int gpfsel2; 72 | 73 | unsigned int gpfsel0_o; 74 | unsigned int gpfsel1_o; 75 | unsigned int gpfsel2_o; 76 | 77 | static void setup_io() { 78 | int fd = open("/dev/mem", O_RDWR | O_SYNC); 79 | if (fd < 0) { 80 | printf("Unable to open /dev/mem. Run as root using sudo?\n"); 81 | exit(-1); 82 | } 83 | 84 | void *gpio_map = mmap( 85 | NULL, // Any adddress in our space will do 86 | BCM2708_PERI_SIZE, // Map length 87 | PROT_READ | PROT_WRITE, // Enable reading & writting to mapped memory 88 | MAP_SHARED, // Shared with other processes 89 | fd, // File to map 90 | BCM2708_PERI_BASE // Offset to GPIO peripheral 91 | ); 92 | 93 | close(fd); 94 | 95 | if (gpio_map == MAP_FAILED) { 96 | printf("mmap failed, errno = %d\n", errno); 97 | exit(-1); 98 | } 99 | 100 | gpio = ((volatile unsigned *)gpio_map) + GPIO_ADDR / 4; 101 | gpclk = ((volatile unsigned *)gpio_map) + GPCLK_ADDR / 4; 102 | } 103 | 104 | static void setup_gpclk() { 105 | // Enable 200MHz CLK output on GPIO4, adjust divider and pll source depending 106 | // on pi model 107 | *(gpclk + (CLK_GP0_CTL / 4)) = CLK_PASSWD | (1 << 5); 108 | usleep(10); 109 | while ((*(gpclk + (CLK_GP0_CTL / 4))) & (1 << 7)) 110 | ; 111 | usleep(100); 112 | *(gpclk + (CLK_GP0_DIV / 4)) = 113 | CLK_PASSWD | (6 << 12); // divider , 6=200MHz on pi3 114 | usleep(10); 115 | *(gpclk + (CLK_GP0_CTL / 4)) = 116 | CLK_PASSWD | 5 | (1 << 4); // pll? 6=plld, 5=pllc 117 | usleep(10); 118 | while (((*(gpclk + (CLK_GP0_CTL / 4))) & (1 << 7)) == 0) 119 | ; 120 | usleep(100); 121 | 122 | SET_GPIO_ALT(PIN_CLK, 0); // gpclk0 123 | } 124 | 125 | void ps_setup_protocol() { 126 | setup_io(); 127 | setup_gpclk(); 128 | 129 | *(gpio + 10) = 0xffffec; 130 | 131 | *(gpio + 0) = GPFSEL0_INPUT; 132 | *(gpio + 1) = GPFSEL1_INPUT; 133 | *(gpio + 2) = GPFSEL2_INPUT; 134 | } 135 | 136 | void ps_write_16(unsigned int address, unsigned int data) { 137 | *(gpio + 0) = GPFSEL0_OUTPUT; 138 | *(gpio + 1) = GPFSEL1_OUTPUT; 139 | *(gpio + 2) = GPFSEL2_OUTPUT; 140 | 141 | *(gpio + 7) = ((data & 0xffff) << 8) | (REG_DATA << PIN_A0); 142 | *(gpio + 7) = 1 << PIN_WR; 143 | *(gpio + 10) = 1 << PIN_WR; 144 | *(gpio + 10) = 0xffffec; 145 | 146 | *(gpio + 7) = ((address & 0xffff) << 8) | (REG_ADDR_LO << PIN_A0); 147 | *(gpio + 7) = 1 << PIN_WR; 148 | *(gpio + 10) = 1 << PIN_WR; 149 | *(gpio + 10) = 0xffffec; 150 | 151 | *(gpio + 7) = ((0x0000 | (address >> 16)) << 8) | (REG_ADDR_HI << PIN_A0); 152 | *(gpio + 7) = 1 << PIN_WR; 153 | *(gpio + 10) = 1 << PIN_WR; 154 | *(gpio + 10) = 0xffffec; 155 | 156 | *(gpio + 0) = GPFSEL0_INPUT; 157 | *(gpio + 1) = GPFSEL1_INPUT; 158 | *(gpio + 2) = GPFSEL2_INPUT; 159 | 160 | while (*(gpio + 13) & (1 << PIN_TXN_IN_PROGRESS)) 161 | ; 162 | } 163 | 164 | void ps_write_8(unsigned int address, unsigned int data) { 165 | if ((address & 1) == 0) 166 | data = data + (data << 8); // EVEN, A0=0,UDS 167 | else 168 | data = data & 0xff; // ODD , A0=1,LDS 169 | 170 | *(gpio + 0) = GPFSEL0_OUTPUT; 171 | *(gpio + 1) = GPFSEL1_OUTPUT; 172 | *(gpio + 2) = GPFSEL2_OUTPUT; 173 | 174 | *(gpio + 7) = ((data & 0xffff) << 8) | (REG_DATA << PIN_A0); 175 | *(gpio + 7) = 1 << PIN_WR; 176 | *(gpio + 10) = 1 << PIN_WR; 177 | *(gpio + 10) = 0xffffec; 178 | 179 | *(gpio + 7) = ((address & 0xffff) << 8) | (REG_ADDR_LO << PIN_A0); 180 | *(gpio + 7) = 1 << PIN_WR; 181 | *(gpio + 10) = 1 << PIN_WR; 182 | *(gpio + 10) = 0xffffec; 183 | 184 | *(gpio + 7) = ((0x0100 | (address >> 16)) << 8) | (REG_ADDR_HI << PIN_A0); 185 | *(gpio + 7) = 1 << PIN_WR; 186 | *(gpio + 10) = 1 << PIN_WR; 187 | *(gpio + 10) = 0xffffec; 188 | 189 | *(gpio + 0) = GPFSEL0_INPUT; 190 | *(gpio + 1) = GPFSEL1_INPUT; 191 | *(gpio + 2) = GPFSEL2_INPUT; 192 | 193 | while (*(gpio + 13) & (1 << PIN_TXN_IN_PROGRESS)) 194 | ; 195 | } 196 | 197 | void ps_write_32(unsigned int address, unsigned int value) { 198 | ps_write_16(address, value >> 16); 199 | ps_write_16(address + 2, value); 200 | } 201 | 202 | unsigned int ps_read_16(unsigned int address) { 203 | *(gpio + 0) = GPFSEL0_OUTPUT; 204 | *(gpio + 1) = GPFSEL1_OUTPUT; 205 | *(gpio + 2) = GPFSEL2_OUTPUT; 206 | 207 | *(gpio + 7) = ((address & 0xffff) << 8) | (REG_ADDR_LO << PIN_A0); 208 | *(gpio + 7) = 1 << PIN_WR; 209 | *(gpio + 10) = 1 << PIN_WR; 210 | *(gpio + 10) = 0xffffec; 211 | 212 | *(gpio + 7) = ((0x0200 | (address >> 16)) << 8) | (REG_ADDR_HI << PIN_A0); 213 | *(gpio + 7) = 1 << PIN_WR; 214 | *(gpio + 10) = 1 << PIN_WR; 215 | *(gpio + 10) = 0xffffec; 216 | 217 | *(gpio + 0) = GPFSEL0_INPUT; 218 | *(gpio + 1) = GPFSEL1_INPUT; 219 | *(gpio + 2) = GPFSEL2_INPUT; 220 | 221 | *(gpio + 7) = (REG_DATA << PIN_A0); 222 | *(gpio + 7) = 1 << PIN_RD; 223 | 224 | while (*(gpio + 13) & (1 << PIN_TXN_IN_PROGRESS)) 225 | ; 226 | 227 | unsigned int value = *(gpio + 13); 228 | 229 | *(gpio + 10) = 0xffffec; 230 | 231 | return (value >> 8) & 0xffff; 232 | } 233 | 234 | unsigned int ps_read_8(unsigned int address) { 235 | *(gpio + 0) = GPFSEL0_OUTPUT; 236 | *(gpio + 1) = GPFSEL1_OUTPUT; 237 | *(gpio + 2) = GPFSEL2_OUTPUT; 238 | 239 | *(gpio + 7) = ((address & 0xffff) << 8) | (REG_ADDR_LO << PIN_A0); 240 | *(gpio + 7) = 1 << PIN_WR; 241 | *(gpio + 10) = 1 << PIN_WR; 242 | *(gpio + 10) = 0xffffec; 243 | 244 | *(gpio + 7) = ((0x0300 | (address >> 16)) << 8) | (REG_ADDR_HI << PIN_A0); 245 | *(gpio + 7) = 1 << PIN_WR; 246 | *(gpio + 10) = 1 << PIN_WR; 247 | *(gpio + 10) = 0xffffec; 248 | 249 | *(gpio + 0) = GPFSEL0_INPUT; 250 | *(gpio + 1) = GPFSEL1_INPUT; 251 | *(gpio + 2) = GPFSEL2_INPUT; 252 | 253 | *(gpio + 7) = (REG_DATA << PIN_A0); 254 | *(gpio + 7) = 1 << PIN_RD; 255 | 256 | while (*(gpio + 13) & (1 << PIN_TXN_IN_PROGRESS)) 257 | ; 258 | 259 | unsigned int value = *(gpio + 13); 260 | 261 | *(gpio + 10) = 0xffffec; 262 | 263 | value = (value >> 8) & 0xffff; 264 | 265 | if ((address & 1) == 0) 266 | return (value >> 8) & 0xff; // EVEN, A0=0,UDS 267 | else 268 | return value & 0xff; // ODD , A0=1,LDS 269 | } 270 | 271 | unsigned int ps_read_32(unsigned int address) { 272 | unsigned int a = ps_read_16(address); 273 | unsigned int b = ps_read_16(address + 2); 274 | return (a << 16) | b; 275 | } 276 | 277 | void ps_write_status_reg(unsigned int value) { 278 | *(gpio + 0) = GPFSEL0_OUTPUT; 279 | *(gpio + 1) = GPFSEL1_OUTPUT; 280 | *(gpio + 2) = GPFSEL2_OUTPUT; 281 | 282 | *(gpio + 7) = ((value & 0xffff) << 8) | (REG_STATUS << PIN_A0); 283 | 284 | *(gpio + 7) = 1 << PIN_WR; 285 | *(gpio + 7) = 1 << PIN_WR; // delay 286 | *(gpio + 10) = 1 << PIN_WR; 287 | *(gpio + 10) = 0xffffec; 288 | 289 | *(gpio + 0) = GPFSEL0_INPUT; 290 | *(gpio + 1) = GPFSEL1_INPUT; 291 | *(gpio + 2) = GPFSEL2_INPUT; 292 | } 293 | 294 | unsigned int ps_read_status_reg() { 295 | *(gpio + 7) = (REG_STATUS << PIN_A0); 296 | *(gpio + 7) = 1 << PIN_RD; 297 | *(gpio + 7) = 1 << PIN_RD; 298 | *(gpio + 7) = 1 << PIN_RD; 299 | *(gpio + 7) = 1 << PIN_RD; 300 | 301 | unsigned int value = *(gpio + 13); 302 | 303 | *(gpio + 10) = 0xffffec; 304 | 305 | return (value >> 8) & 0xffff; 306 | } 307 | 308 | void ps_reset_state_machine() { 309 | ps_write_status_reg(STATUS_BIT_INIT); 310 | usleep(1500); 311 | ps_write_status_reg(0); 312 | usleep(100); 313 | } 314 | 315 | void ps_pulse_reset() { 316 | ps_write_status_reg(0); 317 | usleep(100000); 318 | ps_write_status_reg(STATUS_BIT_RESET); 319 | } 320 | 321 | unsigned int ps_get_ipl_zero() { 322 | unsigned int value = *(gpio + 13); 323 | return value & (1 << PIN_IPL_ZERO); 324 | } 325 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/ps_protocol.c.save: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "mailbox.h" 13 | 14 | 15 | #define BUS_TO_PHYS(x) ((x)&~0xC0000000) 16 | #define CODESIZE 16384 17 | 18 | int mailbox; 19 | unsigned handle; 20 | unsigned ptr; 21 | uint8_t *program; 22 | 23 | 24 | #define PIN_TXN_IN_PROGRESS 0 25 | #define PIN_IPL_ZERO 1 26 | #define PIN_A0 2 27 | #define PIN_A1 3 28 | #define PIN_CLK 4 29 | #define PIN_UNUSED 5 30 | #define PIN_RD 6 31 | #define PIN_WR 7 32 | #define PIN_D(x) (8 + x) 33 | 34 | #define REG_DATA 0 35 | #define REG_ADDR_LO 1 36 | #define REG_ADDR_HI 2 37 | #define REG_STATUS 3 38 | 39 | #define STATUS_BIT_INIT 1 40 | #define STATUS_BIT_RESET 2 41 | 42 | #define STATUS_MASK_IPL 0xe000 43 | #define STATUS_SHIFT_IPL 13 44 | 45 | //#define BCM2708_PERI_BASE 0x20000000 // pi0-1 46 | //#define BCM2708_PERI_BASE 0xFE000000 // pi4 47 | #define BCM2708_PERI_BASE 0x3F000000 // pi3 48 | #define BCM2708_PERI_SIZE 0x00F00000 49 | 50 | #define GPIO_ADDR 0x200000 /* GPIO controller */ 51 | #define GPCLK_ADDR 0x101000 52 | 53 | #define GPIO_BASE (BCM2708_PERI_BASE + 0x200000) /* GPIO controller */ 54 | #define GPCLK_BASE (BCM2708_PERI_BASE + 0x101000) 55 | 56 | #define CLK_PASSWD 0x5a000000 57 | #define CLK_GP0_CTL 0x070 58 | #define CLK_GP0_DIV 0x074 59 | 60 | // GPIO setup macros. Always use INP_GPIO(x) before using OUT_GPIO(x) or 61 | // SET_GPIO_ALT(x,y) 62 | #define INP_GPIO(g) *(gpio + ((g) / 10)) &= ~(7 << (((g) % 10) * 3)) 63 | #define OUT_GPIO(g) *(gpio + ((g) / 10)) |= (1 << (((g) % 10) * 3)) 64 | #define SET_GPIO_ALT(g, a) \ 65 | *(gpio + (((g) / 10))) |= \ 66 | (((a) <= 3 ? (a) + 4 : (a) == 4 ? 3 : 2) << (((g) % 10) * 3)) 67 | 68 | #define GPIO_PULL *(gpio + 37) // Pull up/pull down 69 | #define GPIO_PULLCLK0 *(gpio + 38) // Pull up/pull down clock 70 | 71 | #define GPFSEL0_INPUT 0x0024c240 72 | #define GPFSEL1_INPUT 0x00000000 73 | #define GPFSEL2_INPUT 0x00000000 74 | 75 | #define GPFSEL0_OUTPUT 0x0924c240 76 | #define GPFSEL1_OUTPUT 0x09249249 77 | #define GPFSEL2_OUTPUT 0x00000249 78 | 79 | volatile unsigned int *gpio; 80 | volatile unsigned int *gpclk; 81 | 82 | //register volatile unsigned int *mbox asm ("r28"); 83 | volatile unsigned int *mbox; 84 | volatile unsigned int *mbox3; 85 | 86 | #define MBOX_ADDR 0x000000a0 87 | #define cmd_w8 1 88 | #define cmd_r8 3 89 | #define cmd_w16 5 90 | #define cmd_r16 7 91 | #define cmd_w32 9 92 | #define cmd_r32 11 93 | #define cmd_w64 13 94 | #define cmd_r64 15 95 | #define cmd_stat 17 96 | #define cmd_ipl 19 97 | 98 | unsigned int gpfsel0; 99 | unsigned int gpfsel1; 100 | unsigned int gpfsel2; 101 | 102 | unsigned int gpfsel0_o; 103 | unsigned int gpfsel1_o; 104 | unsigned int gpfsel2_o; 105 | 106 | static void setup_io() { 107 | int fd = open("/dev/mem", O_RDWR | O_SYNC); 108 | if (fd < 0) { 109 | printf("Unable to open /dev/mem. Run as root using sudo?\n"); 110 | exit(-1); 111 | } 112 | 113 | void *gpio_map = mmap( 114 | NULL, // Any adddress in our space will do 115 | BCM2708_PERI_SIZE, // Map length 116 | PROT_READ | PROT_WRITE, // Enable reading & writting to mapped memory 117 | MAP_SHARED, // Shared with other processes 118 | fd, // File to map 119 | BCM2708_PERI_BASE // Offset to GPIO peripheral 120 | ); 121 | 122 | 123 | if (gpio_map == MAP_FAILED) { 124 | printf("gpio mmap failed, errno = %d\n", errno); 125 | exit(-1); 126 | } 127 | 128 | gpio = ((volatile unsigned *)gpio_map) + GPIO_ADDR / 4; 129 | gpclk = ((volatile unsigned *)gpio_map) + GPCLK_ADDR / 4; 130 | mbox = ((volatile unsigned *)gpio_map) + MBOX_ADDR / 4; 131 | 132 | /* 133 | void *mbox_map = mmap( 134 | NULL, // Any adddress in our space will do 135 | 1024, // Map length 136 | PROT_READ | PROT_WRITE, // Enable reading & writting to mapped memory 137 | MAP_SHARED, // Shared with other processes 138 | fd, // File to map 139 | BCM2708_PERI_BASE // Offset to GPIO peripheral 140 | ); 141 | 142 | close(fd); 143 | 144 | if (mbox_map == MAP_FAILED) { 145 | printf("mbox mmap failed, errno = %d\n", errno); 146 | exit(-1); 147 | } 148 | mbox = ((volatile unsigned *)mbox_map) + MBOX_ADDR / 4; 149 | */ 150 | 151 | mailbox = mbox_open(); 152 | handle = mem_alloc(mailbox, CODESIZE, 8, 4); 153 | ptr = mem_lock(mailbox, handle); 154 | program = mapmem(BUS_TO_PHYS(ptr), CODESIZE); 155 | 156 | int mfd = 0; 157 | mfd = open("code.bin", O_RDONLY); 158 | if (mfd < 1) { 159 | printf("Failed loading code.bin\n"); 160 | exit(0); 161 | } else { 162 | int size = (int)lseek(mfd, 0, SEEK_END); 163 | if (size > CODESIZE){ 164 | printf("VPU binary exceeds maximum codesize\n"); 165 | exit(0); 166 | } 167 | lseek(mfd, 0, SEEK_SET); 168 | read(mfd, program, size); 169 | printf("Loaded VPU1 code.bin with size %d byte\n", size); 170 | } 171 | 172 | printf("Execute VPU1, return R0 = 0x%08x\n", execute_vpu1(mailbox, ptr, 0, 0, 0, 0, 0, 0)); 173 | 174 | } 175 | 176 | static void setup_gpclk() { 177 | // Enable 200MHz CLK output on GPIO4, adjust divider and pll source depending 178 | // on pi model 179 | *(gpclk + (CLK_GP0_CTL / 4)) = CLK_PASSWD | (1 << 5); 180 | usleep(10); 181 | while ((*(gpclk + (CLK_GP0_CTL / 4))) & (1 << 7)) 182 | ; 183 | usleep(100); 184 | *(gpclk + (CLK_GP0_DIV / 4)) = 185 | CLK_PASSWD | (6 << 12); // divider , 6=200MHz on pi3 186 | usleep(10); 187 | *(gpclk + (CLK_GP0_CTL / 4)) = 188 | CLK_PASSWD | 5 | (1 << 4); // pll? 6=plld, 5=pllc 189 | usleep(10); 190 | while (((*(gpclk + (CLK_GP0_CTL / 4))) & (1 << 7)) == 0) 191 | ; 192 | usleep(100); 193 | 194 | SET_GPIO_ALT(PIN_CLK, 0); // gpclk0 195 | } 196 | 197 | void ps_setup_protocol() { 198 | setup_io(); 199 | setup_gpclk(); 200 | 201 | *(gpio + 10) = 0xffffec; 202 | 203 | *(gpio + 0) = GPFSEL0_INPUT; 204 | *(gpio + 1) = GPFSEL1_INPUT; 205 | *(gpio + 2) = GPFSEL2_INPUT; 206 | } 207 | 208 | void ps_write_8(unsigned int address, unsigned int data) { 209 | *(mbox + 0) = address; 210 | *(mbox + 1) = data; 211 | *(mbox + 3) = cmd_w8; 212 | while (*(mbox+3) & (1 << 0)) 213 | ; 214 | } 215 | void ps_write_16(unsigned int address, unsigned int data) { 216 | 217 | *(mbox + 0) = address; 218 | *(mbox + 1) = data; 219 | *(mbox + 3) = cmd_w16; 220 | while (*(mbox+3) & (1 << 0)) 221 | ; 222 | } 223 | 224 | void ps_write_32(unsigned int address, unsigned int data) { 225 | *(mbox + 0) = address; 226 | *(mbox + 1) = data; 227 | *(mbox + 3) = cmd_w32; 228 | while (*(mbox + 3) & (1 << 0)) 229 | ; 230 | } 231 | 232 | unsigned int ps_read_8(unsigned int address) { 233 | *(mbox + 0) = address; 234 | *(mbox + 3) = cmd_r8; 235 | while (*(mbox+3) & (1 << 0)) 236 | ; 237 | return *(mbox + 1); 238 | } 239 | 240 | unsigned int ps_read_16(unsigned int address) { 241 | *(mbox + 0) = address; 242 | *(mbox + 3) = cmd_r16; 243 | while (*(mbox+3) & (1 << 0)) 244 | ; 245 | return *(mbox + 1); 246 | } 247 | 248 | unsigned int ps_read_32(unsigned int address) { 249 | *(mbox + 0) = address; 250 | *(mbox + 3) = cmd_r32; 251 | while (*(mbox + 3) & (1 << 0)) 252 | ; 253 | return *(mbox + 1); 254 | } 255 | 256 | 257 | void ps_write_status_reg(unsigned int value) { 258 | *(gpio + 0) = GPFSEL0_OUTPUT; 259 | *(gpio + 1) = GPFSEL1_OUTPUT; 260 | *(gpio + 2) = GPFSEL2_OUTPUT; 261 | 262 | *(gpio + 7) = ((value & 0xffff) << 8) | (REG_STATUS << PIN_A0); 263 | 264 | *(gpio + 7) = 1 << PIN_WR; 265 | *(gpio + 7) = 1 << PIN_WR; // delay 266 | *(gpio + 10) = 1 << PIN_WR; 267 | *(gpio + 10) = 0xffffec; 268 | 269 | *(gpio + 0) = GPFSEL0_INPUT; 270 | *(gpio + 1) = GPFSEL1_INPUT; 271 | *(gpio + 2) = GPFSEL2_INPUT; 272 | } 273 | 274 | 275 | unsigned int ps_read_status_reg() { 276 | 277 | *(mbox + 3) = cmd_stat; 278 | while (*(mbox + 3) & (1 << 0)) 279 | ; 280 | return *(mbox + 1); 281 | } 282 | 283 | void ps_reset_state_machine() { 284 | ps_write_status_reg(STATUS_BIT_INIT); 285 | usleep(1500); 286 | ps_write_status_reg(0); 287 | usleep(100); 288 | } 289 | 290 | void ps_pulse_reset() { 291 | ps_write_status_reg(0); 292 | usleep(100000); 293 | ps_write_status_reg(STATUS_BIT_RESET); 294 | } 295 | 296 | unsigned int ps_get_ipl_zero() { 297 | *(mbox + 3) = cmd_ipl; 298 | while (*(mbox + 3) & (1 << 0)) 299 | ; 300 | return *(mbox + 1); 301 | } 302 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/ps_protocol.h: -------------------------------------------------------------------------------- 1 | #ifndef _PS_PROTOCOL_H 2 | #define _PS_PROTOCOL_H 3 | 4 | unsigned int ps_read_8(unsigned int address); 5 | unsigned int ps_read_16(unsigned int address); 6 | unsigned int ps_read_32(unsigned int address); 7 | 8 | void ps_write_8(unsigned int address, unsigned int data); 9 | void ps_write_16(unsigned int address, unsigned int data); 10 | void ps_write_32(unsigned int address, unsigned int data); 11 | 12 | unsigned int ps_read_status_reg(); 13 | void ps_write_status_reg(unsigned int value); 14 | 15 | void ps_setup_protocol(); 16 | void ps_reset_state_machine(); 17 | void ps_pulse_reset(); 18 | 19 | unsigned int ps_get_ipl_zero(); 20 | 21 | #endif /* _PS_PROTOCOL_H */ 22 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/psconf.h: -------------------------------------------------------------------------------- 1 | #ifndef _PSCONF_H 2 | #define _PSCONF_H 3 | 4 | #define FASTMEM_FASTPATH 1 5 | #define FASTMEM_AUTOCONFIG 1 6 | 7 | #define USE_MAPPING_TABLE 1 8 | #define USE_MAPPING_LIST 0 9 | 10 | #define MAX_MAPPING_DEVICES 16 11 | #define MAX_MAPPING_LIST_LENGTH 32 12 | 13 | #define MAX_AUTOCONFIG_PICS 16 14 | 15 | #define A314_ENABLED 1 16 | 17 | #define FASTMEM_BASE 0x200000 18 | #define FASTMEM_SIZE (8 * 1024 * 1024) 19 | 20 | #define KICK_BASE 0xF80000 21 | #define KICK_SIZE (512 * 1024) 22 | 23 | #endif /* _PSCONF_H */ 24 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/softfloat/README.txt: -------------------------------------------------------------------------------- 1 | MAME note: this package is derived from the following original SoftFloat 2 | package and has been "re-packaged" to work with MAME's conventions and 3 | build system. The source files come from bits64/ and bits64/templates 4 | in the original distribution as MAME requires a compiler with a 64-bit 5 | integer type. 6 | 7 | 8 | Package Overview for SoftFloat Release 2b 9 | 10 | John R. Hauser 11 | 2002 May 27 12 | 13 | 14 | ---------------------------------------------------------------------------- 15 | Overview 16 | 17 | SoftFloat is a software implementation of floating-point that conforms to 18 | the IEC/IEEE Standard for Binary Floating-Point Arithmetic. SoftFloat is 19 | distributed in the form of C source code. Compiling the SoftFloat sources 20 | generates two things: 21 | 22 | -- A SoftFloat object file (typically `softfloat.o') containing the complete 23 | set of IEC/IEEE floating-point routines. 24 | 25 | -- A `timesoftfloat' program for evaluating the speed of the SoftFloat 26 | routines. (The SoftFloat module is linked into this program.) 27 | 28 | The SoftFloat package is documented in four text files: 29 | 30 | SoftFloat.txt Documentation for using the SoftFloat functions. 31 | SoftFloat-source.txt Documentation for compiling SoftFloat. 32 | SoftFloat-history.txt History of major changes to SoftFloat. 33 | timesoftfloat.txt Documentation for using `timesoftfloat'. 34 | 35 | Other files in the package comprise the source code for SoftFloat. 36 | 37 | Please be aware that some work is involved in porting this software to other 38 | targets. It is not just a matter of getting `make' to complete without 39 | error messages. I would have written the code that way if I could, but 40 | there are fundamental differences between systems that can't be hidden. 41 | You should not attempt to compile SoftFloat without first reading both 42 | `SoftFloat.txt' and `SoftFloat-source.txt'. 43 | 44 | 45 | ---------------------------------------------------------------------------- 46 | Legal Notice 47 | 48 | SoftFloat was written by me, John R. Hauser. This work was made possible in 49 | part by the International Computer Science Institute, located at Suite 600, 50 | 1947 Center Street, Berkeley, California 94704. Funding was partially 51 | provided by the National Science Foundation under grant MIP-9311980. The 52 | original version of this code was written as part of a project to build 53 | a fixed-point vector processor in collaboration with the University of 54 | California at Berkeley, overseen by Profs. Nelson Morgan and John Wawrzynek. 55 | 56 | THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 57 | has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 58 | TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 59 | PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL 60 | LOSSES, COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO 61 | FURTHERMORE EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER 62 | SCIENCE INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, 63 | COSTS, OR OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE 64 | SOFTWARE. 65 | 66 | Derivative works are acceptable, even for commercial purposes, provided 67 | that the minimal documentation requirements stated in the source code are 68 | satisfied. 69 | 70 | 71 | ---------------------------------------------------------------------------- 72 | Contact Information 73 | 74 | At the time of this writing, the most up-to-date information about 75 | SoftFloat and the latest release can be found at the Web page `http:// 76 | www.cs.berkeley.edu/~jhauser/arithmetic/SoftFloat.html'. 77 | 78 | 79 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/softfloat/mamesf.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------- 2 | | One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined. 3 | *----------------------------------------------------------------------------*/ 4 | #ifdef LSB_FIRST 5 | #define LITTLEENDIAN 6 | #else 7 | #define BIGENDIAN 8 | #endif 9 | 10 | /*---------------------------------------------------------------------------- 11 | | The macro `BITS64' can be defined to indicate that 64-bit integer types are 12 | | supported by the compiler. 13 | *----------------------------------------------------------------------------*/ 14 | #define BITS64 15 | 16 | /*---------------------------------------------------------------------------- 17 | | Each of the following `typedef's defines the most convenient type that holds 18 | | integers of at least as many bits as specified. For example, `uint8' should 19 | | be the most convenient type that can hold unsigned integers of as many as 20 | | 8 bits. The `flag' type must be able to hold either a 0 or 1. For most 21 | | implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed 22 | | to the same as `int'. 23 | *----------------------------------------------------------------------------*/ 24 | 25 | typedef sint8 flag; 26 | typedef sint8 int8; 27 | typedef sint16 int16; 28 | typedef sint32 int32; 29 | typedef sint64 int64; 30 | 31 | /*---------------------------------------------------------------------------- 32 | | Each of the following `typedef's defines a type that holds integers 33 | | of _exactly_ the number of bits specified. For instance, for most 34 | | implementation of C, `bits16' and `sbits16' should be `typedef'ed to 35 | | `unsigned short int' and `signed short int' (or `short int'), respectively. 36 | *----------------------------------------------------------------------------*/ 37 | typedef uint8 bits8; 38 | typedef sint8 sbits8; 39 | typedef uint16 bits16; 40 | typedef sint16 sbits16; 41 | typedef uint32 bits32; 42 | typedef sint32 sbits32; 43 | typedef uint64 bits64; 44 | typedef sint64 sbits64; 45 | 46 | /*---------------------------------------------------------------------------- 47 | | The `LIT64' macro takes as its argument a textual integer literal and 48 | | if necessary ``marks'' the literal as having a 64-bit integer type. 49 | | For example, the GNU C Compiler (`gcc') requires that 64-bit literals be 50 | | appended with the letters `LL' standing for `long long', which is `gcc's 51 | | name for the 64-bit integer type. Some compilers may allow `LIT64' to be 52 | | defined as the identity macro: `#define LIT64( a ) a'. 53 | *----------------------------------------------------------------------------*/ 54 | #define LIT64( a ) a##ULL 55 | 56 | /*---------------------------------------------------------------------------- 57 | | The macro `INLINE' can be used before functions that should be inlined. If 58 | | a compiler does not support explicit inlining, this macro should be defined 59 | | to be `static'. 60 | *----------------------------------------------------------------------------*/ 61 | // MAME defines INLINE 62 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/softfloat/milieu.h: -------------------------------------------------------------------------------- 1 | 2 | /*============================================================================ 3 | 4 | This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic 5 | Package, Release 2b. 6 | 7 | Written by John R. Hauser. This work was made possible in part by the 8 | International Computer Science Institute, located at Suite 600, 1947 Center 9 | Street, Berkeley, California 94704. Funding was partially provided by the 10 | National Science Foundation under grant MIP-9311980. The original version 11 | of this code was written as part of a project to build a fixed-point vector 12 | processor in collaboration with the University of California at Berkeley, 13 | overseen by Profs. Nelson Morgan and John Wawrzynek. More information 14 | is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ 15 | arithmetic/SoftFloat.html'. 16 | 17 | THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has 18 | been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES 19 | RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS 20 | AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, 21 | COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE 22 | EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE 23 | INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR 24 | OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. 25 | 26 | Derivative works are acceptable, even for commercial purposes, so long as 27 | (1) the source code for the derivative work includes prominent notice that 28 | the work is derivative, and (2) the source code includes prominent notice with 29 | these four paragraphs for those parts of this code that are retained. 30 | 31 | =============================================================================*/ 32 | 33 | /*---------------------------------------------------------------------------- 34 | | Include common integer types and flags. 35 | *----------------------------------------------------------------------------*/ 36 | #include "mamesf.h" 37 | 38 | /*---------------------------------------------------------------------------- 39 | | Symbolic Boolean literals. 40 | *----------------------------------------------------------------------------*/ 41 | #define FALSE 0 42 | #define TRUE 1 43 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/softfloat/softfloat-specialize: -------------------------------------------------------------------------------- 1 | 2 | /*============================================================================ 3 | 4 | This C source fragment is part of the SoftFloat IEC/IEEE Floating-point 5 | Arithmetic Package, Release 2b. 6 | 7 | Written by John R. Hauser. This work was made possible in part by the 8 | International Computer Science Institute, located at Suite 600, 1947 Center 9 | Street, Berkeley, California 94704. Funding was partially provided by the 10 | National Science Foundation under grant MIP-9311980. The original version 11 | of this code was written as part of a project to build a fixed-point vector 12 | processor in collaboration with the University of California at Berkeley, 13 | overseen by Profs. Nelson Morgan and John Wawrzynek. More information 14 | is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ 15 | arithmetic/SoftFloat.html'. 16 | 17 | THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has 18 | been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES 19 | RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS 20 | AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, 21 | COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE 22 | EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE 23 | INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR 24 | OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. 25 | 26 | Derivative works are acceptable, even for commercial purposes, so long as 27 | (1) the source code for the derivative work includes prominent notice that 28 | the work is derivative, and (2) the source code includes prominent notice with 29 | these four paragraphs for those parts of this code that are retained. 30 | 31 | =============================================================================*/ 32 | 33 | /*---------------------------------------------------------------------------- 34 | | Underflow tininess-detection mode, statically initialized to default value. 35 | | (The declaration in `softfloat.h' must match the `int8' type here.) 36 | *----------------------------------------------------------------------------*/ 37 | int8 float_detect_tininess = float_tininess_after_rounding; 38 | 39 | /*---------------------------------------------------------------------------- 40 | | Raises the exceptions specified by `flags'. Floating-point traps can be 41 | | defined here if desired. It is currently not possible for such a trap to 42 | | substitute a result value. If traps are not implemented, this routine 43 | | should be simply `float_exception_flags |= flags;'. 44 | *----------------------------------------------------------------------------*/ 45 | 46 | void float_raise( int8 flags ) 47 | { 48 | 49 | float_exception_flags |= flags; 50 | 51 | } 52 | 53 | /*---------------------------------------------------------------------------- 54 | | Internal canonical NaN format. 55 | *----------------------------------------------------------------------------*/ 56 | typedef struct { 57 | flag sign; 58 | bits64 high, low; 59 | } commonNaNT; 60 | 61 | /*---------------------------------------------------------------------------- 62 | | The pattern for a default generated single-precision NaN. 63 | *----------------------------------------------------------------------------*/ 64 | #define float32_default_nan 0xFFFFFFFF 65 | 66 | /*---------------------------------------------------------------------------- 67 | | Returns 1 if the single-precision floating-point value `a' is a NaN; 68 | | otherwise returns 0. 69 | *----------------------------------------------------------------------------*/ 70 | 71 | flag float32_is_nan( float32 a ) 72 | { 73 | 74 | return ( 0xFF000000 < (bits32) ( a<<1 ) ); 75 | 76 | } 77 | 78 | /*---------------------------------------------------------------------------- 79 | | Returns 1 if the single-precision floating-point value `a' is a signaling 80 | | NaN; otherwise returns 0. 81 | *----------------------------------------------------------------------------*/ 82 | 83 | flag float32_is_signaling_nan( float32 a ) 84 | { 85 | 86 | return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF ); 87 | 88 | } 89 | 90 | /*---------------------------------------------------------------------------- 91 | | Returns the result of converting the single-precision floating-point NaN 92 | | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 93 | | exception is raised. 94 | *----------------------------------------------------------------------------*/ 95 | 96 | static commonNaNT float32ToCommonNaN( float32 a ) 97 | { 98 | commonNaNT z; 99 | 100 | if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 101 | z.sign = a>>31; 102 | z.low = 0; 103 | z.high = ( (bits64) a )<<41; 104 | return z; 105 | 106 | } 107 | 108 | /*---------------------------------------------------------------------------- 109 | | Returns the result of converting the canonical NaN `a' to the single- 110 | | precision floating-point format. 111 | *----------------------------------------------------------------------------*/ 112 | 113 | static float32 commonNaNToFloat32( commonNaNT a ) 114 | { 115 | 116 | return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 ); 117 | 118 | } 119 | 120 | /*---------------------------------------------------------------------------- 121 | | Takes two single-precision floating-point values `a' and `b', one of which 122 | | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 123 | | signaling NaN, the invalid exception is raised. 124 | *----------------------------------------------------------------------------*/ 125 | 126 | static float32 propagateFloat32NaN( float32 a, float32 b ) 127 | { 128 | flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 129 | 130 | aIsNaN = float32_is_nan( a ); 131 | aIsSignalingNaN = float32_is_signaling_nan( a ); 132 | bIsNaN = float32_is_nan( b ); 133 | bIsSignalingNaN = float32_is_signaling_nan( b ); 134 | a |= 0x00400000; 135 | b |= 0x00400000; 136 | if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 137 | if ( aIsNaN ) { 138 | return ( aIsSignalingNaN & bIsNaN ) ? b : a; 139 | } 140 | else { 141 | return b; 142 | } 143 | 144 | } 145 | 146 | /*---------------------------------------------------------------------------- 147 | | The pattern for a default generated double-precision NaN. 148 | *----------------------------------------------------------------------------*/ 149 | #define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF ) 150 | 151 | /*---------------------------------------------------------------------------- 152 | | Returns 1 if the double-precision floating-point value `a' is a NaN; 153 | | otherwise returns 0. 154 | *----------------------------------------------------------------------------*/ 155 | 156 | flag float64_is_nan( float64 a ) 157 | { 158 | 159 | return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) ); 160 | 161 | } 162 | 163 | /*---------------------------------------------------------------------------- 164 | | Returns 1 if the double-precision floating-point value `a' is a signaling 165 | | NaN; otherwise returns 0. 166 | *----------------------------------------------------------------------------*/ 167 | 168 | flag float64_is_signaling_nan( float64 a ) 169 | { 170 | 171 | return 172 | ( ( ( a>>51 ) & 0xFFF ) == 0xFFE ) 173 | && ( a & LIT64( 0x0007FFFFFFFFFFFF ) ); 174 | 175 | } 176 | 177 | /*---------------------------------------------------------------------------- 178 | | Returns the result of converting the double-precision floating-point NaN 179 | | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 180 | | exception is raised. 181 | *----------------------------------------------------------------------------*/ 182 | 183 | static commonNaNT float64ToCommonNaN( float64 a ) 184 | { 185 | commonNaNT z; 186 | 187 | if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 188 | z.sign = a>>63; 189 | z.low = 0; 190 | z.high = a<<12; 191 | return z; 192 | 193 | } 194 | 195 | /*---------------------------------------------------------------------------- 196 | | Returns the result of converting the canonical NaN `a' to the double- 197 | | precision floating-point format. 198 | *----------------------------------------------------------------------------*/ 199 | 200 | static float64 commonNaNToFloat64( commonNaNT a ) 201 | { 202 | 203 | return 204 | ( ( (bits64) a.sign )<<63 ) 205 | | LIT64( 0x7FF8000000000000 ) 206 | | ( a.high>>12 ); 207 | 208 | } 209 | 210 | /*---------------------------------------------------------------------------- 211 | | Takes two double-precision floating-point values `a' and `b', one of which 212 | | is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a 213 | | signaling NaN, the invalid exception is raised. 214 | *----------------------------------------------------------------------------*/ 215 | 216 | static float64 propagateFloat64NaN( float64 a, float64 b ) 217 | { 218 | flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 219 | 220 | aIsNaN = float64_is_nan( a ); 221 | aIsSignalingNaN = float64_is_signaling_nan( a ); 222 | bIsNaN = float64_is_nan( b ); 223 | bIsSignalingNaN = float64_is_signaling_nan( b ); 224 | a |= LIT64( 0x0008000000000000 ); 225 | b |= LIT64( 0x0008000000000000 ); 226 | if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 227 | if ( aIsNaN ) { 228 | return ( aIsSignalingNaN & bIsNaN ) ? b : a; 229 | } 230 | else { 231 | return b; 232 | } 233 | 234 | } 235 | 236 | #ifdef FLOATX80 237 | 238 | /*---------------------------------------------------------------------------- 239 | | The pattern for a default generated extended double-precision NaN. The 240 | | `high' and `low' values hold the most- and least-significant bits, 241 | | respectively. 242 | *----------------------------------------------------------------------------*/ 243 | #define floatx80_default_nan_high 0xFFFF 244 | #define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 245 | 246 | /*---------------------------------------------------------------------------- 247 | | Returns 1 if the extended double-precision floating-point value `a' is a 248 | | NaN; otherwise returns 0. 249 | *----------------------------------------------------------------------------*/ 250 | 251 | flag floatx80_is_nan( floatx80 a ) 252 | { 253 | 254 | return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 ); 255 | 256 | } 257 | 258 | /*---------------------------------------------------------------------------- 259 | | Returns 1 if the extended double-precision floating-point value `a' is a 260 | | signaling NaN; otherwise returns 0. 261 | *----------------------------------------------------------------------------*/ 262 | 263 | flag floatx80_is_signaling_nan( floatx80 a ) 264 | { 265 | bits64 aLow; 266 | 267 | aLow = a.low & ~ LIT64( 0x4000000000000000 ); 268 | return 269 | ( ( a.high & 0x7FFF ) == 0x7FFF ) 270 | && (bits64) ( aLow<<1 ) 271 | && ( a.low == aLow ); 272 | 273 | } 274 | 275 | /*---------------------------------------------------------------------------- 276 | | Returns the result of converting the extended double-precision floating- 277 | | point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the 278 | | invalid exception is raised. 279 | *----------------------------------------------------------------------------*/ 280 | 281 | static commonNaNT floatx80ToCommonNaN( floatx80 a ) 282 | { 283 | commonNaNT z; 284 | 285 | if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 286 | z.sign = a.high>>15; 287 | z.low = 0; 288 | z.high = a.low<<1; 289 | return z; 290 | 291 | } 292 | 293 | /*---------------------------------------------------------------------------- 294 | | Returns the result of converting the canonical NaN `a' to the extended 295 | | double-precision floating-point format. 296 | *----------------------------------------------------------------------------*/ 297 | 298 | static floatx80 commonNaNToFloatx80( commonNaNT a ) 299 | { 300 | floatx80 z; 301 | 302 | z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 ); 303 | z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF; 304 | return z; 305 | 306 | } 307 | 308 | /*---------------------------------------------------------------------------- 309 | | Takes two extended double-precision floating-point values `a' and `b', one 310 | | of which is a NaN, and returns the appropriate NaN result. If either `a' or 311 | | `b' is a signaling NaN, the invalid exception is raised. 312 | *----------------------------------------------------------------------------*/ 313 | 314 | floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b ) 315 | { 316 | flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 317 | 318 | aIsNaN = floatx80_is_nan( a ); 319 | aIsSignalingNaN = floatx80_is_signaling_nan( a ); 320 | bIsNaN = floatx80_is_nan( b ); 321 | bIsSignalingNaN = floatx80_is_signaling_nan( b ); 322 | a.low |= LIT64( 0xC000000000000000 ); 323 | b.low |= LIT64( 0xC000000000000000 ); 324 | if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 325 | if ( aIsNaN ) { 326 | return ( aIsSignalingNaN & bIsNaN ) ? b : a; 327 | } 328 | else { 329 | return b; 330 | } 331 | 332 | } 333 | 334 | #define EXP_BIAS 0x3FFF 335 | 336 | /*---------------------------------------------------------------------------- 337 | | Returns the fraction bits of the extended double-precision floating-point 338 | | value `a'. 339 | *----------------------------------------------------------------------------*/ 340 | 341 | static inline bits64 extractFloatx80Frac( floatx80 a ) 342 | { 343 | 344 | return a.low; 345 | 346 | } 347 | 348 | /*---------------------------------------------------------------------------- 349 | | Returns the exponent bits of the extended double-precision floating-point 350 | | value `a'. 351 | *----------------------------------------------------------------------------*/ 352 | 353 | static inline int32 extractFloatx80Exp( floatx80 a ) 354 | { 355 | 356 | return a.high & 0x7FFF; 357 | 358 | } 359 | 360 | /*---------------------------------------------------------------------------- 361 | | Returns the sign bit of the extended double-precision floating-point value 362 | | `a'. 363 | *----------------------------------------------------------------------------*/ 364 | 365 | static inline flag extractFloatx80Sign( floatx80 a ) 366 | { 367 | 368 | return a.high>>15; 369 | 370 | } 371 | 372 | #endif 373 | 374 | #ifdef FLOAT128 375 | 376 | /*---------------------------------------------------------------------------- 377 | | The pattern for a default generated quadruple-precision NaN. The `high' and 378 | | `low' values hold the most- and least-significant bits, respectively. 379 | *----------------------------------------------------------------------------*/ 380 | #define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF ) 381 | #define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF ) 382 | 383 | /*---------------------------------------------------------------------------- 384 | | Returns 1 if the quadruple-precision floating-point value `a' is a NaN; 385 | | otherwise returns 0. 386 | *----------------------------------------------------------------------------*/ 387 | 388 | flag float128_is_nan( float128 a ) 389 | { 390 | 391 | return 392 | ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) ) 393 | && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) ); 394 | 395 | } 396 | 397 | /*---------------------------------------------------------------------------- 398 | | Returns 1 if the quadruple-precision floating-point value `a' is a 399 | | signaling NaN; otherwise returns 0. 400 | *----------------------------------------------------------------------------*/ 401 | 402 | flag float128_is_signaling_nan( float128 a ) 403 | { 404 | 405 | return 406 | ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE ) 407 | && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) ); 408 | 409 | } 410 | 411 | /*---------------------------------------------------------------------------- 412 | | Returns the result of converting the quadruple-precision floating-point NaN 413 | | `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid 414 | | exception is raised. 415 | *----------------------------------------------------------------------------*/ 416 | 417 | static commonNaNT float128ToCommonNaN( float128 a ) 418 | { 419 | commonNaNT z; 420 | 421 | if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid ); 422 | z.sign = a.high>>63; 423 | shortShift128Left( a.high, a.low, 16, &z.high, &z.low ); 424 | return z; 425 | 426 | } 427 | 428 | /*---------------------------------------------------------------------------- 429 | | Returns the result of converting the canonical NaN `a' to the quadruple- 430 | | precision floating-point format. 431 | *----------------------------------------------------------------------------*/ 432 | 433 | static float128 commonNaNToFloat128( commonNaNT a ) 434 | { 435 | float128 z; 436 | 437 | shift128Right( a.high, a.low, 16, &z.high, &z.low ); 438 | z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 ); 439 | return z; 440 | 441 | } 442 | 443 | /*---------------------------------------------------------------------------- 444 | | Takes two quadruple-precision floating-point values `a' and `b', one of 445 | | which is a NaN, and returns the appropriate NaN result. If either `a' or 446 | | `b' is a signaling NaN, the invalid exception is raised. 447 | *----------------------------------------------------------------------------*/ 448 | 449 | static float128 propagateFloat128NaN( float128 a, float128 b ) 450 | { 451 | flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN; 452 | 453 | aIsNaN = float128_is_nan( a ); 454 | aIsSignalingNaN = float128_is_signaling_nan( a ); 455 | bIsNaN = float128_is_nan( b ); 456 | bIsSignalingNaN = float128_is_signaling_nan( b ); 457 | a.high |= LIT64( 0x0000800000000000 ); 458 | b.high |= LIT64( 0x0000800000000000 ); 459 | if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid ); 460 | if ( aIsNaN ) { 461 | return ( aIsSignalingNaN & bIsNaN ) ? b : a; 462 | } 463 | else { 464 | return b; 465 | } 466 | 467 | } 468 | 469 | #endif 470 | 471 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/softfloat/softfloat.h: -------------------------------------------------------------------------------- 1 | 2 | /*============================================================================ 3 | 4 | This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic 5 | Package, Release 2b. 6 | 7 | Written by John R. Hauser. This work was made possible in part by the 8 | International Computer Science Institute, located at Suite 600, 1947 Center 9 | Street, Berkeley, California 94704. Funding was partially provided by the 10 | National Science Foundation under grant MIP-9311980. The original version 11 | of this code was written as part of a project to build a fixed-point vector 12 | processor in collaboration with the University of California at Berkeley, 13 | overseen by Profs. Nelson Morgan and John Wawrzynek. More information 14 | is available through the Web page `http://www.cs.berkeley.edu/~jhauser/ 15 | arithmetic/SoftFloat.html'. 16 | 17 | THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has 18 | been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES 19 | RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS 20 | AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES, 21 | COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE 22 | EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE 23 | INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR 24 | OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE. 25 | 26 | Derivative works are acceptable, even for commercial purposes, so long as 27 | (1) the source code for the derivative work includes prominent notice that 28 | the work is derivative, and (2) the source code includes prominent notice with 29 | these four paragraphs for those parts of this code that are retained. 30 | 31 | =============================================================================*/ 32 | 33 | /*---------------------------------------------------------------------------- 34 | | The macro `FLOATX80' must be defined to enable the extended double-precision 35 | | floating-point format `floatx80'. If this macro is not defined, the 36 | | `floatx80' type will not be defined, and none of the functions that either 37 | | input or output the `floatx80' type will be defined. The same applies to 38 | | the `FLOAT128' macro and the quadruple-precision format `float128'. 39 | *----------------------------------------------------------------------------*/ 40 | #define FLOATX80 41 | #define FLOAT128 42 | 43 | /*---------------------------------------------------------------------------- 44 | | Software IEC/IEEE floating-point types. 45 | *----------------------------------------------------------------------------*/ 46 | typedef bits32 float32; 47 | typedef bits64 float64; 48 | #ifdef FLOATX80 49 | typedef struct { 50 | bits16 high; 51 | bits64 low; 52 | } floatx80; 53 | #endif 54 | #ifdef FLOAT128 55 | typedef struct { 56 | bits64 high, low; 57 | } float128; 58 | #endif 59 | 60 | /*---------------------------------------------------------------------------- 61 | | Primitive arithmetic functions, including multi-word arithmetic, and 62 | | division and square root approximations. (Can be specialized to target if 63 | | desired.) 64 | *----------------------------------------------------------------------------*/ 65 | #include "softfloat-macros" 66 | 67 | /*---------------------------------------------------------------------------- 68 | | Software IEC/IEEE floating-point underflow tininess-detection mode. 69 | *----------------------------------------------------------------------------*/ 70 | extern int8 float_detect_tininess; 71 | enum { 72 | float_tininess_after_rounding = 0, 73 | float_tininess_before_rounding = 1 74 | }; 75 | 76 | /*---------------------------------------------------------------------------- 77 | | Software IEC/IEEE floating-point rounding mode. 78 | *----------------------------------------------------------------------------*/ 79 | extern int8 float_rounding_mode; 80 | enum { 81 | float_round_nearest_even = 0, 82 | float_round_to_zero = 1, 83 | float_round_down = 2, 84 | float_round_up = 3 85 | }; 86 | 87 | /*---------------------------------------------------------------------------- 88 | | Software IEC/IEEE floating-point exception flags. 89 | *----------------------------------------------------------------------------*/ 90 | extern int8 float_exception_flags; 91 | enum { 92 | float_flag_invalid = 0x01, float_flag_denormal = 0x02, float_flag_divbyzero = 0x04, float_flag_overflow = 0x08, 93 | float_flag_underflow = 0x10, float_flag_inexact = 0x20 94 | }; 95 | 96 | /*---------------------------------------------------------------------------- 97 | | Routine to raise any or all of the software IEC/IEEE floating-point 98 | | exception flags. 99 | *----------------------------------------------------------------------------*/ 100 | void float_raise( int8 ); 101 | 102 | /*---------------------------------------------------------------------------- 103 | | Software IEC/IEEE integer-to-floating-point conversion routines. 104 | *----------------------------------------------------------------------------*/ 105 | float32 int32_to_float32( int32 ); 106 | float64 int32_to_float64( int32 ); 107 | #ifdef FLOATX80 108 | floatx80 int32_to_floatx80( int32 ); 109 | #endif 110 | #ifdef FLOAT128 111 | float128 int32_to_float128( int32 ); 112 | #endif 113 | float32 int64_to_float32( int64 ); 114 | float64 int64_to_float64( int64 ); 115 | #ifdef FLOATX80 116 | floatx80 int64_to_floatx80( int64 ); 117 | #endif 118 | #ifdef FLOAT128 119 | float128 int64_to_float128( int64 ); 120 | #endif 121 | 122 | /*---------------------------------------------------------------------------- 123 | | Software IEC/IEEE single-precision conversion routines. 124 | *----------------------------------------------------------------------------*/ 125 | int32 float32_to_int32( float32 ); 126 | int32 float32_to_int32_round_to_zero( float32 ); 127 | int64 float32_to_int64( float32 ); 128 | int64 float32_to_int64_round_to_zero( float32 ); 129 | float64 float32_to_float64( float32 ); 130 | #ifdef FLOATX80 131 | floatx80 float32_to_floatx80( float32 ); 132 | #endif 133 | #ifdef FLOAT128 134 | float128 float32_to_float128( float32 ); 135 | #endif 136 | 137 | /*---------------------------------------------------------------------------- 138 | | Software IEC/IEEE single-precision operations. 139 | *----------------------------------------------------------------------------*/ 140 | float32 float32_round_to_int( float32 ); 141 | float32 float32_add( float32, float32 ); 142 | float32 float32_sub( float32, float32 ); 143 | float32 float32_mul( float32, float32 ); 144 | float32 float32_div( float32, float32 ); 145 | float32 float32_rem( float32, float32 ); 146 | float32 float32_sqrt( float32 ); 147 | flag float32_eq( float32, float32 ); 148 | flag float32_le( float32, float32 ); 149 | flag float32_lt( float32, float32 ); 150 | flag float32_eq_signaling( float32, float32 ); 151 | flag float32_le_quiet( float32, float32 ); 152 | flag float32_lt_quiet( float32, float32 ); 153 | flag float32_is_signaling_nan( float32 ); 154 | 155 | /*---------------------------------------------------------------------------- 156 | | Software IEC/IEEE double-precision conversion routines. 157 | *----------------------------------------------------------------------------*/ 158 | int32 float64_to_int32( float64 ); 159 | int32 float64_to_int32_round_to_zero( float64 ); 160 | int64 float64_to_int64( float64 ); 161 | int64 float64_to_int64_round_to_zero( float64 ); 162 | float32 float64_to_float32( float64 ); 163 | #ifdef FLOATX80 164 | floatx80 float64_to_floatx80( float64 ); 165 | #endif 166 | #ifdef FLOAT128 167 | float128 float64_to_float128( float64 ); 168 | #endif 169 | 170 | /*---------------------------------------------------------------------------- 171 | | Software IEC/IEEE double-precision operations. 172 | *----------------------------------------------------------------------------*/ 173 | float64 float64_round_to_int( float64 ); 174 | float64 float64_add( float64, float64 ); 175 | float64 float64_sub( float64, float64 ); 176 | float64 float64_mul( float64, float64 ); 177 | float64 float64_div( float64, float64 ); 178 | float64 float64_rem( float64, float64 ); 179 | float64 float64_sqrt( float64 ); 180 | flag float64_eq( float64, float64 ); 181 | flag float64_le( float64, float64 ); 182 | flag float64_lt( float64, float64 ); 183 | flag float64_eq_signaling( float64, float64 ); 184 | flag float64_le_quiet( float64, float64 ); 185 | flag float64_lt_quiet( float64, float64 ); 186 | flag float64_is_signaling_nan( float64 ); 187 | 188 | #ifdef FLOATX80 189 | 190 | /*---------------------------------------------------------------------------- 191 | | Software IEC/IEEE extended double-precision conversion routines. 192 | *----------------------------------------------------------------------------*/ 193 | int32 floatx80_to_int32( floatx80 ); 194 | int32 floatx80_to_int32_round_to_zero( floatx80 ); 195 | int64 floatx80_to_int64( floatx80 ); 196 | int64 floatx80_to_int64_round_to_zero( floatx80 ); 197 | float32 floatx80_to_float32( floatx80 ); 198 | float64 floatx80_to_float64( floatx80 ); 199 | #ifdef FLOAT128 200 | float128 floatx80_to_float128( floatx80 ); 201 | #endif 202 | floatx80 floatx80_scale(floatx80 a, floatx80 b); 203 | 204 | /*---------------------------------------------------------------------------- 205 | | Packs the sign `zSign', exponent `zExp', and significand `zSig' into an 206 | | extended double-precision floating-point value, returning the result. 207 | *----------------------------------------------------------------------------*/ 208 | 209 | static inline floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig ) 210 | { 211 | floatx80 z; 212 | 213 | z.low = zSig; 214 | z.high = ( ( (bits16) zSign )<<15 ) + zExp; 215 | return z; 216 | 217 | } 218 | 219 | /*---------------------------------------------------------------------------- 220 | | Software IEC/IEEE extended double-precision rounding precision. Valid 221 | | values are 32, 64, and 80. 222 | *----------------------------------------------------------------------------*/ 223 | extern int8 floatx80_rounding_precision; 224 | 225 | /*---------------------------------------------------------------------------- 226 | | Software IEC/IEEE extended double-precision operations. 227 | *----------------------------------------------------------------------------*/ 228 | floatx80 floatx80_round_to_int( floatx80 ); 229 | floatx80 floatx80_add( floatx80, floatx80 ); 230 | floatx80 floatx80_sub( floatx80, floatx80 ); 231 | floatx80 floatx80_mul( floatx80, floatx80 ); 232 | floatx80 floatx80_div( floatx80, floatx80 ); 233 | floatx80 floatx80_rem( floatx80, floatx80 ); 234 | floatx80 floatx80_sqrt( floatx80 ); 235 | flag floatx80_eq( floatx80, floatx80 ); 236 | flag floatx80_le( floatx80, floatx80 ); 237 | flag floatx80_lt( floatx80, floatx80 ); 238 | flag floatx80_eq_signaling( floatx80, floatx80 ); 239 | flag floatx80_le_quiet( floatx80, floatx80 ); 240 | flag floatx80_lt_quiet( floatx80, floatx80 ); 241 | flag floatx80_is_signaling_nan( floatx80 ); 242 | 243 | /* int floatx80_fsin(floatx80 &a); 244 | int floatx80_fcos(floatx80 &a); 245 | int floatx80_ftan(floatx80 &a); */ 246 | 247 | floatx80 floatx80_flognp1(floatx80 a); 248 | floatx80 floatx80_flogn(floatx80 a); 249 | floatx80 floatx80_flog2(floatx80 a); 250 | floatx80 floatx80_flog10(floatx80 a); 251 | 252 | // roundAndPackFloatx80 used to be in softfloat-round-pack, is now in softfloat.c 253 | floatx80 roundAndPackFloatx80(int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1); 254 | 255 | #endif 256 | 257 | #ifdef FLOAT128 258 | 259 | /*---------------------------------------------------------------------------- 260 | | Software IEC/IEEE quadruple-precision conversion routines. 261 | *----------------------------------------------------------------------------*/ 262 | int32 float128_to_int32( float128 ); 263 | int32 float128_to_int32_round_to_zero( float128 ); 264 | int64 float128_to_int64( float128 ); 265 | int64 float128_to_int64_round_to_zero( float128 ); 266 | float32 float128_to_float32( float128 ); 267 | float64 float128_to_float64( float128 ); 268 | #ifdef FLOATX80 269 | floatx80 float128_to_floatx80( float128 ); 270 | #endif 271 | 272 | /*---------------------------------------------------------------------------- 273 | | Software IEC/IEEE quadruple-precision operations. 274 | *----------------------------------------------------------------------------*/ 275 | float128 float128_round_to_int( float128 ); 276 | float128 float128_add( float128, float128 ); 277 | float128 float128_sub( float128, float128 ); 278 | float128 float128_mul( float128, float128 ); 279 | float128 float128_div( float128, float128 ); 280 | float128 float128_rem( float128, float128 ); 281 | float128 float128_sqrt( float128 ); 282 | flag float128_eq( float128, float128 ); 283 | flag float128_le( float128, float128 ); 284 | flag float128_lt( float128, float128 ); 285 | flag float128_eq_signaling( float128, float128 ); 286 | flag float128_le_quiet( float128, float128 ); 287 | flag float128_lt_quiet( float128, float128 ); 288 | flag float128_is_signaling_nan( float128 ); 289 | 290 | /*---------------------------------------------------------------------------- 291 | | Packs the sign `zSign', the exponent `zExp', and the significand formed 292 | | by the concatenation of `zSig0' and `zSig1' into a quadruple-precision 293 | | floating-point value, returning the result. After being shifted into the 294 | | proper positions, the three fields `zSign', `zExp', and `zSig0' are simply 295 | | added together to form the most significant 32 bits of the result. This 296 | | means that any integer portion of `zSig0' will be added into the exponent. 297 | | Since a properly normalized significand will have an integer portion equal 298 | | to 1, the `zExp' input should be 1 less than the desired result exponent 299 | | whenever `zSig0' and `zSig1' concatenated form a complete, normalized 300 | | significand. 301 | *----------------------------------------------------------------------------*/ 302 | 303 | static inline float128 304 | packFloat128( flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) 305 | { 306 | float128 z; 307 | 308 | z.low = zSig1; 309 | z.high = ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<48 ) + zSig0; 310 | return z; 311 | 312 | } 313 | 314 | /*---------------------------------------------------------------------------- 315 | | Takes an abstract floating-point value having sign `zSign', exponent `zExp', 316 | | and extended significand formed by the concatenation of `zSig0', `zSig1', 317 | | and `zSig2', and returns the proper quadruple-precision floating-point value 318 | | corresponding to the abstract input. Ordinarily, the abstract value is 319 | | simply rounded and packed into the quadruple-precision format, with the 320 | | inexact exception raised if the abstract input cannot be represented 321 | | exactly. However, if the abstract value is too large, the overflow and 322 | | inexact exceptions are raised and an infinity or maximal finite value is 323 | | returned. If the abstract value is too small, the input value is rounded to 324 | | a subnormal number, and the underflow and inexact exceptions are raised if 325 | | the abstract input cannot be represented exactly as a subnormal quadruple- 326 | | precision floating-point number. 327 | | The input significand must be normalized or smaller. If the input 328 | | significand is not normalized, `zExp' must be 0; in that case, the result 329 | | returned is a subnormal number, and it must not require rounding. In the 330 | | usual case that the input significand is normalized, `zExp' must be 1 less 331 | | than the ``true'' floating-point exponent. The handling of underflow and 332 | | overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic. 333 | *----------------------------------------------------------------------------*/ 334 | 335 | static inline float128 336 | roundAndPackFloat128( 337 | flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1, bits64 zSig2 ) 338 | { 339 | int8 roundingMode; 340 | flag roundNearestEven, increment, isTiny; 341 | 342 | roundingMode = float_rounding_mode; 343 | roundNearestEven = ( roundingMode == float_round_nearest_even ); 344 | increment = ( (sbits64) zSig2 < 0 ); 345 | if ( ! roundNearestEven ) { 346 | if ( roundingMode == float_round_to_zero ) { 347 | increment = 0; 348 | } 349 | else { 350 | if ( zSign ) { 351 | increment = ( roundingMode == float_round_down ) && zSig2; 352 | } 353 | else { 354 | increment = ( roundingMode == float_round_up ) && zSig2; 355 | } 356 | } 357 | } 358 | if ( 0x7FFD <= (bits32) zExp ) { 359 | if ( ( 0x7FFD < zExp ) 360 | || ( ( zExp == 0x7FFD ) 361 | && eq128( 362 | LIT64( 0x0001FFFFFFFFFFFF ), 363 | LIT64( 0xFFFFFFFFFFFFFFFF ), 364 | zSig0, 365 | zSig1 366 | ) 367 | && increment 368 | ) 369 | ) { 370 | float_raise( float_flag_overflow | float_flag_inexact ); 371 | if ( ( roundingMode == float_round_to_zero ) 372 | || ( zSign && ( roundingMode == float_round_up ) ) 373 | || ( ! zSign && ( roundingMode == float_round_down ) ) 374 | ) { 375 | return 376 | packFloat128( 377 | zSign, 378 | 0x7FFE, 379 | LIT64( 0x0000FFFFFFFFFFFF ), 380 | LIT64( 0xFFFFFFFFFFFFFFFF ) 381 | ); 382 | } 383 | return packFloat128( zSign, 0x7FFF, 0, 0 ); 384 | } 385 | if ( zExp < 0 ) { 386 | isTiny = 387 | ( float_detect_tininess == float_tininess_before_rounding ) 388 | || ( zExp < -1 ) 389 | || ! increment 390 | || lt128( 391 | zSig0, 392 | zSig1, 393 | LIT64( 0x0001FFFFFFFFFFFF ), 394 | LIT64( 0xFFFFFFFFFFFFFFFF ) 395 | ); 396 | shift128ExtraRightJamming( 397 | zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 ); 398 | zExp = 0; 399 | if ( isTiny && zSig2 ) float_raise( float_flag_underflow ); 400 | if ( roundNearestEven ) { 401 | increment = ( (sbits64) zSig2 < 0 ); 402 | } 403 | else { 404 | if ( zSign ) { 405 | increment = ( roundingMode == float_round_down ) && zSig2; 406 | } 407 | else { 408 | increment = ( roundingMode == float_round_up ) && zSig2; 409 | } 410 | } 411 | } 412 | } 413 | if ( zSig2 ) float_exception_flags |= float_flag_inexact; 414 | if ( increment ) { 415 | add128( zSig0, zSig1, 0, 1, &zSig0, &zSig1 ); 416 | zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven ); 417 | } 418 | else { 419 | if ( ( zSig0 | zSig1 ) == 0 ) zExp = 0; 420 | } 421 | return packFloat128( zSign, zExp, zSig0, zSig1 ); 422 | 423 | } 424 | 425 | /*---------------------------------------------------------------------------- 426 | | Takes an abstract floating-point value having sign `zSign', exponent `zExp', 427 | | and significand formed by the concatenation of `zSig0' and `zSig1', and 428 | | returns the proper quadruple-precision floating-point value corresponding 429 | | to the abstract input. This routine is just like `roundAndPackFloat128' 430 | | except that the input significand has fewer bits and does not have to be 431 | | normalized. In all cases, `zExp' must be 1 less than the ``true'' floating- 432 | | point exponent. 433 | *----------------------------------------------------------------------------*/ 434 | 435 | static inline float128 436 | normalizeRoundAndPackFloat128( 437 | flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 ) 438 | { 439 | int8 shiftCount; 440 | bits64 zSig2; 441 | 442 | if ( zSig0 == 0 ) { 443 | zSig0 = zSig1; 444 | zSig1 = 0; 445 | zExp -= 64; 446 | } 447 | shiftCount = countLeadingZeros64( zSig0 ) - 15; 448 | if ( 0 <= shiftCount ) { 449 | zSig2 = 0; 450 | shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 ); 451 | } 452 | else { 453 | shift128ExtraRightJamming( 454 | zSig0, zSig1, 0, - shiftCount, &zSig0, &zSig1, &zSig2 ); 455 | } 456 | zExp -= shiftCount; 457 | return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 ); 458 | 459 | } 460 | #endif 461 | -------------------------------------------------------------------------------- /GCC/VC4_PSPROTO/pistorm/software/softfloat/softfloat.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/captain-amygdala/VPU-example/577057b56d3f64027cb021fb86807f3d25beeee6/GCC/VC4_PSPROTO/pistorm/software/softfloat/softfloat.o -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | C = main.c mailbox.c 2 | H = mailbox.h 3 | 4 | F = -lrt -lm -ldl 5 | 6 | all: vcrun code 7 | 8 | vcrun: $(C) $(H) 9 | gcc -o vcrun $(F) $(C) $(H) 10 | 11 | code: 12 | ./vasmvidcore -Fbin -o code.bin code.asm 13 | clean: 14 | rm -f vcrun 15 | rm -f code.bin 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VPU-example 2 | Simple example for running code on VPU from Linux 3 | 4 | Toggling GPIO2 on a Raspberry Pi, see code.asm 5 | 6 | Based on https://github.com/ali1234/vcpoke/ 7 | 8 | VASM is avaible at http://sun.hasenbraten.de/vasm/ 9 | 10 | -------------------------------------------------------------------------------- /code.asm: -------------------------------------------------------------------------------- 1 | .equ GPIO, 2 2 | .equ GPSEL, 0x7E200000 + (GPIO/10)*4 3 | .equ GPSET, 0x7E20001C + (GPIO>>5)*4 4 | .equ GPCLR, 0x7E200028 + (GPIO>>5)*4 5 | 6 | 7 | mov r1, GPSEL 8 | 9 | ld r0, (r1) 10 | and r0, ~(0b111<<((GPIO%10)*3)) #set our GPIO as output 11 | or r0, 1<<((GPIO%10)*3) 12 | st r0, (r1) 13 | 14 | mov r1, GPSET 15 | mov r2, GPCLR 16 | mov r3, 1<<(GPIO%32) #our GPIO's bit 17 | 18 | st r3, (r2) #low 19 | st r3, (r1) #high 20 | st r3, (r2) #low 21 | st r3, (r1) #high 22 | st r3, (r2) #low 23 | st r3, (r1) #high 24 | st r3, (r2) #low 25 | st r3, (r1) #high 26 | st r3, (r2) #low 27 | st r3, (r1) #high 28 | st r3, (r2) #low 29 | st r3, (r1) #high 30 | st r3, (r2) #low 31 | st r3, (r1) #high 32 | st r3, (r2) #low 33 | st r3, (r1) #high 34 | st r3, (r2) #low 35 | st r3, (r1) #high 36 | st r3, (r2) #low 37 | st r3, (r1) #high 38 | st r3, (r2) #low 39 | st r3, (r1) #high 40 | st r3, (r2) #low 41 | st r3, (r1) #high 42 | st r3, (r2) #low 43 | st r3, (r1) #high 44 | st r3, (r2) #low 45 | st r3, (r1) #high 46 | st r3, (r2) #low 47 | st r3, (r1) #high 48 | st r3, (r2) #low 49 | st r3, (r1) #high 50 | st r3, (r2) #low 51 | st r3, (r1) #high 52 | st r3, (r2) #low 53 | st r3, (r1) #high 54 | st r3, (r2) #low 55 | st r3, (r1) #high 56 | st r3, (r2) #low 57 | st r3, (r1) #high 58 | rts 59 | -------------------------------------------------------------------------------- /code.asm.poke: -------------------------------------------------------------------------------- 1 | ld r0,(r0) 2 | rts 3 | st r1,(r0) 4 | rts 5 | -------------------------------------------------------------------------------- /mailbox.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012, Broadcom Europe Ltd. 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are met: 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of the copyright holder nor the 13 | names of its contributors may be used to endorse or promote products 14 | derived from this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY 20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include "mailbox.h" 39 | 40 | #define PAGE_SIZE (4*1024) 41 | 42 | void *mapmem(unsigned base, unsigned size) 43 | { 44 | int mem_fd; 45 | unsigned offset = base % PAGE_SIZE; 46 | base = base - offset; 47 | size = size + offset; 48 | /* open /dev/mem */ 49 | if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) { 50 | printf("can't open /dev/mem\nThis program should be run as root. Try prefixing command with: sudo\n"); 51 | exit (-1); 52 | } 53 | void *mem = mmap( 54 | 0, 55 | size, 56 | PROT_READ|PROT_WRITE, 57 | MAP_SHARED/*|MAP_FIXED*/, 58 | mem_fd, 59 | base); 60 | #ifdef DEBUG 61 | printf("base=0x%x, mem=%p\n", base, mem); 62 | #endif 63 | if (mem == MAP_FAILED) { 64 | printf("mmap error %d\n", (int)mem); 65 | exit (-1); 66 | } 67 | close(mem_fd); 68 | return (char *)mem + offset; 69 | } 70 | 71 | void unmapmem(void *addr, unsigned size) 72 | { 73 | unsigned offset = (unsigned)addr % PAGE_SIZE; 74 | addr = (char *)addr - offset; 75 | size = size + offset; 76 | int s = munmap(addr, size); 77 | if (s != 0) { 78 | printf("munmap error %d\n", s); 79 | exit (-1); 80 | } 81 | } 82 | 83 | /* 84 | * use ioctl to send mbox property message 85 | */ 86 | 87 | static int mbox_property(int file_desc, void *buf) 88 | { 89 | int ret_val = ioctl(file_desc, IOCTL_MBOX_PROPERTY, buf); 90 | 91 | if (ret_val < 0) { 92 | printf("ioctl_set_msg failed:%d\n", ret_val); 93 | } 94 | 95 | #ifdef DEBUG 96 | unsigned *p = buf; int i; unsigned size = *(unsigned *)buf; 97 | for (i=0; i 29 | 30 | #define MAJOR_NUM 100 31 | #define IOCTL_MBOX_PROPERTY _IOWR(MAJOR_NUM, 0, char *) 32 | #define DEVICE_FILE_NAME "/dev/vcio" 33 | 34 | int mbox_open(); 35 | void mbox_close(int file_desc); 36 | 37 | unsigned get_version(int file_desc); 38 | unsigned mem_alloc(int file_desc, unsigned size, unsigned align, unsigned flags); 39 | unsigned mem_free(int file_desc, unsigned handle); 40 | unsigned mem_lock(int file_desc, unsigned handle); 41 | unsigned mem_unlock(int file_desc, unsigned handle); 42 | void *mapmem(unsigned base, unsigned size); 43 | void unmapmem(void *addr, unsigned size); 44 | 45 | unsigned execute_code(int file_desc, unsigned code, unsigned r0, unsigned r1, unsigned r2, unsigned r3, unsigned r4, unsigned r5); 46 | unsigned execute_qpu(int file_desc, unsigned num_qpus, unsigned control, unsigned noflush, unsigned timeout); 47 | unsigned qpu_enable(int file_desc, unsigned enable); 48 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "mailbox.h" 13 | 14 | 15 | #define BUS_TO_PHYS(x) ((x)&~0xC0000000) 16 | 17 | #define CODESIZE 1024 18 | 19 | int mbox; 20 | unsigned handle; 21 | unsigned ptr; 22 | uint8_t *program; 23 | 24 | 25 | void setup() { 26 | mbox = mbox_open(); 27 | handle = mem_alloc(mbox, CODESIZE, 8, 4); 28 | ptr = mem_lock(mbox, handle); 29 | program = mapmem(BUS_TO_PHYS(ptr), CODESIZE); 30 | 31 | int fd = 0; 32 | fd = open("code.bin", O_RDONLY); 33 | if (fd < 1) { 34 | printf("Failed loading code.bin\n"); 35 | exit(0); 36 | } else { 37 | int size = (int)lseek(fd, 0, SEEK_END); 38 | if (size > CODESIZE){ 39 | printf("VPU binary exceeds maximum codesize\n"); 40 | exit(0); 41 | } 42 | lseek(fd, 0, SEEK_SET); 43 | read(fd, program, size); 44 | printf("Loaded code.bin with size %d byte\n", size); 45 | } 46 | 47 | } 48 | 49 | 50 | void cleanup() { 51 | unmapmem(program, 64); 52 | mem_unlock(mbox, handle); 53 | mem_free(mbox, handle); 54 | mbox_close(mbox); 55 | } 56 | 57 | 58 | unsigned readmem(unsigned phys) { 59 | return execute_code(mbox, ptr, phys, 0, 0, 0, 0, 0); 60 | } 61 | 62 | 63 | void writemem(unsigned phys, unsigned value) { 64 | execute_code(mbox, ptr+4, phys, value, 0, 0, 0, 0); 65 | } 66 | 67 | 68 | int main(int argc, char *argv[]) { 69 | setup(); 70 | printf("Start VPU code\n"); 71 | printf("Returnvalue R0 = 0x%08x\n", execute_code(mbox, ptr, 0, 0, 0, 0, 0, 0)); 72 | cleanup(); 73 | 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /vasmvidcore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/captain-amygdala/VPU-example/577057b56d3f64027cb021fb86807f3d25beeee6/vasmvidcore --------------------------------------------------------------------------------