add missing files not taken with github import
This commit is contained in:
479
util/bas_printf.c
Normal file
479
util/bas_printf.c
Normal file
@@ -0,0 +1,479 @@
|
||||
/*
|
||||
* tc.printf.c: A public-domain, minimal printf/sprintf routine that prints
|
||||
* through the putchar() routine. Feel free to use for
|
||||
* anything... -- 7/17/87 Paul Placeway
|
||||
*/
|
||||
/*-
|
||||
* Copyright (c) 1980, 1991 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include "MCF5475.h"
|
||||
#include "bas_printf.h"
|
||||
#include "bas_string.h"
|
||||
|
||||
/*
|
||||
* Lexical definitions.
|
||||
*
|
||||
* All lexical space is allocated dynamically.
|
||||
* The eighth/sixteenth bit of characters is used to prevent recognition,
|
||||
* and eventually stripped.
|
||||
*/
|
||||
#define META 0200
|
||||
#define ASCII 0177
|
||||
#define QUOTE ((char) 0200) /* Eighth char bit used for 'ing */
|
||||
#define TRIM 0177 /* Mask to strip quote bit */
|
||||
#define UNDER 0000000 /* No extra bits to do both */
|
||||
#define BOLD 0000000 /* Bold flag */
|
||||
#define STANDOUT META /* Standout flag */
|
||||
#define LITERAL 0000000 /* Literal character flag */
|
||||
#define ATTRIBUTES 0200 /* The bits used for attributes */
|
||||
#define CHAR 0000177 /* Mask to mask out the character */
|
||||
|
||||
#define INF 32766 /* should be bigger than any field to print */
|
||||
|
||||
static char snil[] = "(nil)";
|
||||
|
||||
bool conoutstat(void)
|
||||
{
|
||||
bool stat;
|
||||
|
||||
stat = MCF_PSC0_PSCSR & MCF_PSC_PSCSR_TXRDY; /* TX FIFO can take data */
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
bool coninstat(void)
|
||||
{
|
||||
bool stat;
|
||||
|
||||
stat = MCF_PSC0_PSCSR & MCF_PSC_PSCSR_RXRDY; /* RX FIFO has data available */
|
||||
|
||||
return stat;
|
||||
}
|
||||
|
||||
void xputchar(int c)
|
||||
{
|
||||
do { ; } while (!conoutstat());
|
||||
MCF_PSC_PSCRB_8BIT(0) = (char) c;
|
||||
}
|
||||
|
||||
char xgetchar(void)
|
||||
{
|
||||
char c;
|
||||
|
||||
do { ; } while (!coninstat());
|
||||
c = MCF_PSC_PSCTB_8BIT(0);
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static void doprnt(void (*addchar)(int), const char *sfmt, va_list ap)
|
||||
{
|
||||
char buf[128];
|
||||
char *bp;
|
||||
const char *f;
|
||||
float flt;
|
||||
long l;
|
||||
unsigned long u;
|
||||
int i;
|
||||
int fmt;
|
||||
unsigned char pad = ' ';
|
||||
int flush_left = 0;
|
||||
int f_width = 0;
|
||||
int prec = INF;
|
||||
int hash = 0;
|
||||
int do_long = 0;
|
||||
int sign = 0;
|
||||
int attributes = 0;
|
||||
|
||||
f = sfmt;
|
||||
for (; *f; f++)
|
||||
{
|
||||
if (*f != '%')
|
||||
{
|
||||
/* then just out the char */
|
||||
(*addchar)((int) (((unsigned char) *f) | attributes));
|
||||
}
|
||||
else
|
||||
{
|
||||
f++; /* skip the % */
|
||||
|
||||
if (*f == '-')
|
||||
{ /* minus: flush left */
|
||||
flush_left = 1;
|
||||
f++;
|
||||
}
|
||||
|
||||
if (*f == '0' || *f == '.')
|
||||
{
|
||||
/* padding with 0 rather than blank */
|
||||
pad = '0';
|
||||
f++;
|
||||
}
|
||||
if (*f == '*')
|
||||
{
|
||||
/* field width */
|
||||
f_width = va_arg(ap, int);
|
||||
f++;
|
||||
}
|
||||
else if (isdigit((unsigned char)*f))
|
||||
{
|
||||
f_width = atoi(f);
|
||||
while (isdigit((unsigned char)*f))
|
||||
f++; /* skip the digits */
|
||||
}
|
||||
|
||||
if (*f == '.')
|
||||
{ /* precision */
|
||||
f++;
|
||||
if (*f == '*')
|
||||
{
|
||||
prec = va_arg(ap, int);
|
||||
f++;
|
||||
}
|
||||
else if (isdigit((unsigned char)*f))
|
||||
{
|
||||
prec = atoi(f);
|
||||
while (isdigit((unsigned char)*f))
|
||||
f++; /* skip the digits */
|
||||
}
|
||||
}
|
||||
|
||||
if (*f == '#')
|
||||
{ /* alternate form */
|
||||
hash = 1;
|
||||
f++;
|
||||
}
|
||||
|
||||
if (*f == 'l')
|
||||
{ /* long format */
|
||||
do_long++;
|
||||
f++;
|
||||
if (*f == 'l')
|
||||
{
|
||||
do_long++;
|
||||
f++;
|
||||
}
|
||||
}
|
||||
|
||||
fmt = (unsigned char) *f;
|
||||
if (fmt != 'S' && fmt != 'Q' && isupper(fmt))
|
||||
{
|
||||
do_long = 1;
|
||||
fmt = tolower(fmt);
|
||||
}
|
||||
bp = buf;
|
||||
switch (fmt)
|
||||
{ /* do the format */
|
||||
case 'd':
|
||||
switch (do_long)
|
||||
{
|
||||
case 0:
|
||||
l = (long) (va_arg(ap, int));
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
l = va_arg(ap, long);
|
||||
break;
|
||||
}
|
||||
|
||||
if (l < 0)
|
||||
{
|
||||
sign = 1;
|
||||
l = -l;
|
||||
}
|
||||
do
|
||||
{
|
||||
*bp++ = (char) (l % 10) + '0';
|
||||
} while ((l /= 10) > 0);
|
||||
if (sign)
|
||||
*bp++ = '-';
|
||||
f_width = f_width - (int) (bp - buf);
|
||||
if (!flush_left)
|
||||
while (f_width-- > 0)
|
||||
(*addchar)((int) (pad | attributes));
|
||||
for (bp--; bp >= buf; bp--)
|
||||
(*addchar)((int) (((unsigned char) *bp) | attributes));
|
||||
if (flush_left)
|
||||
while (f_width-- > 0)
|
||||
(*addchar)((int) (' ' | attributes));
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
/* this is actually more than stupid, but does work for now */
|
||||
flt = (float) (va_arg(ap, double)); /* beware: va_arg() extends float to double! */
|
||||
if (flt < 0)
|
||||
{
|
||||
sign = 1;
|
||||
flt = -flt;
|
||||
}
|
||||
{
|
||||
int quotient, remainder;
|
||||
|
||||
quotient = (int) flt;
|
||||
remainder = (flt - quotient) * 10E5;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
*bp++ = (char) (remainder % 10) + '0';
|
||||
remainder /= 10;
|
||||
}
|
||||
*bp++ = '.';
|
||||
do
|
||||
{
|
||||
*bp++ = (char) (quotient % 10) + '0';
|
||||
} while ((quotient /= 10) > 0);
|
||||
if (sign)
|
||||
*bp++ = '-';
|
||||
f_width = f_width - (int) (bp - buf);
|
||||
if (!flush_left)
|
||||
while (f_width-- > 0)
|
||||
(*addchar)((int) (pad | attributes));
|
||||
for (bp--; bp >= buf; bp--)
|
||||
(*addchar)((int) (((unsigned char) *bp) | attributes));
|
||||
if (flush_left)
|
||||
while (f_width-- > 0)
|
||||
(*addchar)((int) (' ' | attributes));
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
do_long = 1;
|
||||
hash = 1;
|
||||
fmt = 'x';
|
||||
/* no break */
|
||||
case 'o':
|
||||
case 'x':
|
||||
case 'u':
|
||||
switch (do_long)
|
||||
{
|
||||
case 0:
|
||||
u = (unsigned long) (va_arg(ap, unsigned int));
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
u = va_arg(ap, unsigned long);
|
||||
break;
|
||||
}
|
||||
if (fmt == 'u')
|
||||
{ /* unsigned decimal */
|
||||
do
|
||||
{
|
||||
*bp++ = (char) (u % 10) + '0';
|
||||
} while ((u /= 10) > 0);
|
||||
}
|
||||
else if (fmt == 'o')
|
||||
{ /* octal */
|
||||
do
|
||||
{
|
||||
*bp++ = (char) (u % 8) + '0';
|
||||
} while ((u /= 8) > 0);
|
||||
if (hash)
|
||||
*bp++ = '0';
|
||||
}
|
||||
else if (fmt == 'x')
|
||||
{ /* hex */
|
||||
do
|
||||
{
|
||||
i = (int) (u % 16);
|
||||
if (i < 10)
|
||||
*bp++ = i + '0';
|
||||
else
|
||||
*bp++ = i - 10 + 'a';
|
||||
} while ((u /= 16) > 0);
|
||||
if (hash)
|
||||
{
|
||||
*bp++ = 'x';
|
||||
*bp++ = '0';
|
||||
}
|
||||
}
|
||||
i = f_width - (int) (bp - buf);
|
||||
if (!flush_left)
|
||||
while (i-- > 0)
|
||||
(*addchar)((int) (pad | attributes));
|
||||
for (bp--; bp >= buf; bp--)
|
||||
(*addchar)((int) (((unsigned char) *bp) | attributes));
|
||||
if (flush_left)
|
||||
while (i-- > 0)
|
||||
(*addchar)((int) (' ' | attributes));
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
i = va_arg(ap, int);
|
||||
(*addchar)((int) (i | attributes));
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
case 'Q':
|
||||
case 's':
|
||||
case 'q':
|
||||
bp = va_arg(ap, char *);
|
||||
if (!bp)
|
||||
bp = snil;
|
||||
f_width = f_width - strlen((char *) bp);
|
||||
if (!flush_left)
|
||||
while (f_width-- > 0)
|
||||
(*addchar)((int) (pad | attributes));
|
||||
for (i = 0; *bp && i < prec; i++)
|
||||
{
|
||||
if (fmt == 'q' && (*bp & QUOTE))
|
||||
(*addchar)((int) ('\\' | attributes));
|
||||
(*addchar)(
|
||||
(int) (((unsigned char) *bp & TRIM) | attributes));
|
||||
bp++;
|
||||
}
|
||||
if (flush_left)
|
||||
while (f_width-- > 0)
|
||||
(*addchar)((int) (' ' | attributes));
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
attributes = va_arg(ap, int);
|
||||
break;
|
||||
|
||||
case '%':
|
||||
(*addchar)((int) ('%' | attributes));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
flush_left = 0, f_width = 0, prec = INF, hash = 0, do_long = 0;
|
||||
sign = 0;
|
||||
pad = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char *xstring, *xestring;
|
||||
|
||||
void xaddchar(int c)
|
||||
{
|
||||
if (xestring == xstring)
|
||||
*xstring = '\0';
|
||||
else
|
||||
*xstring++ = (char) c;
|
||||
}
|
||||
|
||||
int sprintf(char *str, const char *format, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
|
||||
xstring = str;
|
||||
|
||||
doprnt(xaddchar, format, va);
|
||||
va_end(va);
|
||||
*xstring++ = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void xsnprintf(char *str, size_t size, const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
|
||||
xstring = str;
|
||||
xestring = str + size - 1;
|
||||
doprnt(xaddchar, fmt, va);
|
||||
va_end(va);
|
||||
*xstring++ = '\0';
|
||||
}
|
||||
|
||||
void xprintf(const char *fmt, ...)
|
||||
{
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
doprnt(xputchar, fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
void xvprintf(const char *fmt, va_list va)
|
||||
{
|
||||
doprnt(xputchar, fmt, va);
|
||||
}
|
||||
|
||||
void xvsnprintf(char *str, size_t size, const char *fmt, va_list va)
|
||||
{
|
||||
xstring = str;
|
||||
xestring = str + size - 1;
|
||||
doprnt(xaddchar, fmt, va);
|
||||
*xstring++ = '\0';
|
||||
}
|
||||
|
||||
|
||||
void display_progress()
|
||||
{
|
||||
static int _progress_index;
|
||||
char progress_char[] = "|/-\\";
|
||||
|
||||
xputchar(progress_char[_progress_index++ % strlen(progress_char)]);
|
||||
xputchar('\r');
|
||||
}
|
||||
|
||||
void hexdump(uint8_t buffer[], int size)
|
||||
{
|
||||
int i;
|
||||
int line = 0;
|
||||
volatile uint8_t *bp = buffer;
|
||||
|
||||
while (bp < buffer + size) {
|
||||
volatile uint8_t *lbp = bp;
|
||||
|
||||
xprintf("%08x ", line);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
uint8_t c = *lbp++;
|
||||
if (bp + i > buffer + size) {
|
||||
break;
|
||||
}
|
||||
xprintf("%02x ", c);
|
||||
}
|
||||
|
||||
lbp = bp;
|
||||
for (i = 0; i < 16; i++) {
|
||||
volatile int8_t c = *lbp++;
|
||||
|
||||
if (bp + i > buffer + size) {
|
||||
break;
|
||||
}
|
||||
if (c > ' ' && c < '~') {
|
||||
xprintf("%c", c);
|
||||
} else {
|
||||
xprintf(".");
|
||||
}
|
||||
}
|
||||
xprintf("\r\n");
|
||||
|
||||
bp += 16;
|
||||
line += 16;
|
||||
}
|
||||
}
|
||||
166
util/bas_string.c
Normal file
166
util/bas_string.c
Normal file
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* bas_string.c
|
||||
*
|
||||
* This file is part of BaS_gcc.
|
||||
*
|
||||
* BaS_gcc is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* BaS_gcc is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Created on: 26.02.2013
|
||||
* Author: Markus Fröschle
|
||||
*/
|
||||
|
||||
#include "bas_types.h"
|
||||
#include <stdint.h>
|
||||
#include "bas_string.h"
|
||||
|
||||
void *memcpy(void *dst, const void *src, size_t n)
|
||||
{
|
||||
uint8_t *to = dst;
|
||||
|
||||
while (to < (uint8_t *) dst + n)
|
||||
*to++ = * (uint8_t *) src++;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
void *memmove(void *dst, const void *src, size_t n)
|
||||
{
|
||||
uint8_t *to = dst;
|
||||
|
||||
while (to < (uint8_t *) dst + n)
|
||||
*to++ = * (uint8_t *) src++;
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
||||
void bzero(void *s, size_t n)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
((unsigned char *) s)[i] = '\0';
|
||||
}
|
||||
|
||||
void *memset(void *s, int c, size_t n)
|
||||
{
|
||||
uint8_t *dst = s;
|
||||
|
||||
do
|
||||
{
|
||||
*dst++ = c;
|
||||
} while ((dst - (uint8_t *) s) < n);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
int memcmp(const void *s1, const void *s2, size_t max)
|
||||
{
|
||||
int i;
|
||||
int cmp = 0;
|
||||
|
||||
for (i = 0; i < max; i++)
|
||||
{
|
||||
cmp = (* (const char *) s1 - * (const char *) s2);
|
||||
if (cmp != 0) return cmp;
|
||||
}
|
||||
return cmp;
|
||||
}
|
||||
|
||||
int strcmp(const char *s1, const char *s2)
|
||||
{
|
||||
int i;
|
||||
int cmp;
|
||||
|
||||
for (i = 0; *s1++ && *s2++; i++)
|
||||
{
|
||||
cmp = (*s1 - *s2);
|
||||
if (cmp != 0) return cmp;
|
||||
}
|
||||
return cmp;
|
||||
}
|
||||
|
||||
int strncmp(const char *s1, const char *s2, size_t max)
|
||||
{
|
||||
int i;
|
||||
int cmp = 0;
|
||||
|
||||
for (i = 0; i < max && *s1++ && *s2++; i++)
|
||||
{
|
||||
cmp = (*s1 - *s2);
|
||||
if (cmp != 0) return cmp;
|
||||
}
|
||||
return cmp;
|
||||
}
|
||||
|
||||
char *strcpy(char *dst, const char *src)
|
||||
{
|
||||
char *ptr = dst;
|
||||
|
||||
while ((*dst++ = *src++) != '\0');
|
||||
return ptr;
|
||||
}
|
||||
|
||||
char *strncpy(char *dst, const char *src, size_t max)
|
||||
{
|
||||
char *ptr = dst;
|
||||
|
||||
while ((*dst++ = *src++) != '\0' && max-- >= 0);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int atoi(const char *c)
|
||||
{
|
||||
int value = 0;
|
||||
while (isdigit(*c))
|
||||
{
|
||||
value *= 10;
|
||||
value += (int) (*c - '0');
|
||||
c++;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
size_t strlen(const char *s)
|
||||
{
|
||||
const char *start = s;
|
||||
|
||||
while (*s++);
|
||||
|
||||
return s - start - 1;
|
||||
}
|
||||
|
||||
|
||||
char *strcat(char *dst, const char *src)
|
||||
{
|
||||
char *ret = dst;
|
||||
dst = &dst[strlen(dst)];
|
||||
while ((*dst++ = *src++) != '\0');
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *strncat(char *dst, const char *src, size_t max)
|
||||
{
|
||||
size_t i;
|
||||
char *ret = dst;
|
||||
|
||||
dst = &dst[strlen(dst)];
|
||||
for (i = 0; i < max && *src; i++)
|
||||
{
|
||||
*dst++ = *src++;
|
||||
}
|
||||
*dst++ = '\0';
|
||||
|
||||
return ret;
|
||||
}
|
||||
352
util/bcopy.S
Normal file
352
util/bcopy.S
Normal file
@@ -0,0 +1,352 @@
|
||||
|
||||
| new version of bcopy, memcpy and memmove
|
||||
| handles overlap, odd/even alignment
|
||||
| uses movem to copy 256 bytes blocks faster.
|
||||
| Alexander Lehmann alexlehm@iti.informatik.th-darmstadt.de
|
||||
| sortof inspired by jrbs bcopy
|
||||
|
||||
.text
|
||||
.even
|
||||
.globl ___bcopy
|
||||
.globl __bcopy
|
||||
.globl _bcopy
|
||||
.globl _memcpy
|
||||
.globl _memmove
|
||||
|
||||
| void *memcpy( void *dest, const void *src, size_t len );
|
||||
| void *memmove( void *dest, const void *src, size_t len );
|
||||
| returns dest
|
||||
| functions are aliased
|
||||
|
||||
#ifndef __SOZOBON__
|
||||
_memcpy:
|
||||
_memmove:
|
||||
movl sp@(4),a1 | dest
|
||||
movl sp@(8),a0 | src
|
||||
jra common | the rest is samea as bcopy
|
||||
#else
|
||||
| ___bcopy() is the base function below; for memcpy(), memmove()
|
||||
| and bcopy(), we have to sneak a size_t into an unsigned long first.
|
||||
|
||||
_memcpy:
|
||||
_memmove:
|
||||
movl sp@(4),a1 | dest
|
||||
movl sp@(8),a0 | src
|
||||
clrl d0 | here is the sneaky bit...
|
||||
movw sp@(12),d0 | length
|
||||
jra common2 | the rest is samea as bcopy
|
||||
|
||||
_bcopy:
|
||||
movl sp@(4),a0 | src
|
||||
movl sp@(8),a1 | dest
|
||||
clrl d0 | here is the sneaky bit...
|
||||
movw sp@(12),d0 | length
|
||||
jra common2 | the rest is samea as bcopy
|
||||
#endif
|
||||
|
||||
| void bcopy( const void *src, void *dest, size_t length );
|
||||
| void _bcopy( const void *src, void *dest, unsigned long length );
|
||||
| return value not used (returns src)
|
||||
| functions are aliased (except for HSC -- sb)
|
||||
|
||||
#ifndef __SOZOBON__
|
||||
_bcopy:
|
||||
___bcopy:
|
||||
#endif
|
||||
__bcopy:
|
||||
move.l 4(sp),a0 | src
|
||||
move.l 8(sp),a1 | dest
|
||||
common: move.l 12(sp),d0 | length
|
||||
common2:
|
||||
jeq exit | length==0? (size_t)
|
||||
|
||||
| a0 src, a1 dest, d0.l length
|
||||
move.l d2,-(sp)
|
||||
|
||||
| overlay ?
|
||||
cmp.l a0,a1
|
||||
jgt top_down
|
||||
|
||||
#ifdef __mcoldfire__
|
||||
move.l a0,d1 | test for alignment
|
||||
move.l a1,d2
|
||||
eor.l d2,d1
|
||||
#else
|
||||
move.w a0,d1 | test for alignment
|
||||
move.w a1,d2
|
||||
eor.w d2,d1
|
||||
#endif
|
||||
btst #0,d1 | one odd one even ?
|
||||
jne slow_copy
|
||||
btst #0,d2 | both even ?
|
||||
jeq both_even
|
||||
move.b (a0)+,(a1)+ | copy one byte, now we are both even
|
||||
subq.l #1,d0
|
||||
both_even:
|
||||
moveq #0,d1 | save length less 256
|
||||
move.b d0,d1
|
||||
lsr.l #8,d0 | number of 256 bytes blocks
|
||||
jeq less256
|
||||
#ifdef __mcoldfire__
|
||||
lea -10 * 4(sp),sp
|
||||
movem.l d1/d3-d7/a2/a3/a5/a6,(sp) | d2 is already saved
|
||||
| exclude a4 because of -mbaserel
|
||||
copy256:
|
||||
movem.l 0(a0),d1-d7/a2/a3/a5/a6 | copy 5*44+36=256 bytes
|
||||
movem.l d1-d7/a2/a3/a5/a6,a1@
|
||||
movem.l 44(a0),d1-d7/a2/a3/a5/a6
|
||||
movem.l d1-d7/a2/a3/a5/a6,44(a1)
|
||||
movem.l 88(a0),d1-d7/a2/a3/a5/a6
|
||||
movem.l d1-d7/a2/a3/a5/a6,88(a1)
|
||||
movem.l 132(a0),d1-d7/a2/a3/a5/a6
|
||||
movem.l d1-d7/a2/a3/a5/a6,132(a1)
|
||||
movem.l 176(a0),d1-d7/a2/a3/a5/a6
|
||||
movem.l d1-d7/a2/a3/a5/a6,176(a1)
|
||||
movem.l 220(a0),d1-d7/a2-a3
|
||||
movem.l d1-d7/a2-a3,220(a1)
|
||||
lea 256(a0),a0
|
||||
#else
|
||||
movem.l d1/d3-d7/a2/a3/a5/a6,-(sp) | d2 is already saved
|
||||
| exclude a4 because of -mbaserel
|
||||
copy256:
|
||||
movem.l (a0)+,d1-d7/a2/a3/a5/a6 | copy 5*44+36=256 bytes
|
||||
movem.l d1-d7/a2/a3/a5/a6,(a1)
|
||||
movem.l (a0)+,d1-d7/a2/a3/a5/a6
|
||||
movem.l d1-d7/a2/a3/a5/a6,44(a1)
|
||||
movem.l (a0)+,d1-d7/a2/a3/a5/a6
|
||||
movem.l d1-d7/a2/a3/a5/a6,88(a1)
|
||||
movem.l (a0)+,d1-d7/a2/a3/a5/a6
|
||||
movem.l d1-d7/a2/a3/a5/a6,132(a1)
|
||||
movem.l (a0)+,d1-d7/a2/a3/a5/a6
|
||||
movem.l d1-d7/a2/a3/a5/a6,176(a1)
|
||||
movem.l (a0)+,d1-d7/a2-a3
|
||||
movem.l d1-d7/a2-a3,220(a1)
|
||||
#endif
|
||||
lea a1@(256),a1 | increment dest, src is already
|
||||
subql #1,d0
|
||||
jne copy256 | next, please
|
||||
#ifdef __mcoldfire__
|
||||
movml sp@,d1/d3-d7/a2/a3/a5/a6
|
||||
lea sp@(40),sp
|
||||
less256: | copy 16 bytes blocks
|
||||
movl d1,d0
|
||||
lsrl #2,d0 | number of 4 bytes blocks
|
||||
jeq less4 | less that 4 bytes left
|
||||
movl d0,d2
|
||||
negl d2
|
||||
andil #3,d2 | d2 = number of bytes below 16 (-n)&3
|
||||
subql #1,d0
|
||||
lsrl #2,d0 | number of 16 bytes blocks minus 1, if d2==0
|
||||
addl d2,d2 | offset in code (movl two bytes)
|
||||
jmp pc@(2,d2:l) | jmp into loop
|
||||
#else
|
||||
movml sp@+,d1/d3-d7/a2/a3/a5/a6
|
||||
less256: | copy 16 bytes blocks
|
||||
movw d1,d0
|
||||
lsrw #2,d0 | number of 4 bytes blocks
|
||||
jeq less4 | less that 4 bytes left
|
||||
movw d0,d2
|
||||
negw d2
|
||||
andiw #3,d2 | d2 = number of bytes below 16 (-n)&3
|
||||
subqw #1,d0
|
||||
lsrw #2,d0 | number of 16 bytes blocks minus 1, if d2==0
|
||||
addw d2,d2 | offset in code (movl two bytes)
|
||||
jmp pc@(2,d2:w) | jmp into loop
|
||||
#endif
|
||||
copy16:
|
||||
movl a0@+,a1@+
|
||||
movl a0@+,a1@+
|
||||
movl a0@+,a1@+
|
||||
movl a0@+,a1@+
|
||||
#ifdef __mcoldfire__
|
||||
subql #1,d0
|
||||
bpl copy16
|
||||
#else
|
||||
dbra d0,copy16
|
||||
#endif
|
||||
less4:
|
||||
btst #1,d1
|
||||
jeq less2
|
||||
movw a0@+,a1@+
|
||||
less2:
|
||||
btst #0,d1
|
||||
jeq none
|
||||
movb a0@,a1@
|
||||
none:
|
||||
exit_d2:
|
||||
movl sp@+,d2
|
||||
exit:
|
||||
movl sp@(4),d0 | return dest (for memcpy only)
|
||||
rts
|
||||
|
||||
slow_copy: | byte by bytes copy
|
||||
#ifdef __mcoldfire__
|
||||
movl d0,d1
|
||||
negl d1
|
||||
andil #7,d1 | d1 = number of bytes blow 8 (-n)&7
|
||||
addql #7,d0
|
||||
lsrl #3,d0 | number of 8 bytes block plus 1, if d1!=0
|
||||
addl d1,d1 | offset in code (movb two bytes)
|
||||
jmp pc@(2,d1:l) | jump into loop
|
||||
#else
|
||||
movw d0,d1
|
||||
negw d1
|
||||
andiw #7,d1 | d1 = number of bytes blow 8 (-n)&7
|
||||
addql #7,d0
|
||||
lsrl #3,d0 | number of 8 bytes block plus 1, if d1!=0
|
||||
addw d1,d1 | offset in code (movb two bytes)
|
||||
jmp pc@(2,d1:w) | jump into loop
|
||||
#endif
|
||||
scopy:
|
||||
movb a0@+,a1@+
|
||||
movb a0@+,a1@+
|
||||
movb a0@+,a1@+
|
||||
movb a0@+,a1@+
|
||||
movb a0@+,a1@+
|
||||
movb a0@+,a1@+
|
||||
movb a0@+,a1@+
|
||||
movb a0@+,a1@+
|
||||
subql #1,d0
|
||||
jne scopy
|
||||
jra exit_d2
|
||||
|
||||
top_down:
|
||||
addl d0,a0 | a0 byte after end of src
|
||||
addl d0,a1 | a1 byte after end of dest
|
||||
|
||||
#ifdef __mcoldfire__
|
||||
movl a0,d1 | exact the same as above, only with predec
|
||||
movl a1,d2
|
||||
eorl d2,d1
|
||||
#else
|
||||
movw a0,d1 | exact the same as above, only with predec
|
||||
movw a1,d2
|
||||
eorw d2,d1
|
||||
#endif
|
||||
btst #0,d1
|
||||
jne slow_copy_d
|
||||
|
||||
btst #0,d2
|
||||
jeq both_even_d
|
||||
movb a0@-,a1@-
|
||||
subql #1,d0
|
||||
both_even_d:
|
||||
movq #0,d1
|
||||
movb d0,d1
|
||||
lsrl #8,d0
|
||||
jeq less256_d
|
||||
#ifdef __mcoldfire__
|
||||
lea sp@(-40),sp
|
||||
movml d1/d3-d7/a2/a3/a5/a6,sp@
|
||||
copy256_d:
|
||||
movml a0@(-44),d1-d7/a2/a3/a5/a6
|
||||
movml d1-d7/a2/a3/a5/a6,a1@(-44)
|
||||
movml a0@(-88),d1-d7/a2/a3/a5/a6
|
||||
movml d1-d7/a2/a3/a5/a6,a1@(-88)
|
||||
movml a0@(-132),d1-d7/a2/a3/a5/a6
|
||||
movml d1-d7/a2/a3/a5/a6,a1@(-132)
|
||||
movml a0@(-176),d1-d7/a2/a3/a5/a6
|
||||
movml d1-d7/a2/a3/a5/a6,a1@(-176)
|
||||
movml a0@(-220),d1-d7/a2/a3/a5/a6
|
||||
movml d1-d7/a2/a3/a5/a6,a1@(-220)
|
||||
movml a0@(-256),d1-d7/a2-a3
|
||||
movml d1-d7/a2-a3,a1@(-256)
|
||||
lea a1@(-256),a1
|
||||
#else
|
||||
movml d1/d3-d7/a2/a3/a5/a6,sp@-
|
||||
copy256_d:
|
||||
movml a0@(-44),d1-d7/a2/a3/a5/a6
|
||||
movml d1-d7/a2/a3/a5/a6,a1@-
|
||||
movml a0@(-88),d1-d7/a2/a3/a5/a6
|
||||
movml d1-d7/a2/a3/a5/a6,a1@-
|
||||
movml a0@(-132),d1-d7/a2/a3/a5/a6
|
||||
movml d1-d7/a2/a3/a5/a6,a1@-
|
||||
movml a0@(-176),d1-d7/a2/a3/a5/a6
|
||||
movml d1-d7/a2/a3/a5/a6,a1@-
|
||||
movml a0@(-220),d1-d7/a2/a3/a5/a6
|
||||
movml d1-d7/a2/a3/a5/a6,a1@-
|
||||
movml a0@(-256),d1-d7/a2-a3
|
||||
movml d1-d7/a2-a3,a1@-
|
||||
#endif
|
||||
lea a0@(-256),a0
|
||||
subql #1,d0
|
||||
jne copy256_d
|
||||
#ifdef __mcoldfire__
|
||||
movml sp@,d1/d3-d7/a2/a3/a5/a6
|
||||
lea sp@(40),sp
|
||||
less256_d:
|
||||
movl d1,d0
|
||||
lsrl #2,d0
|
||||
jeq less4_d
|
||||
movl d0,d2
|
||||
negl d2
|
||||
andil #3,d2
|
||||
subql #1,d0
|
||||
lsrl #2,d0
|
||||
addl d2,d2
|
||||
jmp pc@(2,d2:l)
|
||||
#else
|
||||
movml sp@+,d1/d3-d7/a2/a3/a5/a6
|
||||
less256_d:
|
||||
movw d1,d0
|
||||
lsrw #2,d0
|
||||
jeq less4_d
|
||||
movw d0,d2
|
||||
negw d2
|
||||
andiw #3,d2
|
||||
subqw #1,d0
|
||||
lsrw #2,d0
|
||||
addw d2,d2
|
||||
jmp pc@(2,d2:w)
|
||||
#endif
|
||||
copy16_d:
|
||||
movl a0@-,a1@-
|
||||
movl a0@-,a1@-
|
||||
movl a0@-,a1@-
|
||||
movl a0@-,a1@-
|
||||
#ifdef __mcoldfire__
|
||||
subql #1,d0
|
||||
bpl copy16_d
|
||||
#else
|
||||
dbra d0,copy16_d
|
||||
#endif
|
||||
less4_d:
|
||||
btst #1,d1
|
||||
jeq less2_d
|
||||
movw a0@-,a1@-
|
||||
less2_d:
|
||||
btst #0,d1
|
||||
jeq exit_d2
|
||||
movb a0@-,a1@-
|
||||
jra exit_d2
|
||||
slow_copy_d:
|
||||
#ifdef __mcoldfire__
|
||||
movl d0,d1
|
||||
negl d1
|
||||
andil #7,d1
|
||||
addql #7,d0
|
||||
lsrl #3,d0
|
||||
addl d1,d1
|
||||
jmp pc@(2,d1:l)
|
||||
#else
|
||||
movw d0,d1
|
||||
negw d1
|
||||
andiw #7,d1
|
||||
addql #7,d0
|
||||
lsrl #3,d0
|
||||
addw d1,d1
|
||||
jmp pc@(2,d1:w)
|
||||
#endif
|
||||
scopy_d:
|
||||
movb a0@-,a1@-
|
||||
movb a0@-,a1@-
|
||||
movb a0@-,a1@-
|
||||
movb a0@-,a1@-
|
||||
movb a0@-,a1@-
|
||||
movb a0@-,a1@-
|
||||
movb a0@-,a1@-
|
||||
movb a0@-,a1@-
|
||||
subql #1,d0
|
||||
jne scopy_d
|
||||
jra exit_d2
|
||||
|
||||
576
util/conout.c
Executable file
576
util/conout.c
Executable file
@@ -0,0 +1,576 @@
|
||||
/*
|
||||
* conout.c - lowlevel color model dependent screen handling routines
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2004 by Authors (see below)
|
||||
* Copyright (C) 2016 The EmuTOS development team
|
||||
*
|
||||
* Authors:
|
||||
* MAD Martin Doering
|
||||
*
|
||||
* This file is distributed under the GPL, version 2 or at your
|
||||
* option any later version. See doc/license.txt for details.
|
||||
*/
|
||||
|
||||
#include "conout.h"
|
||||
#include "video.h"
|
||||
#include "font.h"
|
||||
#include "fb.h"
|
||||
#include "bas_string.h"
|
||||
|
||||
#define plane_offset 2 /* interleaved planes */
|
||||
|
||||
#define v_fnt_st fnt->first_ade
|
||||
#define v_fnt_nd fnt->last_ade
|
||||
#define v_off_ad fnt->off_table
|
||||
#define v_bas_ad ((uint8_t *) info_fb->screen_base)
|
||||
|
||||
uint8_t *v_cur_ad; /* cursor address */
|
||||
int8_t v_stat_0; /* console status byte */
|
||||
uint16_t v_cur_cx;
|
||||
uint16_t v_cur_cy;
|
||||
int8_t v_cur_tim;
|
||||
uint16_t v_cel_mx;
|
||||
uint16_t v_cel_my;
|
||||
uint16_t v_cel_wr;
|
||||
int16_t v_cur_of;
|
||||
uint16_t v_cel_ht;
|
||||
int8_t v_period;
|
||||
const uint16_t *v_fnt_ad;
|
||||
int16_t v_fbt_wr;
|
||||
int16_t v_col_bg;
|
||||
int16_t v_col_fg;
|
||||
uint16_t v_fnt_wr;
|
||||
|
||||
|
||||
#define v_planes (info_fb->var.bits_per_pixel)
|
||||
extern struct fb_info *info_fb;
|
||||
#define v_lin_wr (info_fb->var.width / 2) /* length of a screen line in words */
|
||||
|
||||
/*
|
||||
* internal prototypes
|
||||
*/
|
||||
static void neg_cell(uint8_t *);
|
||||
static uint8_t * cell_addr(int, int);
|
||||
static void cell_xfer(uint8_t *, uint8_t *);
|
||||
static bool next_cell(void);
|
||||
|
||||
|
||||
/*
|
||||
* char_addr - retrieve the address of the source cell
|
||||
*
|
||||
*
|
||||
* Given an offset value.
|
||||
*
|
||||
* in:
|
||||
* ch - source cell code
|
||||
*
|
||||
* out:
|
||||
* pointer to first byte of source cell if code was valid
|
||||
*/
|
||||
|
||||
static uint8_t *char_addr(int16_t ch)
|
||||
{
|
||||
uint16_t offs;
|
||||
|
||||
/* test against limits */
|
||||
if (ch >= v_fnt_st)
|
||||
{
|
||||
if (ch <= v_fnt_nd)
|
||||
{
|
||||
/* getch offset from offset table */
|
||||
offs = v_off_ad[ch];
|
||||
offs >>= 3; /* convert from pixels to bytes. */
|
||||
|
||||
/* return valid address */
|
||||
return (uint8_t*) v_fnt_ad + offs;
|
||||
}
|
||||
}
|
||||
|
||||
/* invalid code. no address returned */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* ascii_out - prints an ascii character on the screen
|
||||
*
|
||||
* in:
|
||||
*
|
||||
* ch.w ascii code for character
|
||||
*/
|
||||
|
||||
void ascii_out(int ch)
|
||||
{
|
||||
uint8_t * src, * dst;
|
||||
bool visible; /* was the cursor visible? */
|
||||
|
||||
src = char_addr(ch); /* a0 -> get character source */
|
||||
if (src == NULL)
|
||||
return; /* no valid character */
|
||||
|
||||
dst = v_cur_ad; /* a1 -> get destination */
|
||||
|
||||
visible = v_stat_0 & M_CVIS; /* test visibility bit */
|
||||
if ( visible ) {
|
||||
neg_cell(v_cur_ad); /* delete cursor. */
|
||||
v_stat_0 &= ~M_CVIS; /* start of critical section */
|
||||
}
|
||||
|
||||
/* put the cell out (this covers the cursor) */
|
||||
cell_xfer(src, dst);
|
||||
|
||||
/* advance the cursor and update cursor address and coordinates */
|
||||
if (next_cell())
|
||||
{
|
||||
uint8_t * cell;
|
||||
|
||||
int y = v_cur_cy;
|
||||
|
||||
/* perform cell carriage return. */
|
||||
cell = v_bas_ad + (uint32_t) v_cel_wr * y;
|
||||
v_cur_cx = 0; /* set X to first cell in line */
|
||||
|
||||
/* perform cell line feed. */
|
||||
if ( y < v_cel_my )
|
||||
{
|
||||
cell += v_cel_wr; /* move down one cell */
|
||||
v_cur_cy = y + 1; /* update cursor's y coordinate */
|
||||
}
|
||||
else {
|
||||
scroll_up(0); /* scroll from top of screen */
|
||||
}
|
||||
v_cur_ad = cell; /* update cursor address */
|
||||
}
|
||||
|
||||
/* if visible */
|
||||
if ( visible ) {
|
||||
neg_cell(v_cur_ad); /* display cursor. */
|
||||
v_stat_0 |= M_CSTATE; /* set state flag (cursor on). */
|
||||
v_stat_0 |= M_CVIS; /* end of critical section. */
|
||||
|
||||
/* do not flash the cursor when it moves */
|
||||
if (v_stat_0 & M_CFLASH) {
|
||||
v_cur_tim = v_period; /* reset the timer. */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* blank_out - Fills region with the background color.
|
||||
*
|
||||
* Fills a cell-word aligned region with the background color.
|
||||
*
|
||||
* The rectangular region is specified by a top/left cell x,y and a
|
||||
* bottom/right cell x,y, inclusive. Routine assumes top/left x is
|
||||
* even and bottom/right x is odd for cell-word alignment. This is,
|
||||
* because this routine is heavily optimized for speed, by always
|
||||
* blanking as much space as possible in one go.
|
||||
*
|
||||
* in:
|
||||
* topx - top/left cell x position (must be even)
|
||||
* topy - top/left cell y position
|
||||
* botx - bottom/right cell x position (must be odd)
|
||||
* boty - bottom/right cell y position
|
||||
*/
|
||||
|
||||
void blank_out(int topx, int topy, int botx, int boty)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* cell_addr - convert cell X,Y to a screen address.
|
||||
*
|
||||
*
|
||||
* convert cell X,Y to a screen address. also clip cartesian coordinates
|
||||
* to the limits of the current screen.
|
||||
*
|
||||
* latest update:
|
||||
*
|
||||
* 18-sep-84
|
||||
* in:
|
||||
*
|
||||
* d0.w cell X
|
||||
* d1.w cell Y
|
||||
*
|
||||
* out:
|
||||
* a1 points to first byte of cell
|
||||
*/
|
||||
|
||||
static uint8_t *cell_addr(int x, int y)
|
||||
{
|
||||
int32_t disx, disy;
|
||||
|
||||
/* check bounds against screen limits */
|
||||
if ( x >= v_cel_mx )
|
||||
x = v_cel_mx; /* clipped x */
|
||||
|
||||
if ( y >= v_cel_my )
|
||||
y = v_cel_my; /* clipped y */
|
||||
|
||||
/* X displacement = even(X) * v_planes + Xmod2 */
|
||||
disx = (int32_t)v_planes * (x & ~1);
|
||||
if ( x & 1 ) { /* Xmod2 = 0 ? */
|
||||
disx++; /* Xmod2 = 1 */
|
||||
}
|
||||
|
||||
/* Y displacement = Y // cell conversion factor */
|
||||
disy = (int32_t)v_cel_wr * y;
|
||||
|
||||
/*
|
||||
* cell address = screen base address + Y displacement
|
||||
* + X displacement + offset from screen-begin (fix)
|
||||
*/
|
||||
return v_bas_ad + disy + disx + v_cur_of;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* cell_xfer - Performs a byte aligned block transfer.
|
||||
*
|
||||
*
|
||||
* This routine performs a byte aligned block transfer for the purpose of
|
||||
* manipulating monospaced byte-wide text. the routine maps a single-plane,
|
||||
* arbitrarily-long byte-wide image to a multi-plane bit map.
|
||||
* all transfers are byte aligned.
|
||||
*
|
||||
* in:
|
||||
* a0.l points to contiguous source block (1 byte wide)
|
||||
* a1.l points to destination (1st plane, top of block)
|
||||
*
|
||||
* out:
|
||||
* a4 points to byte below this cell's bottom
|
||||
*/
|
||||
|
||||
static void cell_xfer(uint8_t * src, uint8_t * dst)
|
||||
{
|
||||
uint8_t * src_sav, * dst_sav;
|
||||
uint16_t fg;
|
||||
uint16_t bg;
|
||||
int fnt_wr, line_wr;
|
||||
int plane;
|
||||
|
||||
fnt_wr = v_fnt_wr;
|
||||
line_wr = v_lin_wr;
|
||||
|
||||
/* check for reversed foreground and background colors */
|
||||
if ( v_stat_0 & M_REVID)
|
||||
{
|
||||
fg = v_col_bg;
|
||||
bg = v_col_fg;
|
||||
}
|
||||
else
|
||||
{
|
||||
fg = v_col_fg;
|
||||
bg = v_col_bg;
|
||||
}
|
||||
|
||||
src_sav = src;
|
||||
dst_sav = dst;
|
||||
|
||||
for (plane = v_planes; plane--;)
|
||||
{
|
||||
int i;
|
||||
|
||||
src = src_sav; /* reload src */
|
||||
dst = dst_sav; /* reload dst */
|
||||
|
||||
if (bg & 0x0001)
|
||||
{
|
||||
if (fg & 0x0001)
|
||||
{
|
||||
/* back:1 fore:1 => all ones */
|
||||
for (i = v_cel_ht; i--;)
|
||||
{
|
||||
*dst = 0xff; /* inject a block */
|
||||
dst += line_wr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* back:1 fore:0 => invert block */
|
||||
for (i = v_cel_ht; i--; )
|
||||
{
|
||||
/* inject the inverted source block */
|
||||
*dst = ~*src;
|
||||
dst += line_wr;
|
||||
src += fnt_wr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (fg & 0x0001)
|
||||
{
|
||||
/* back:0 fore:1 => direct substitution */
|
||||
for (i = v_cel_ht; i--;)
|
||||
{
|
||||
*dst = *src;
|
||||
dst += line_wr;
|
||||
src += fnt_wr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* back:0 fore:0 => all zeros */
|
||||
for (i = v_cel_ht; i--; )
|
||||
{
|
||||
*dst = 0x00; /* inject a block */
|
||||
dst += line_wr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bg >>= 1; /* next background color bit */
|
||||
fg >>= 1; /* next foreground color bit */
|
||||
dst_sav += plane_offset; /* top of block in next plane */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* move_cursor - move the cursor.
|
||||
*
|
||||
* move the cursor and update global parameters
|
||||
* erase the old cursor (if necessary) and draw new cursor (if necessary)
|
||||
*
|
||||
* in:
|
||||
* d0.w new cell X coordinate
|
||||
* d1.w new cell Y coordinate
|
||||
*/
|
||||
|
||||
void move_cursor(int x, int y)
|
||||
{
|
||||
/* update cell position */
|
||||
|
||||
/* clamp x,y to valid ranges */
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
else if (x > v_cel_mx)
|
||||
x = v_cel_mx;
|
||||
|
||||
if (y < 0)
|
||||
y = 0;
|
||||
else if (y > v_cel_my)
|
||||
y = v_cel_my;
|
||||
|
||||
v_cur_cx = x;
|
||||
v_cur_cy = y;
|
||||
|
||||
/* is cursor visible? */
|
||||
if ( !(v_stat_0 & M_CVIS) ) {
|
||||
/* not visible */
|
||||
v_cur_ad = cell_addr(x, y); /* just set new coordinates */
|
||||
return; /* and quit */
|
||||
}
|
||||
|
||||
/* is cursor flashing? */
|
||||
if ( v_stat_0 & M_CFLASH ) {
|
||||
v_stat_0 &= ~M_CVIS; /* yes, make invisible...semaphore. */
|
||||
|
||||
/* is cursor presently displayed ? */
|
||||
if ( !(v_stat_0 & M_CSTATE )) {
|
||||
/* not displayed */
|
||||
v_cur_ad = cell_addr(x, y); /* just set new coordinates */
|
||||
|
||||
/* show the cursor when it moves */
|
||||
neg_cell(v_cur_ad); /* complement cursor. */
|
||||
v_stat_0 |= M_CSTATE;
|
||||
v_cur_tim = v_period; /* reset the timer. */
|
||||
|
||||
v_stat_0 |= M_CVIS; /* end of critical section. */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* move the cursor after all special checks failed */
|
||||
neg_cell(v_cur_ad); /* erase present cursor */
|
||||
|
||||
v_cur_ad = cell_addr(x, y); /* fetch x and y coords. */
|
||||
neg_cell(v_cur_ad); /* complement cursor. */
|
||||
|
||||
/* do not flash the cursor when it moves */
|
||||
v_cur_tim = v_period; /* reset the timer. */
|
||||
|
||||
v_stat_0 |= M_CVIS; /* end of critical section. */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* neg_cell - negates
|
||||
*
|
||||
* This routine negates the contents of an arbitrarily-tall byte-wide cell
|
||||
* composed of an arbitrary number of (Atari-style) bit-planes.
|
||||
* Cursor display can be accomplished via this procedure. Since a second
|
||||
* negation restores the original cell condition, there is no need to save
|
||||
* the contents beneath the cursor block.
|
||||
*
|
||||
* in:
|
||||
* a1.l points to destination (1st plane, top of block)
|
||||
*
|
||||
* out:
|
||||
*/
|
||||
|
||||
static void neg_cell(uint8_t * cell)
|
||||
{
|
||||
int plane, len;
|
||||
int cell_len = v_cel_ht;
|
||||
|
||||
v_stat_0 |= M_CRIT; /* start of critical section. */
|
||||
|
||||
for (plane = v_planes; plane--; ) {
|
||||
uint8_t * addr = cell; /* top of current dest plane */
|
||||
|
||||
/* reset cell length counter */
|
||||
for (len = cell_len; len--; ) {
|
||||
*addr = ~*addr;
|
||||
addr += v_lin_wr;
|
||||
}
|
||||
cell += plane_offset; /* a1 -> top of block in next plane */
|
||||
}
|
||||
v_stat_0 &= ~M_CRIT; /* end of critical section. */
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* invert_cell - negates the cells bits
|
||||
*
|
||||
* This routine negates the contents of an arbitrarily-tall byte-wide cell
|
||||
* composed of an arbitrary number of (Atari-style) bit-planes.
|
||||
*
|
||||
* Wrapper for neg_cell().
|
||||
*
|
||||
* in:
|
||||
* x - cell X coordinate
|
||||
* y - cell Y coordinate
|
||||
*/
|
||||
|
||||
void invert_cell(int x, int y)
|
||||
{
|
||||
/* fetch x and y coords and invert cursor. */
|
||||
neg_cell(cell_addr(x, y));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* next_cell - Return the next cell address.
|
||||
*
|
||||
* sets next cell address given the current position and screen constraints
|
||||
*
|
||||
* returns:
|
||||
* false - no wrap condition exists
|
||||
* true - CR LF required (position has not been updated)
|
||||
*/
|
||||
|
||||
static bool next_cell(void)
|
||||
{
|
||||
/* check bounds against screen limits */
|
||||
if (v_cur_cx == v_cel_mx)
|
||||
{
|
||||
/* increment cell ptr */
|
||||
if (!(v_stat_0 & M_CEOL))
|
||||
{
|
||||
/* overwrite in effect */
|
||||
return 0; /* no wrap condition exists */
|
||||
/* don't change cell parameters */
|
||||
}
|
||||
|
||||
/* call carriage return routine */
|
||||
/* call line feed routine */
|
||||
return 1; /* indicate that CR LF is required */
|
||||
}
|
||||
|
||||
v_cur_cx += 1; /* next cell to right */
|
||||
|
||||
/* if X is even, move to next word in the plane */
|
||||
if (v_cur_cx & 1)
|
||||
{
|
||||
/* x is odd */
|
||||
v_cur_ad += 1; /* a1 -> new cell */
|
||||
return 0; /* indicate no wrap needed */
|
||||
}
|
||||
|
||||
/* new cell (1st plane), added offset to next word in plane */
|
||||
v_cur_ad += (v_planes << 1) - 1;
|
||||
|
||||
return 0; /* indicate no wrap needed */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* scroll_up - Scroll upwards
|
||||
*
|
||||
*
|
||||
* Scroll copies a source region as wide as the screen to an overlapping
|
||||
* destination region on a one cell-height offset basis. Two entry points
|
||||
* are provided: Partial-lower scroll-up, partial-lower scroll-down.
|
||||
* Partial-lower screen operations require the cell y # indicating the
|
||||
* top line where scrolling will take place.
|
||||
*
|
||||
* After the copy is performed, any non-overlapping area of the previous
|
||||
* source region is "erased" by calling blank_out which fills the area
|
||||
* with the background color.
|
||||
*
|
||||
* in:
|
||||
* top_line - cell y of cell line to be used as top line in scroll
|
||||
*/
|
||||
|
||||
void scroll_up(int top_line)
|
||||
{
|
||||
uint32_t count;
|
||||
uint8_t * src, * dst;
|
||||
|
||||
/* screen base addr + cell y nbr * cell wrap */
|
||||
dst = v_bas_ad + (uint32_t) top_line * v_cel_wr;
|
||||
|
||||
/* form source address from cell wrap + base address */
|
||||
src = dst + v_cel_wr;
|
||||
|
||||
/* form # of bytes to move */
|
||||
count = (uint32_t) v_cel_wr * (v_cel_my - top_line);
|
||||
|
||||
/* move BYTEs of memory*/
|
||||
memmove(dst, src, count);
|
||||
|
||||
/* exit thru blank out, bottom line cell address y to top/left cell */
|
||||
blank_out(0, v_cel_my , v_cel_mx, v_cel_my );
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* scroll_down - Scroll (partially) downwards
|
||||
*/
|
||||
|
||||
void scroll_down(int start_line)
|
||||
{
|
||||
uint32_t count;
|
||||
uint8_t * src, * dst;
|
||||
|
||||
/* screen base addr + offset of start line */
|
||||
src = v_bas_ad + (uint32_t) start_line * v_cel_wr;
|
||||
|
||||
/* form destination from source + cell wrap */
|
||||
dst = src + v_cel_wr;
|
||||
|
||||
/* form # of bytes to move */
|
||||
count = (uint32_t) v_cel_wr * (v_cel_my - start_line);
|
||||
|
||||
/* move BYTEs of memory*/
|
||||
memmove(dst, src, count);
|
||||
|
||||
/* exit thru blank out */
|
||||
blank_out(0, start_line , v_cel_mx, start_line);
|
||||
}
|
||||
|
||||
70
util/libgcc_helper.S
Normal file
70
util/libgcc_helper.S
Normal file
@@ -0,0 +1,70 @@
|
||||
//
|
||||
// needed for ELF compilation of x86emu which uses 64 bit multiplication and division. This
|
||||
// is implemented in libgcc.a. However, the ELF compiler emits leading underscores and libgcc
|
||||
// is not compiled like that - we must reimplement the symbols.
|
||||
//
|
||||
// FIXME: This is a quirk and should be replaced by BaS' own implementation later
|
||||
//
|
||||
.global ___divdi3
|
||||
.extern __divdi3
|
||||
___divdi3: jmp __divdi3
|
||||
|
||||
.global ___muldi3
|
||||
.extern __muldi3
|
||||
___muldi3: jmp __muldi3
|
||||
|
||||
.global ___moddi3
|
||||
.extern __moddi3
|
||||
___moddi3: jmp __moddi3
|
||||
|
||||
.global ___udivdi3
|
||||
.extern __udivdi3
|
||||
___udivdi3: jmp __udivdi3
|
||||
|
||||
.global ___umoddi3
|
||||
.extern __umoddi3
|
||||
___umoddi3: jmp __umoddi3
|
||||
|
||||
.global ___divdf3
|
||||
.extern __divdf3
|
||||
___divdf3: jmp __divdf3
|
||||
|
||||
.global ___muldf3
|
||||
.extern __muldf3
|
||||
___muldf3: jmp __muldf3
|
||||
|
||||
.global ___subsf3
|
||||
.extern __subsf3
|
||||
___subsf3: jmp __subsf3
|
||||
|
||||
.global ___floatsidf
|
||||
.extern __floatsidf
|
||||
___floatsidf: jmp __floatsidf
|
||||
|
||||
.global ___floatsisf
|
||||
.extern __floatsisf
|
||||
___floatsisf: jmp __floatsisf
|
||||
|
||||
.global ___extendsfdf2
|
||||
.extern __extendsfdf2
|
||||
___extendsfdf2: jmp __extendsfdf2
|
||||
|
||||
.global ___floatunsidf
|
||||
.extern __floatunsidf
|
||||
___floatunsidf: jmp __floatunsidf
|
||||
|
||||
.global ___truncdfsf2
|
||||
.extern __truncdfsf2
|
||||
___truncdfsf2: jmp __truncdfsf2
|
||||
|
||||
.global ___ltsf2
|
||||
.extern __ltsf2
|
||||
___ltsf2: jmp __ltsf2
|
||||
|
||||
.global ___fixdfsi
|
||||
.extern __fixdfsi
|
||||
___fixdfsi: jmp __fixdfsi
|
||||
|
||||
.global ___fixsfsi
|
||||
.extern __fixsfsi
|
||||
___fixsfsi: jmp __fixsfsi
|
||||
16
util/setjmp.S
Normal file
16
util/setjmp.S
Normal file
@@ -0,0 +1,16 @@
|
||||
.globl _setjmp
|
||||
.globl _longjmp
|
||||
|
||||
_setjmp: move.l 4(sp),a0 // address of jmp_buf[]
|
||||
move.l (sp),(a0) // save return address
|
||||
movem.l d2-d7/a2-a7,4(a0) // save registers to jmp_buf
|
||||
clr.l d0
|
||||
rts
|
||||
|
||||
_longjmp: move.l 4(sp),a0 // address of jmp_buf[]
|
||||
move.l 8(sp),d0 // value to return
|
||||
jne not_0 // value may not be 0
|
||||
moveq.l #1,d0
|
||||
not_0: movem.l 4(a0),d2-d7/a2-a7 // restore registers
|
||||
move.l (a0),(sp) // restore saved return address
|
||||
rts
|
||||
85
util/wait.c
Normal file
85
util/wait.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* wait.c
|
||||
*
|
||||
* Created on: 10.12.2012
|
||||
* Author: mfro
|
||||
*
|
||||
* This file is part of BaS_gcc.
|
||||
*
|
||||
* BaS_gcc is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* BaS_gcc is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with BaS_gcc. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Copyright 2010 - 2012 F. Aschwanden
|
||||
* Copyright 2011 - 2012 V. Riviere
|
||||
* Copyright 2012 M. Froeschle
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <MCF5475.h>
|
||||
#include <wait.h>
|
||||
|
||||
uint32_t get_timer(void)
|
||||
{
|
||||
return MCF_SLT_SCNT(0);
|
||||
}
|
||||
|
||||
static uint32_t timer_value;
|
||||
|
||||
void start_timeout(void)
|
||||
{
|
||||
timer_value = get_timer();
|
||||
}
|
||||
|
||||
bool end_timeout(uint32_t msec)
|
||||
{
|
||||
msec *= SYSCLK;
|
||||
|
||||
return (get_timer() - timer_value) < msec ? false : true;
|
||||
}
|
||||
|
||||
/*
|
||||
* wait for the specified number of us on slice timer 0. Replaces the original routines that had
|
||||
* the number of useconds to wait for hardcoded in their name.
|
||||
*/
|
||||
void wait(uint32_t us)
|
||||
{
|
||||
int32_t target = MCF_SLT_SCNT(0) - (us * (SYSCLK / 1000));
|
||||
|
||||
while (MCF_SLT_SCNT(0) - target > 0);
|
||||
}
|
||||
void wait_us() __attribute__ ((weak, alias("wait")));
|
||||
|
||||
/*
|
||||
* same as above, but with milliseconds wait time
|
||||
*/
|
||||
void wait_ms(uint32_t ms)
|
||||
{
|
||||
wait(ms * 1000);
|
||||
}
|
||||
/*
|
||||
* the same as above, with a checker function which gets called while
|
||||
* busy waiting and allows for an early return if it returns true
|
||||
*/
|
||||
bool waitfor(uint32_t us, checker_func condition)
|
||||
{
|
||||
int32_t target = MCF_SLT_SCNT(0) - (us * (SYSCLK / 1000));
|
||||
bool res;
|
||||
|
||||
do
|
||||
{
|
||||
if ((res = (*condition)()))
|
||||
return res;
|
||||
} while (MCF_SLT_SCNT(0) - target > 0);
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user