retire the dec alpha port
This commit is contained in:
parent
f7703d6971
commit
986886f2b8
|
@ -1,76 +0,0 @@
|
|||
#ifndef __FLOAT
|
||||
#define __FLOAT
|
||||
/* IEEE, default rounding */
|
||||
|
||||
#define FLT_ROUNDS 1
|
||||
#define FLT_RADIX 2
|
||||
|
||||
#define FLT_DIG 6
|
||||
#define FLT_EPSILON 1.19209290e-07
|
||||
#define FLT_MANT_DIG 24
|
||||
#define FLT_MAX 3.40282347e+38
|
||||
#define FLT_MAX_10_EXP 38
|
||||
#define FLT_MAX_EXP 128
|
||||
#define FLT_MIN 1.17549435e-38
|
||||
#define FLT_MIN_10_EXP -37
|
||||
#define FLT_MIN_EXP -125
|
||||
|
||||
#define DBL_DIG 15
|
||||
#define DBL_EPSILON 2.2204460492503131e-16
|
||||
#define DBL_MANT_DIG 53
|
||||
#define DBL_MAX 1.797693134862315708145e+308
|
||||
#define DBL_MAX_10_EXP 308
|
||||
#define DBL_MAX_EXP 1024
|
||||
#define DBL_MIN 2.225073858507201383090233e-308
|
||||
#define DBL_MIN_10_EXP -307
|
||||
#define DBL_MIN_EXP -1021
|
||||
#define LDBL_MANT_DIG DBL_MANT_DIG
|
||||
#define LDBL_EPSILON DBL_EPSILON
|
||||
#define LDBL_DIG DBL_DIG
|
||||
#define LDBL_MIN_EXP DBL_MIN_EXP
|
||||
#define LDBL_MIN DBL_MIN
|
||||
#define LDBL_MIN_10_EXP DBL_MIN_10_EXP
|
||||
#define LDBL_MAX_EXP DBL_MAX_EXP
|
||||
#define LDBL_MAX DBL_MAX
|
||||
#define LDBL_MAX_10_EXP DBL_MAX_10_EXP
|
||||
|
||||
typedef union FPdbleword FPdbleword;
|
||||
union FPdbleword
|
||||
{
|
||||
double x;
|
||||
struct { /* little endian */
|
||||
long lo;
|
||||
long hi;
|
||||
};
|
||||
};
|
||||
|
||||
#ifdef _RESEARCH_SOURCE
|
||||
/* define stuff needed for floating conversion */
|
||||
#define IEEE_8087 1
|
||||
#define Sudden_Underflow 1
|
||||
#endif
|
||||
#ifdef _PLAN9_SOURCE
|
||||
#define FPINEX (1<<30)
|
||||
#define FPOVFL (1<<19)
|
||||
#define FPUNFL ((1<<29)|(1<<28))
|
||||
#define FPZDIV (1<<18)
|
||||
#define FPINVAL (1<<17)
|
||||
|
||||
#define FPRNR (2<<26)
|
||||
#define FPRZ (0<<26)
|
||||
#define FPRPINF (3<<26)
|
||||
#define FPRNINF (1<<26)
|
||||
#define FPRMASK (3<<26)
|
||||
|
||||
#define FPPEXT 0
|
||||
#define FPPSGL 0
|
||||
#define FPPDBL 0
|
||||
#define FPPMASK 0
|
||||
/* FSR */
|
||||
#define FPAINEX (1<<24)
|
||||
#define FPAUNFL (1<<23)
|
||||
#define FPAOVFL (1<<22)
|
||||
#define FPAZDIV (1<<21)
|
||||
#define FPAINVAL (1<<20)
|
||||
#endif
|
||||
#endif /* __FLOAT */
|
|
@ -1,77 +0,0 @@
|
|||
#ifndef __MATH
|
||||
#define __MATH
|
||||
#pragma lib "/$M/lib/ape/libap.a"
|
||||
|
||||
/* a HUGE_VAL appropriate for IEEE double-precision */
|
||||
/* the correct value, 1.797693134862316e+308, causes a ken overflow */
|
||||
#define HUGE_VAL 1.79769313486231e+308
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern double acos(double);
|
||||
extern double asin(double);
|
||||
extern double atan(double);
|
||||
extern double atan2(double, double);
|
||||
extern double cos(double);
|
||||
extern double sin(double);
|
||||
extern double tan(double);
|
||||
extern double cosh(double);
|
||||
extern double sinh(double);
|
||||
extern double tanh(double);
|
||||
extern double exp(double);
|
||||
extern double frexp(double, int *);
|
||||
extern double ldexp(double, int);
|
||||
extern double log(double);
|
||||
extern double log10(double);
|
||||
extern double modf(double, double *);
|
||||
extern double pow(double, double);
|
||||
extern double sqrt(double);
|
||||
extern double ceil(double);
|
||||
extern double fabs(double);
|
||||
extern double floor(double);
|
||||
extern double fmod(double, double);
|
||||
extern double NaN(void);
|
||||
extern int isNaN(double);
|
||||
extern double Inf(int);
|
||||
extern int isInf(double, int);
|
||||
|
||||
#ifdef _RESEARCH_SOURCE
|
||||
/* does >> treat left operand as unsigned ? */
|
||||
#define Unsigned_Shifts 1
|
||||
#define M_E 2.7182818284590452354 /* e */
|
||||
#define M_LOG2E 1.4426950408889634074 /* log 2e */
|
||||
#define M_LOG10E 0.43429448190325182765 /* log 10e */
|
||||
#define M_LN2 0.69314718055994530942 /* log e2 */
|
||||
#define M_LN10 2.30258509299404568402 /* log e10 */
|
||||
#define M_PI 3.14159265358979323846 /* pi */
|
||||
#define M_PI_2 1.57079632679489661923 /* pi/2 */
|
||||
#define M_PI_4 0.78539816339744830962 /* pi/4 */
|
||||
#define M_1_PI 0.31830988618379067154 /* 1/pi */
|
||||
#define M_2_PI 0.63661977236758134308 /* 2/pi */
|
||||
#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */
|
||||
#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
|
||||
#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
|
||||
|
||||
extern double hypot(double, double);
|
||||
extern double erf(double);
|
||||
extern double erfc(double);
|
||||
extern double j0(double);
|
||||
extern double y0(double);
|
||||
extern double j1(double);
|
||||
extern double y1(double);
|
||||
extern double jn(int, double);
|
||||
extern double yn(int, double);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define isnan(x) isNaN(x)
|
||||
#define isinf(x) isInf(x)
|
||||
|
||||
#endif /* __MATH */
|
|
@ -1,17 +0,0 @@
|
|||
#ifndef __STDARG
|
||||
#define __STDARG
|
||||
|
||||
typedef char *va_list;
|
||||
|
||||
#define va_start(list, start) list = (char *)(&(start)+1)
|
||||
#define va_end(list)
|
||||
#define va_arg(list, mode)\
|
||||
(sizeof(mode)==1?\
|
||||
((mode*)(list += 4))[-1]:\
|
||||
sizeof(mode)==2?\
|
||||
((mode*)(list += 4))[-1]:\
|
||||
sizeof(mode)>4?\
|
||||
((mode*)(list = (char*)((long)(list+7) & ~7) + sizeof(mode)))[-1]:\
|
||||
((mode*)(list += sizeof(mode)))[-1])
|
||||
|
||||
#endif /* __STDARG */
|
|
@ -1,57 +0,0 @@
|
|||
#ifndef __UREG_H
|
||||
#define __UREG_H
|
||||
#if !defined(_PLAN9_SOURCE)
|
||||
This header file is an extension to ANSI/POSIX
|
||||
#endif
|
||||
|
||||
struct Ureg
|
||||
{
|
||||
/* l.s saves 31 64-bit values: */
|
||||
unsigned long long type;
|
||||
unsigned long long a0;
|
||||
unsigned long long a1;
|
||||
unsigned long long a2;
|
||||
|
||||
unsigned long long r0;
|
||||
unsigned long long r1;
|
||||
unsigned long long r2;
|
||||
unsigned long long r3;
|
||||
unsigned long long r4;
|
||||
unsigned long long r5;
|
||||
unsigned long long r6;
|
||||
unsigned long long r7;
|
||||
unsigned long long r8;
|
||||
unsigned long long r9;
|
||||
unsigned long long r10;
|
||||
unsigned long long r11;
|
||||
unsigned long long r12;
|
||||
unsigned long long r13;
|
||||
unsigned long long r14;
|
||||
unsigned long long r15;
|
||||
|
||||
unsigned long long r19;
|
||||
unsigned long long r20;
|
||||
unsigned long long r21;
|
||||
unsigned long long r22;
|
||||
unsigned long long r23;
|
||||
unsigned long long r24;
|
||||
unsigned long long r25;
|
||||
unsigned long long r26;
|
||||
unsigned long long r27;
|
||||
unsigned long long r28;
|
||||
union {
|
||||
unsigned long long r30;
|
||||
unsigned long long usp;
|
||||
unsigned long long sp;
|
||||
};
|
||||
|
||||
/* OSF/1 PALcode frame: */
|
||||
unsigned long long status; /* PS */
|
||||
unsigned long long pc;
|
||||
unsigned long long r29; /* GP */
|
||||
unsigned long long r16; /* a0 */
|
||||
unsigned long long r17; /* a1 */
|
||||
unsigned long long r18; /* a2 */
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,71 +0,0 @@
|
|||
#define nil ((void*)0)
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned char uchar;
|
||||
typedef unsigned long ulong;
|
||||
typedef unsigned int uint;
|
||||
typedef signed char schar;
|
||||
typedef long long vlong;
|
||||
typedef unsigned long long uvlong;
|
||||
typedef long intptr;
|
||||
typedef unsigned long uintptr;
|
||||
typedef unsigned long usize;
|
||||
typedef uint Rune;
|
||||
typedef union FPdbleword FPdbleword;
|
||||
typedef long jmp_buf[2];
|
||||
#define JMPBUFSP 0
|
||||
#define JMPBUFPC 1
|
||||
#define JMPBUFDPC 0
|
||||
typedef unsigned int mpdigit; /* for /sys/include/mp.h */
|
||||
typedef unsigned char u8int;
|
||||
typedef unsigned short u16int;
|
||||
typedef unsigned int u32int;
|
||||
typedef unsigned long long u64int;
|
||||
|
||||
/* FCR */
|
||||
#define FPINEX (1<<30)
|
||||
#define FPOVFL (1<<19)
|
||||
#define FPUNFL ((1<<29)|(1<<28))
|
||||
#define FPZDIV (1<<18)
|
||||
#define FPINVAL (1<<17)
|
||||
|
||||
#define FPRNR (2<<26)
|
||||
#define FPRZ (0<<26)
|
||||
#define FPRPINF (3<<26)
|
||||
#define FPRNINF (1<<26)
|
||||
#define FPRMASK (3<<26)
|
||||
|
||||
#define FPPEXT 0
|
||||
#define FPPSGL 0
|
||||
#define FPPDBL 0
|
||||
#define FPPMASK 0
|
||||
/* FSR */
|
||||
#define FPAINEX (1<<24)
|
||||
#define FPAUNFL (1<<23)
|
||||
#define FPAOVFL (1<<22)
|
||||
#define FPAZDIV (1<<21)
|
||||
#define FPAINVAL (1<<20)
|
||||
union FPdbleword
|
||||
{
|
||||
double x;
|
||||
struct { /* little endian */
|
||||
ulong lo;
|
||||
ulong hi;
|
||||
};
|
||||
};
|
||||
|
||||
/* stdarg */
|
||||
typedef char* va_list;
|
||||
#define va_start(list, start) list =\
|
||||
(sizeof(start) < 4?\
|
||||
(char*)((int*)&(start)+1):\
|
||||
(char*)(&(start)+1))
|
||||
#define va_end(list)\
|
||||
USED(list)
|
||||
#define va_arg(list, mode)\
|
||||
((sizeof(mode) == 1)?\
|
||||
((list += 4), (mode*)list)[-4]:\
|
||||
(sizeof(mode) == 2)?\
|
||||
((list += 4), (mode*)list)[-2]:\
|
||||
sizeof(mode)>4?\
|
||||
((mode*)(list = (char*)((uintptr)(list+7) & ~7) + sizeof(mode)))[-1]:\
|
||||
((list += sizeof(mode)), (mode*)list)[-1])
|
|
@ -1,49 +0,0 @@
|
|||
struct Ureg
|
||||
{
|
||||
/* l.s saves 31 64-bit values: */
|
||||
uvlong type;
|
||||
uvlong a0;
|
||||
uvlong a1;
|
||||
uvlong a2;
|
||||
|
||||
uvlong r0;
|
||||
uvlong r1;
|
||||
uvlong r2;
|
||||
uvlong r3;
|
||||
uvlong r4;
|
||||
uvlong r5;
|
||||
uvlong r6;
|
||||
uvlong r7;
|
||||
uvlong r8;
|
||||
uvlong r9;
|
||||
uvlong r10;
|
||||
uvlong r11;
|
||||
uvlong r12;
|
||||
uvlong r13;
|
||||
uvlong r14;
|
||||
uvlong r15;
|
||||
|
||||
uvlong r19;
|
||||
uvlong r20;
|
||||
uvlong r21;
|
||||
uvlong r22;
|
||||
uvlong r23;
|
||||
uvlong r24;
|
||||
uvlong r25;
|
||||
uvlong r26;
|
||||
uvlong r27;
|
||||
uvlong r28;
|
||||
union {
|
||||
uvlong r30;
|
||||
uvlong usp;
|
||||
uvlong sp;
|
||||
};
|
||||
|
||||
/* OSF/1 PALcode frame: */
|
||||
uvlong status; /* PS */
|
||||
uvlong pc;
|
||||
uvlong r29; /* GP */
|
||||
uvlong r16; /* a0 */
|
||||
uvlong r17; /* a1 */
|
||||
uvlong r18; /* a2 */
|
||||
};
|
|
@ -1,6 +0,0 @@
|
|||
</sys/src/mkfile.proto
|
||||
|
||||
CC=7c
|
||||
LD=7l
|
||||
O=7
|
||||
AS=7a
|
|
@ -25,7 +25,7 @@ struct Exec
|
|||
#define E_MAGIC _MAGIC(0, 20) /* arm */
|
||||
#define Q_MAGIC _MAGIC(0, 21) /* powerpc */
|
||||
#define N_MAGIC _MAGIC(0, 22) /* mips 4000 LE */
|
||||
#define L_MAGIC _MAGIC(0, 23) /* dec alpha */
|
||||
#define L_MAGIC _MAGIC(0, 23) /* dec alpha (retired) */
|
||||
#define P_MAGIC _MAGIC(0, 24) /* mips 3000 LE */
|
||||
#define U_MAGIC _MAGIC(0, 25) /* sparc64 */
|
||||
#define S_MAGIC _MAGIC(HDR_MAGIC, 26) /* amd64 */
|
||||
|
|
|
@ -1,205 +0,0 @@
|
|||
// Alpha support
|
||||
|
||||
defn acidinit() // Called after all the init modules are loaded
|
||||
{
|
||||
bplist = {};
|
||||
bpfmt = 'X';
|
||||
|
||||
srcpath = {
|
||||
"./",
|
||||
"/sys/src/libc/port/",
|
||||
"/sys/src/libc/9sys/",
|
||||
"/sys/src/libc/alpha/"
|
||||
};
|
||||
|
||||
srcfiles = {}; // list of loaded files
|
||||
srctext = {}; // the text of the files
|
||||
}
|
||||
|
||||
defn stk() // trace
|
||||
{
|
||||
_stk(*PC, *SP, linkreg(0), 0);
|
||||
}
|
||||
|
||||
defn lstk() // trace with locals
|
||||
{
|
||||
_stk(*PC, *SP, linkreg(0), 1);
|
||||
}
|
||||
|
||||
defn gpr() // print general purpose registers
|
||||
{
|
||||
print("R0\t", *R0, "\n");
|
||||
print("R1\t", *R1, " R2\t", *R2, " R3\t", *R3, "\n");
|
||||
print("R4\t", *R4, " R5\t", *R5, " R6\t", *R6, "\n");
|
||||
print("R7\t", *R7, " R8\t", *R8, " R9\t", *R9, "\n");
|
||||
print("R10\t", *R10, " R11\t", *R11, " R12\t", *R12, "\n");
|
||||
print("R13\t", *R13, " R14\t", *R14, " R15\t", *R15, "\n");
|
||||
print("R16\t", *R16, " R17\t", *R17, " R18\t", *R18, "\n");
|
||||
print("R19\t", *R19, " R20\t", *R20, " R21\t", *R21, "\n");
|
||||
print("R22\t", *R22, " R23\t", *R23, " R24\t", *R24, "\n");
|
||||
print("R25\t", *R25, " R26\t", *R26, " R27\t", *R27, "\n");
|
||||
print("R28\t", *R28, " R29\t", *R29, " R30\t", *SP\Y, "\n");
|
||||
}
|
||||
|
||||
defn fpr()
|
||||
{
|
||||
print("F0\t", *fmt(F0, 'G'), "\tF1\t", *fmt(F1, 'G'), "\n");
|
||||
print("F2\t", *fmt(F2, 'G'), "\tF3\t", *fmt(F3, 'G'), "\n");
|
||||
print("F4\t", *fmt(F4, 'G'), "\tF5\t", *fmt(F5, 'G'), "\n");
|
||||
print("F6\t", *fmt(F6, 'G'), "\tF7\t", *fmt(F7, 'G'), "\n");
|
||||
print("F8\t", *fmt(F8, 'G'), "\tF9\t", *fmt(F9, 'G'), "\n");
|
||||
print("F10\t", *fmt(F10, 'G'), "\tF11\t", *fmt(F11, 'G'), "\n");
|
||||
print("F12\t", *fmt(F12, 'G'), "\tF13\t", *fmt(F13, 'G'), "\n");
|
||||
print("F14\t", *fmt(F14, 'G'), "\tF15\t", *fmt(F15, 'G'), "\n");
|
||||
print("F16\t", *fmt(F16, 'G'), "\tF17\t", *fmt(F17, 'G'), "\n");
|
||||
print("F18\t", *fmt(F18, 'G'), "\tF19\t", *fmt(F19, 'G'), "\n");
|
||||
print("F20\t", *fmt(F20, 'G'), "\tF21\t", *fmt(F21, 'G'), "\n");
|
||||
print("F22\t", *fmt(F22, 'G'), "\tF23\t", *fmt(F23, 'G'), "\n");
|
||||
print("F24\t", *fmt(F24, 'G'), "\tF25\t", *fmt(F25, 'G'), "\n");
|
||||
print("F26\t", *fmt(F26, 'G'), "\tF27\t", *fmt(F27, 'G'), "\n");
|
||||
print("F28\t", *fmt(F28, 'G'), "\tF29\t", *fmt(F29, 'G'), "\n");
|
||||
print("F30\t", *fmt(F30, 'G'), "\tF31\t", *fmt(F31, 'G'), "\n");
|
||||
}
|
||||
|
||||
defn spr() // print special processor registers
|
||||
{
|
||||
local pc, link, cause;
|
||||
|
||||
pc = *PC;
|
||||
print("PC\t", pc, " ", fmt(pc, 'a'), " ");
|
||||
pfl(pc);
|
||||
|
||||
link = *R26;
|
||||
print("SP\t", *SP, "\tLINK\t", link, " ", fmt(link, 'a'), " ");
|
||||
pfl(link);
|
||||
|
||||
cause = *TYPE;
|
||||
print("STATUS\t", *STATUS, "\tTYPE\t", cause, " ", reason(cause), "\n");
|
||||
print("A0\t", *A0, " A1\t", *A1, " A2\t", *A2, "\n");
|
||||
}
|
||||
|
||||
defn regs() // print all registers
|
||||
{
|
||||
spr();
|
||||
gpr();
|
||||
}
|
||||
|
||||
defn pstop(pid)
|
||||
{
|
||||
local l, pc;
|
||||
|
||||
pc = *PC;
|
||||
|
||||
print(pid,": ", reason(*TYPE), "\t");
|
||||
print(fmt(pc, 'a'), "\t", fmt(pc, 'i'), "\n");
|
||||
|
||||
if notes then {
|
||||
if notes[0] != "sys: breakpoint" then {
|
||||
print("Notes pending:\n");
|
||||
l = notes;
|
||||
while l do {
|
||||
print("\t", head l, "\n");
|
||||
l = tail l;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sizeofUreg = 296;
|
||||
aggr Ureg
|
||||
{
|
||||
'W' 0 type;
|
||||
'W' 8 a0;
|
||||
'W' 16 a1;
|
||||
'W' 24 a2;
|
||||
'W' 32 r0;
|
||||
'W' 40 r1;
|
||||
'W' 48 r2;
|
||||
'W' 56 r3;
|
||||
'W' 64 r4;
|
||||
'W' 72 r5;
|
||||
'W' 80 r6;
|
||||
'W' 88 r7;
|
||||
'W' 96 r8;
|
||||
'W' 104 r9;
|
||||
'W' 112 r10;
|
||||
'W' 120 r11;
|
||||
'W' 128 r12;
|
||||
'W' 136 r13;
|
||||
'W' 144 r14;
|
||||
'W' 152 r15;
|
||||
'W' 160 r19;
|
||||
'W' 168 r20;
|
||||
'W' 176 r21;
|
||||
'W' 184 r22;
|
||||
'W' 192 r23;
|
||||
'W' 200 r24;
|
||||
'W' 208 r25;
|
||||
'W' 216 r26;
|
||||
'W' 224 r27;
|
||||
'W' 232 r28;
|
||||
{
|
||||
'W' 240 r30;
|
||||
'W' 240 usp;
|
||||
'W' 240 sp;
|
||||
};
|
||||
'W' 248 status;
|
||||
'W' 256 pc;
|
||||
'W' 264 r29;
|
||||
'W' 272 r16;
|
||||
'W' 280 r17;
|
||||
'W' 288 r18;
|
||||
};
|
||||
|
||||
defn
|
||||
Ureg(addr) {
|
||||
complex Ureg addr;
|
||||
print(" type ", addr.type, "\n");
|
||||
print(" a0 ", addr.a0, "\n");
|
||||
print(" a1 ", addr.a1, "\n");
|
||||
print(" a2 ", addr.a2, "\n");
|
||||
print(" r0 ", addr.r0, "\n");
|
||||
print(" r1 ", addr.r1, "\n");
|
||||
print(" r2 ", addr.r2, "\n");
|
||||
print(" r3 ", addr.r3, "\n");
|
||||
print(" r4 ", addr.r4, "\n");
|
||||
print(" r5 ", addr.r5, "\n");
|
||||
print(" r6 ", addr.r6, "\n");
|
||||
print(" r7 ", addr.r7, "\n");
|
||||
print(" r8 ", addr.r8, "\n");
|
||||
print(" r9 ", addr.r9, "\n");
|
||||
print(" r10 ", addr.r10, "\n");
|
||||
print(" r11 ", addr.r11, "\n");
|
||||
print(" r12 ", addr.r12, "\n");
|
||||
print(" r13 ", addr.r13, "\n");
|
||||
print(" r14 ", addr.r14, "\n");
|
||||
print(" r15 ", addr.r15, "\n");
|
||||
print(" r19 ", addr.r19, "\n");
|
||||
print(" r20 ", addr.r20, "\n");
|
||||
print(" r21 ", addr.r21, "\n");
|
||||
print(" r22 ", addr.r22, "\n");
|
||||
print(" r23 ", addr.r23, "\n");
|
||||
print(" r24 ", addr.r24, "\n");
|
||||
print(" r25 ", addr.r25, "\n");
|
||||
print(" r26 ", addr.r26, "\n");
|
||||
print(" r27 ", addr.r27, "\n");
|
||||
print(" r28 ", addr.r28, "\n");
|
||||
print("_12_ {\n");
|
||||
_12_(addr+240);
|
||||
print("}\n");
|
||||
print(" status ", addr.status, "\n");
|
||||
print(" pc ", addr.pc, "\n");
|
||||
print(" r29 ", addr.r29, "\n");
|
||||
print(" r16 ", addr.r16, "\n");
|
||||
print(" r17 ", addr.r17, "\n");
|
||||
print(" r18 ", addr.r18, "\n");
|
||||
};
|
||||
|
||||
defn linkreg(addr)
|
||||
{
|
||||
complex Ureg addr;
|
||||
return addr.r26\X;
|
||||
}
|
||||
|
||||
print("/sys/lib/acid/alpha");
|
||||
|
|
@ -434,10 +434,6 @@ if (map()[2]) != {} then { // map has more than two elements -> active proc
|
|||
if (objtype == "mips" || objtype == "mips2") then {
|
||||
kdir = "ch";
|
||||
}
|
||||
if objtype == "alpha" then {
|
||||
map({"*data", KZERO, 0xffffffff, KZERO});
|
||||
kdir = "alpha";
|
||||
}
|
||||
needacid("proc");
|
||||
needacid("chan");
|
||||
needacid("segment");
|
||||
|
|
|
@ -160,8 +160,6 @@ defn UPCSPRET() {
|
|||
return { code(*(*PC-4) & 0xffff), code(*SP+4), code(*R1) };
|
||||
if objtype == "arm" then
|
||||
return { code(*(*PC-4) & 0xffff), code(*SP+4), code(*R0) }; // untested
|
||||
if objtype == "alpha" then
|
||||
return { code(*(*PC-4) & 0xffff), code(*SP+4), code(*R0) }; // untested
|
||||
}
|
||||
|
||||
defn trapoffset() {
|
||||
|
@ -171,7 +169,6 @@ defn trapoffset() {
|
|||
if objtype == "mips" then return 8;
|
||||
if objtype == "mips2" then return 8;
|
||||
if objtype == "arm" then return 8; // untested
|
||||
if objtype == "alpha" then return 8; // untested
|
||||
}
|
||||
|
||||
defn trapreason() {
|
||||
|
@ -181,7 +178,6 @@ defn trapreason() {
|
|||
if objtype == "mips" then return reason(*CAUSE);
|
||||
if objtype == "mips2" then return reason(*CAUSE);
|
||||
if objtype == "arm" then return "unknown trap"; // untested
|
||||
if objtype == "alpha" then return reason(cause); // untested
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ defn labsp(l)
|
|||
|
||||
defn labstk(l)
|
||||
{
|
||||
_stk(labpc(l), labsp(l), 0, 0);
|
||||
_stk(labpc(l), labsp(l), 0, 1);
|
||||
}
|
||||
|
||||
defn lablstk(l)
|
||||
|
@ -250,7 +250,7 @@ defn threadstks(P){
|
|||
ign = stkignore;
|
||||
stkignore = {
|
||||
"^/sys/src/libthread/",
|
||||
"^/sys/src/libc/(386|arm|alpha|sparc|power|mips)/"
|
||||
"^/sys/src/libc/(386|arm|sparc|power|mips)/"
|
||||
};
|
||||
setproc(P.pid);
|
||||
Tq = (Tqueue)P.threads;
|
||||
|
@ -315,7 +315,7 @@ defn threadstk(T){
|
|||
setproc(P.pid);
|
||||
|
||||
if T.state == Running then{
|
||||
stk();
|
||||
lstk();
|
||||
} else {
|
||||
labstk(T.sched);
|
||||
}
|
||||
|
|
|
@ -116,11 +116,11 @@ defn trumpfninfo() {
|
|||
}
|
||||
|
||||
defn trumpretval() {
|
||||
if objtype=="386" then
|
||||
if objtype=="386" || objtype=="amd64" then
|
||||
return *AX;
|
||||
if objtype=="mips" then
|
||||
return *R1;
|
||||
if objtype=="power" || objtype=="alpha" then
|
||||
if objtype=="power" || objtype=="arm" then
|
||||
return *R0;
|
||||
}
|
||||
|
||||
|
|
|
@ -160,7 +160,7 @@ defn addressof(pattern) {
|
|||
// translate to ape system calls if we have an ape binary
|
||||
if _addressof("_EXITS") != 0 then
|
||||
pattern = trussapecalls[match(pattern, trusscalls)];
|
||||
if regexp("(seek|_SEEK)", pattern) && (objtype=="amd64" || objtype == "power64" || objtype == "alpha") then
|
||||
if regexp("(seek|_SEEK)", pattern) && (objtype=="amd64" || objtype == "power64") then
|
||||
pattern = "_" + pattern;
|
||||
return _addressof(pattern);
|
||||
}
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
dev
|
||||
root
|
||||
cons
|
||||
arch
|
||||
pnp pci
|
||||
env
|
||||
pipe
|
||||
proc
|
||||
mnt
|
||||
srv
|
||||
dup
|
||||
# rtc
|
||||
ssl
|
||||
cap
|
||||
kprof
|
||||
# loopback
|
||||
|
||||
ether netif
|
||||
ip arp chandial inferno ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum
|
||||
|
||||
draw screen vga vgax
|
||||
mouse mouse
|
||||
vga
|
||||
|
||||
sd
|
||||
floppy dma
|
||||
|
||||
audio dma
|
||||
uart
|
||||
|
||||
link
|
||||
ether2114x pci
|
||||
ethermedium
|
||||
|
||||
misc
|
||||
arch164
|
||||
|
||||
sdata pci sdscsi
|
||||
# sd53c8xx pci sdscsi
|
||||
|
||||
uarti8250
|
||||
|
||||
vgargb524 =cur
|
||||
vgas3 +cur
|
||||
vgas3 +cur vgasavage
|
||||
vgatvp3026 =cur
|
||||
|
||||
ip
|
||||
tcp
|
||||
udp
|
||||
ipifc
|
||||
icmp
|
||||
icmp6
|
||||
|
||||
port
|
||||
int cpuserver = 0;
|
||||
|
||||
bootdir
|
||||
/$objtype/bin/paqfs
|
||||
/$objtype/bin/auth/factotum
|
||||
bootfs.paq
|
||||
boot
|
|
@ -1,56 +0,0 @@
|
|||
dev
|
||||
root
|
||||
cons
|
||||
arch
|
||||
pnp pci
|
||||
env
|
||||
pipe
|
||||
proc
|
||||
mnt
|
||||
srv
|
||||
dup
|
||||
# rtc
|
||||
ssl
|
||||
cap
|
||||
kprof
|
||||
# loopback
|
||||
|
||||
ether netif
|
||||
ip arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno
|
||||
|
||||
sd
|
||||
floppy dma
|
||||
|
||||
audio dma
|
||||
uart
|
||||
|
||||
link
|
||||
ether2114x pci
|
||||
ethermedium
|
||||
loopbackmedium
|
||||
|
||||
misc
|
||||
arch164
|
||||
|
||||
sdata pci sdscsi
|
||||
# sd53c8xx pci sdscsi
|
||||
|
||||
uarti8250
|
||||
|
||||
ip
|
||||
tcp
|
||||
udp
|
||||
ipifc
|
||||
icmp
|
||||
icmp6
|
||||
gre
|
||||
ipmux
|
||||
|
||||
port
|
||||
int cpuserver = 1;
|
||||
|
||||
bootdir
|
||||
/$objtype/bin/paqfs
|
||||
/$objtype/bin/auth/factotum
|
||||
bootfs.paq
|
||||
boot
|
|
@ -1,363 +0,0 @@
|
|||
/*
|
||||
* EB164 and similar
|
||||
* CPU: 21164
|
||||
* Core Logic: 21172 CIA or 21174 PYXIS
|
||||
*/
|
||||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
|
||||
static ulong *core;
|
||||
static ulong *wind;
|
||||
|
||||
static ulong windsave[16];
|
||||
static ulong coresave[1];
|
||||
|
||||
ulong iobase0;
|
||||
ulong iobase1;
|
||||
#define iobase(p) (iobase0+(p))
|
||||
|
||||
static int
|
||||
ident(void)
|
||||
{
|
||||
return 0; /* bug! */
|
||||
}
|
||||
|
||||
static uvlong* sgmap;
|
||||
|
||||
static void
|
||||
sginit(void)
|
||||
{
|
||||
ulong pa;
|
||||
uvlong *pte;
|
||||
|
||||
sgmap = xspanalloc(BY2PG, BY2PG, 0);
|
||||
memset(sgmap, 0, BY2PG);
|
||||
|
||||
/*
|
||||
* Prepare scatter-gather map for 0-8MB.
|
||||
*/
|
||||
pte = sgmap;
|
||||
for(pa = 0; pa < 8*1024*1024; pa += BY2PG)
|
||||
*pte++ = ((pa>>PGSHIFT)<<1)|1;
|
||||
|
||||
/*
|
||||
* Set up a map for ISA DMA accesses to physical memory.
|
||||
* Addresses presented by an ISA device between ISAWINDOW
|
||||
* and ISAWINDOW+8MB will be translated to between 0 and
|
||||
* 0+8MB of physical memory.
|
||||
*/
|
||||
wind[0x400/4] = ISAWINDOW|2|1; /* window base */
|
||||
wind[0x440/4] = 0x00700000; /* window mask */
|
||||
wind[0x480/4] = PADDR(sgmap)>>2; /* <33:10> of sg map */
|
||||
|
||||
wind[0x100/4] = 3; /* invalidate tlb cache */
|
||||
}
|
||||
|
||||
static void *
|
||||
kmapio(ulong space, ulong offset, int size)
|
||||
{
|
||||
return kmapv(((uvlong)space<<32LL)|offset, size);
|
||||
}
|
||||
|
||||
static void
|
||||
coreinit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
core = kmapio(0x87, 0x40000000, 0x10000);
|
||||
wind = kmapio(0x87, 0x60000000, 0x1000);
|
||||
|
||||
iobase0 = (ulong)kmapio(0x89, 0, 0x20000);
|
||||
|
||||
/* hae_io = core[0x440/4];
|
||||
iobase1 = (ulong)kmapio(0x89, hae_io, 0x10000); */
|
||||
|
||||
/* save critical parts of hardware memory mapping */
|
||||
for (i = 4; i < 8; i++) {
|
||||
windsave[4*(i-4)+0] = wind[(i*0x100+0x00)/4];
|
||||
windsave[4*(i-4)+1] = wind[(i*0x100+0x40)/4];
|
||||
windsave[4*(i-4)+2] = wind[(i*0x100+0x80)/4];
|
||||
}
|
||||
coresave[0] = core[0x140/4];
|
||||
|
||||
/* disable windows */
|
||||
wind[0x400/4] = 0;
|
||||
wind[0x500/4] = 0;
|
||||
wind[0x600/4] = 0;
|
||||
wind[0x700/4] = 0;
|
||||
|
||||
sginit();
|
||||
|
||||
/*
|
||||
* Set up a map for PCI DMA accesses to physical memory.
|
||||
* Addresses presented by a PCI device between PCIWINDOW
|
||||
* and PCIWINDOW+1GB will be translated to between 0 and
|
||||
* 0+1GB of physical memory.
|
||||
*/
|
||||
wind[0x500/4] = PCIWINDOW|1;
|
||||
wind[0x540/4] = 0x3ff00000;
|
||||
wind[0x580/4] = 0;
|
||||
|
||||
/* clear error state */
|
||||
core[0x8200/4] = 0x7ff;
|
||||
|
||||
/* set config: byte/word enable, no monster window, etc. */
|
||||
core[0x140/4] = 0x21;
|
||||
|
||||
/* turn off mcheck on master abort. now we can probe PCI space. */
|
||||
core[0x8280/4] &= ~(1<<7);
|
||||
|
||||
/* set up interrupts. */
|
||||
i8259init();
|
||||
cserve(52, 4); /* enable SIO interrupt */
|
||||
}
|
||||
|
||||
void
|
||||
ciaerror(void)
|
||||
{
|
||||
print("cia error 0x%luX\n", core[0x8200/4]);
|
||||
}
|
||||
|
||||
static void
|
||||
corehello(void)
|
||||
{
|
||||
print("cpu%d: CIA revision %ld; cnfg %lux cntrl %lux\n",
|
||||
0, /* BUG */
|
||||
core[0x80/4] & 0x7f, core[0x140/4], core[0x100/4]);
|
||||
print("cpu%d: HAE_IO %lux\n", 0, core[0x440/4]);
|
||||
print("\n");
|
||||
}
|
||||
|
||||
static void
|
||||
coredetach(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 4; i < 8; i++) {
|
||||
wind[(i*0x100+0x00)/4] = windsave[4*(i-4)+0];
|
||||
wind[(i*0x100+0x40)/4] = windsave[4*(i-4)+1];
|
||||
wind[(i*0x100+0x80)/4] = windsave[4*(i-4)+2];
|
||||
}
|
||||
core[0x140/4] = coresave[0];
|
||||
/* for (i = 0; i < 4; i++)
|
||||
if (i != 4)
|
||||
cserve(53, i); /* disable interrupts */
|
||||
}
|
||||
|
||||
static Lock pcicfgl;
|
||||
static ulong pcimap[256];
|
||||
|
||||
static void*
|
||||
pcicfg2117x(int tbdf, int rno)
|
||||
{
|
||||
int space, bus;
|
||||
ulong base;
|
||||
|
||||
bus = BUSBNO(tbdf);
|
||||
lock(&pcicfgl);
|
||||
base = pcimap[bus];
|
||||
if (base == 0) {
|
||||
if(bus)
|
||||
space = 0x8B;
|
||||
else
|
||||
space = 0x8A;
|
||||
pcimap[bus] = base = (ulong)kmapio(space, MKBUS(0, bus, 0, 0), (1<<16));
|
||||
}
|
||||
unlock(&pcicfgl);
|
||||
return (void*)(base + BUSDF(tbdf) + rno);
|
||||
}
|
||||
|
||||
static void*
|
||||
pcimem2117x(int addr, int len)
|
||||
{
|
||||
return kmapio(0x88, addr, len);
|
||||
}
|
||||
|
||||
static int
|
||||
intrenable164(Vctl *v)
|
||||
{
|
||||
int vec, irq;
|
||||
|
||||
irq = v->irq;
|
||||
if(irq > MaxIrqPIC) {
|
||||
print("intrenable: irq %d out of range\n", v->irq);
|
||||
return -1;
|
||||
}
|
||||
if(BUSTYPE(v->tbdf) == BusPCI) {
|
||||
vec = irq+VectorPCI;
|
||||
cserve(52, irq);
|
||||
}
|
||||
else {
|
||||
vec = irq+VectorPIC;
|
||||
if(i8259enable(irq, v->tbdf, v) == -1)
|
||||
return -1;
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
/*
|
||||
* I have a function pointer in PCArch for every one of these, because on
|
||||
* some Alphas we have to use sparse mode, but on others we can use
|
||||
* MOVB et al. Additionally, the PC164 documentation threatened us
|
||||
* with the lie that the SIO is in region B, but everything else in region A.
|
||||
* This turned out not to be the case. Given the cost of this solution, it
|
||||
* may be better just to use sparse mode for I/O space on all platforms.
|
||||
*/
|
||||
int
|
||||
inb2117x(int port)
|
||||
{
|
||||
mb();
|
||||
return *(uchar*)(iobase(port));
|
||||
}
|
||||
|
||||
ushort
|
||||
ins2117x(int port)
|
||||
{
|
||||
mb();
|
||||
return *(ushort*)(iobase(port));
|
||||
}
|
||||
|
||||
ulong
|
||||
inl2117x(int port)
|
||||
{
|
||||
mb();
|
||||
return *(ulong*)(iobase(port));
|
||||
}
|
||||
|
||||
void
|
||||
outb2117x(int port, int val)
|
||||
{
|
||||
mb();
|
||||
*(uchar*)(iobase(port)) = val;
|
||||
mb();
|
||||
}
|
||||
|
||||
void
|
||||
outs2117x(int port, ushort val)
|
||||
{
|
||||
mb();
|
||||
*(ushort*)(iobase(port)) = val;
|
||||
mb();
|
||||
}
|
||||
|
||||
void
|
||||
outl2117x(int port, ulong val)
|
||||
{
|
||||
mb();
|
||||
*(ulong*)(iobase(port)) = val;
|
||||
mb();
|
||||
}
|
||||
|
||||
void
|
||||
insb2117x(int port, void *buf, int len)
|
||||
{
|
||||
int i;
|
||||
uchar *p, *q;
|
||||
|
||||
p = (uchar*)iobase(port);
|
||||
q = buf;
|
||||
for(i = 0; i < len; i++){
|
||||
mb();
|
||||
*q++ = *p;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
inss2117x(int port, void *buf, int len)
|
||||
{
|
||||
int i;
|
||||
ushort *p, *q;
|
||||
|
||||
p = (ushort*)iobase(port);
|
||||
q = buf;
|
||||
for(i = 0; i < len; i++){
|
||||
mb();
|
||||
*q++ = *p;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
insl2117x(int port, void *buf, int len)
|
||||
{
|
||||
int i;
|
||||
ulong *p, *q;
|
||||
|
||||
p = (ulong*)iobase(port);
|
||||
q = buf;
|
||||
for(i = 0; i < len; i++){
|
||||
mb();
|
||||
*q++ = *p;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
outsb2117x(int port, void *buf, int len)
|
||||
{
|
||||
int i;
|
||||
uchar *p, *q;
|
||||
|
||||
p = (uchar*)iobase(port);
|
||||
q = buf;
|
||||
for(i = 0; i < len; i++){
|
||||
mb();
|
||||
*p = *q++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
outss2117x(int port, void *buf, int len)
|
||||
{
|
||||
int i;
|
||||
ushort *p, *q;
|
||||
|
||||
p = (ushort*)iobase(port);
|
||||
q = buf;
|
||||
for(i = 0; i < len; i++){
|
||||
mb();
|
||||
*p = *q++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
outsl2117x(int port, void *buf, int len)
|
||||
{
|
||||
int i;
|
||||
ulong *p, *q;
|
||||
|
||||
p = (ulong*)iobase(port);
|
||||
q = buf;
|
||||
for(i = 0; i < len; i++){
|
||||
mb();
|
||||
*p = *q++;
|
||||
}
|
||||
}
|
||||
|
||||
PCArch arch164 = {
|
||||
"EB164",
|
||||
ident,
|
||||
coreinit,
|
||||
corehello,
|
||||
coredetach,
|
||||
pcicfg2117x,
|
||||
pcimem2117x,
|
||||
intrenable164,
|
||||
nil,
|
||||
nil,
|
||||
|
||||
inb2117x,
|
||||
ins2117x,
|
||||
inl2117x,
|
||||
outb2117x,
|
||||
outs2117x,
|
||||
outl2117x,
|
||||
insb2117x,
|
||||
inss2117x,
|
||||
insl2117x,
|
||||
outsb2117x,
|
||||
outss2117x,
|
||||
outsl2117x,
|
||||
};
|
|
@ -1,16 +0,0 @@
|
|||
enum
|
||||
{
|
||||
Bufsize = 16*1024, /* 92 ms each */
|
||||
Nbuf = 16, /* 1.5 seconds total */
|
||||
Dma = 5,
|
||||
IrqAUDIO = 5,
|
||||
SBswab = 0,
|
||||
};
|
||||
|
||||
#define seteisadma(a, b) dmainit(a, Bufsize);
|
||||
#define CACHELINESZ 128
|
||||
#define UNCACHED(type, v) (type*)((ulong)(v))
|
||||
#define dcflush(a, b)
|
||||
|
||||
#define Int0vec
|
||||
#define setvec(v, f, a) intrenable(v, f, a, BUSUNKNOWN, "audio")
|
|
@ -1,71 +0,0 @@
|
|||
typedef struct Hwrpb Hwrpb;
|
||||
typedef struct Hwcpu Hwcpu;
|
||||
typedef struct Hwdsr Hwdsr;
|
||||
|
||||
struct Hwrpb
|
||||
{
|
||||
uvlong phys;
|
||||
uvlong sign;
|
||||
uvlong rev;
|
||||
uvlong size;
|
||||
uvlong cpu0;
|
||||
uvlong by2pg;
|
||||
uvlong pabits;
|
||||
uvlong maxasn;
|
||||
char ssn[16];
|
||||
uvlong systype;
|
||||
uvlong sysvar;
|
||||
uvlong sysrev;
|
||||
uvlong ifreq;
|
||||
uvlong cfreq;
|
||||
uvlong vptb;
|
||||
uvlong resv;
|
||||
uvlong tbhint;
|
||||
uvlong ncpu;
|
||||
uvlong cpulen;
|
||||
uvlong cpuoff;
|
||||
uvlong nctb;
|
||||
uvlong ctblen;
|
||||
uvlong ctboff;
|
||||
uvlong ccrboff;
|
||||
uvlong memoff;
|
||||
uvlong confoff;
|
||||
uvlong fruoff;
|
||||
uvlong termsaveva;
|
||||
uvlong termsavex;
|
||||
uvlong termrestva;
|
||||
uvlong termrestx;
|
||||
uvlong termresetva;
|
||||
uvlong termresetx;
|
||||
uvlong sysresv;
|
||||
uvlong hardresv;
|
||||
uvlong csum;
|
||||
uvlong rxrdymsk;
|
||||
uvlong txrdymsk;
|
||||
uvlong dsroff; /* rev 6 or higher */
|
||||
};
|
||||
|
||||
extern Hwrpb* hwrpb;
|
||||
|
||||
struct Hwcpu
|
||||
{
|
||||
uvlong hwpcb[16];
|
||||
uvlong state;
|
||||
uvlong palmainlen;
|
||||
uvlong palscratchlen;
|
||||
uvlong palmainpa;
|
||||
uvlong palscratchpa;
|
||||
uvlong palrev;
|
||||
uvlong cputype;
|
||||
uvlong cpuvar;
|
||||
uvlong cpurev;
|
||||
uvlong serial[2];
|
||||
/* more crap ... */
|
||||
};
|
||||
|
||||
struct Hwdsr
|
||||
{
|
||||
vlong smm;
|
||||
uvlong lurtoff;
|
||||
uvlong sysnameoff;
|
||||
};
|
|
@ -1,113 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "../port/error.h"
|
||||
#include "io.h"
|
||||
|
||||
enum {
|
||||
Width = 160,
|
||||
Height = 25,
|
||||
|
||||
Attr = 0x4f, /* white on blue */
|
||||
};
|
||||
|
||||
static ulong cgabase;
|
||||
#define CGASCREENBASE ((uchar*)cgabase)
|
||||
|
||||
static int cgapos;
|
||||
static int screeninitdone;
|
||||
static Lock cgascreenlock;
|
||||
|
||||
static uchar
|
||||
cgaregr(int index)
|
||||
{
|
||||
outb(0x3D4, index);
|
||||
return inb(0x3D4+1) & 0xFF;
|
||||
}
|
||||
|
||||
static void
|
||||
cgaregw(int index, int data)
|
||||
{
|
||||
outb(0x3D4, index);
|
||||
outb(0x3D4+1, data);
|
||||
}
|
||||
|
||||
static void
|
||||
movecursor(void)
|
||||
{
|
||||
cgaregw(0x0E, (cgapos/2>>8) & 0xFF);
|
||||
cgaregw(0x0F, cgapos/2 & 0xFF);
|
||||
CGASCREENBASE[cgapos+1] = Attr;
|
||||
}
|
||||
|
||||
static void
|
||||
cgascreenputc(int c)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(c == '\n'){
|
||||
cgapos = cgapos/Width;
|
||||
cgapos = (cgapos+1)*Width;
|
||||
}
|
||||
else if(c == '\t'){
|
||||
i = 8 - ((cgapos/2)&7);
|
||||
while(i-->0)
|
||||
cgascreenputc(' ');
|
||||
}
|
||||
else if(c == '\b'){
|
||||
if(cgapos >= 2)
|
||||
cgapos -= 2;
|
||||
cgascreenputc(' ');
|
||||
cgapos -= 2;
|
||||
}
|
||||
else{
|
||||
CGASCREENBASE[cgapos++] = c;
|
||||
CGASCREENBASE[cgapos++] = Attr;
|
||||
}
|
||||
if(cgapos >= Width*Height){
|
||||
memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
|
||||
for (i = Width*(Height-1); i < Width*Height;) {
|
||||
CGASCREENBASE[i++] = 0x20;
|
||||
CGASCREENBASE[i++] = Attr;
|
||||
}
|
||||
cgapos = Width*(Height-1);
|
||||
}
|
||||
movecursor();
|
||||
}
|
||||
|
||||
void
|
||||
screeninit(void)
|
||||
{
|
||||
cgabase = (ulong)arch->pcimem(0xB8000, 0x8000);
|
||||
|
||||
cgapos = cgaregr(0x0E)<<8;
|
||||
cgapos |= cgaregr(0x0F);
|
||||
cgapos *= 2;
|
||||
screeninitdone = 1;
|
||||
}
|
||||
|
||||
static void
|
||||
cgascreenputs(char* s, int n)
|
||||
{
|
||||
if(!screeninitdone)
|
||||
return;
|
||||
if(!islo()){
|
||||
/*
|
||||
* Don't deadlock trying to
|
||||
* print in an interrupt.
|
||||
*/
|
||||
if(!canlock(&cgascreenlock))
|
||||
return;
|
||||
}
|
||||
else
|
||||
lock(&cgascreenlock);
|
||||
|
||||
while(n-- > 0)
|
||||
cgascreenputc(*s++);
|
||||
|
||||
unlock(&cgascreenlock);
|
||||
}
|
||||
|
||||
void (*screenputs)(char*, int) = cgascreenputs;
|
|
@ -1,112 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
#include "axp.h"
|
||||
#include "ureg.h"
|
||||
|
||||
void
|
||||
clockinit(void)
|
||||
{
|
||||
}
|
||||
|
||||
uvlong
|
||||
cycletimer(void)
|
||||
{
|
||||
ulong pcc;
|
||||
vlong delta;
|
||||
|
||||
pcc = rpcc(nil) & 0xFFFFFFFF;
|
||||
if(m->cpuhz == 0){
|
||||
/*
|
||||
* pcclast is needed to detect wraparound of
|
||||
* the cycle timer which is only 32-bits.
|
||||
* m->cpuhz is set from the info passed from
|
||||
* the firmware.
|
||||
* This could be in clockinit if can
|
||||
* guarantee no wraparound between then and now.
|
||||
*
|
||||
* All the clock stuff needs work.
|
||||
*/
|
||||
m->cpuhz = hwrpb->cfreq;
|
||||
m->pcclast = pcc;
|
||||
}
|
||||
delta = pcc - m->pcclast;
|
||||
if(delta < 0)
|
||||
delta += 0x100000000LL;
|
||||
m->pcclast = pcc;
|
||||
m->fastclock += delta;
|
||||
|
||||
return MACHP(0)->fastclock;
|
||||
}
|
||||
|
||||
uvlong
|
||||
fastticks(uvlong* hz)
|
||||
{
|
||||
uvlong ticks;
|
||||
int x;
|
||||
|
||||
x = splhi();
|
||||
ticks = cycletimer();
|
||||
splx(x);
|
||||
|
||||
if(hz)
|
||||
*hz = m->cpuhz;
|
||||
|
||||
return ticks;
|
||||
}
|
||||
|
||||
ulong
|
||||
µs(void)
|
||||
{
|
||||
return fastticks2us(cycletimer());
|
||||
}
|
||||
|
||||
/*
|
||||
* performance measurement ticks. must be low overhead.
|
||||
* doesn't have to count over a second.
|
||||
*/
|
||||
ulong
|
||||
perfticks(void)
|
||||
{
|
||||
return rpcc(nil);
|
||||
}
|
||||
|
||||
void
|
||||
timerset(Tval)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
microdelay(int us)
|
||||
{
|
||||
uvlong eot;
|
||||
|
||||
eot = fastticks(nil) + (m->cpuhz/1000000)*us;
|
||||
while(fastticks(nil) < eot)
|
||||
;
|
||||
}
|
||||
|
||||
void
|
||||
delay(int millisecs)
|
||||
{
|
||||
microdelay(millisecs*1000);
|
||||
}
|
||||
|
||||
void
|
||||
clock(Ureg *ureg)
|
||||
{
|
||||
static int count;
|
||||
|
||||
cycletimer();
|
||||
|
||||
/* HZ == 100, timer == 1024Hz. error < 1ms */
|
||||
count += 100;
|
||||
if (count < 1024)
|
||||
return;
|
||||
count -= 1024;
|
||||
|
||||
timerintr(ureg, 0);
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
|
||||
int
|
||||
havetimer(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
timeradd(Timer *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
timerdel(Timer *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
clockintrsched(void)
|
||||
{
|
||||
}
|
|
@ -1,265 +0,0 @@
|
|||
typedef struct Conf Conf;
|
||||
typedef struct Confmem Confmem;
|
||||
typedef struct FPsave FPsave;
|
||||
typedef struct ISAConf ISAConf;
|
||||
typedef struct Label Label;
|
||||
typedef struct Lock Lock;
|
||||
typedef struct Mach Mach;
|
||||
typedef struct Notsave Notsave;
|
||||
typedef struct Page Page;
|
||||
typedef struct PCArch PCArch;
|
||||
typedef struct PCB PCB;
|
||||
typedef struct Pcidev Pcidev;
|
||||
typedef struct PMMU PMMU;
|
||||
typedef struct Proc Proc;
|
||||
typedef struct Sys Sys;
|
||||
typedef struct Ureg Ureg;
|
||||
typedef struct Vctl Vctl;
|
||||
typedef vlong Tval;
|
||||
|
||||
#define MAXSYSARG 6 /* for mount(fd, mpt, flag, arg, srv) */
|
||||
|
||||
/*
|
||||
* parameters for sysproc.c
|
||||
*/
|
||||
#define AOUT_MAGIC L_MAGIC
|
||||
|
||||
/*
|
||||
* machine dependent definitions used by ../port/dat.h
|
||||
*/
|
||||
|
||||
struct Lock
|
||||
{
|
||||
ulong key; /* semaphore (non-zero = locked) */
|
||||
ulong sr;
|
||||
ulong pc;
|
||||
Proc *p;
|
||||
Mach *m;
|
||||
ulong pid;
|
||||
ushort isilock;
|
||||
};
|
||||
|
||||
struct Label
|
||||
{
|
||||
ulong sp;
|
||||
ulong pc;
|
||||
};
|
||||
|
||||
/*
|
||||
* Proc.fpstate
|
||||
*/
|
||||
enum
|
||||
{
|
||||
/* floating point states */
|
||||
FPinit,
|
||||
FPactive,
|
||||
FPinactive,
|
||||
|
||||
/* bit or'd with the state */
|
||||
FPillegal= 0x100,
|
||||
};
|
||||
|
||||
struct FPsave
|
||||
{
|
||||
long fpreg[2*32];
|
||||
long dummy; /* lower bits of FPCR, useless */
|
||||
long fpstatus;
|
||||
};
|
||||
|
||||
struct Confmem
|
||||
{
|
||||
ulong base;
|
||||
ulong npage;
|
||||
ulong kbase;
|
||||
ulong klimit;
|
||||
};
|
||||
|
||||
struct Conf
|
||||
{
|
||||
ulong nmach; /* processors */
|
||||
ulong nproc; /* processes */
|
||||
Confmem mem[2];
|
||||
ulong npage; /* total physical pages of memory */
|
||||
ulong upages; /* user page pool */
|
||||
ulong nimage; /* number of page cache image headers */
|
||||
ulong nswap; /* number of swap pages */
|
||||
int nswppo; /* max # of pageouts per segment pass */
|
||||
ulong copymode; /* 0 is copy on write, 1 is copy on reference */
|
||||
int monitor; /* has display? */
|
||||
ulong ialloc; /* bytes available for interrupt time allocation */
|
||||
ulong pipeqsize; /* size in bytes of pipe queues */
|
||||
};
|
||||
|
||||
/*
|
||||
* mmu goo in the Proc structure
|
||||
*/
|
||||
struct PMMU
|
||||
{
|
||||
Page *mmutop; /* 1st level table */
|
||||
Page *mmulvl2; /* 2nd level table */
|
||||
Page *mmufree; /* unused page table pages */
|
||||
Page *mmuused; /* used page table pages, except for mmustk */
|
||||
};
|
||||
|
||||
/*
|
||||
* things saved in the Proc structure during a notify
|
||||
*/
|
||||
struct Notsave
|
||||
{
|
||||
ulong UNUSED;
|
||||
};
|
||||
|
||||
#include "../port/portdat.h"
|
||||
|
||||
/*
|
||||
* machine dependent definitions not used by ../port/dat.h
|
||||
*/
|
||||
/*
|
||||
* Fake kmap
|
||||
*/
|
||||
typedef void KMap;
|
||||
#define VA(k) ((ulong)(k))
|
||||
#define kmap(p) (KMap*)((p)->pa|KZERO)
|
||||
#define kunmap(k)
|
||||
|
||||
/*
|
||||
* Process Control Block, used by PALcode
|
||||
*/
|
||||
struct PCB {
|
||||
uvlong ksp;
|
||||
uvlong usp;
|
||||
uvlong ptbr;
|
||||
ulong asn;
|
||||
ulong pcc;
|
||||
uvlong unique;
|
||||
ulong fen;
|
||||
ulong dummy;
|
||||
uvlong rsrv1;
|
||||
uvlong rsrv2;
|
||||
};
|
||||
|
||||
struct Mach
|
||||
{
|
||||
/* OFFSETS OF THE FOLLOWING KNOWN BY l.s */
|
||||
int machno; /* physical id of processor */
|
||||
ulong splpc; /* pc that called splhi() */
|
||||
Proc *proc; /* current process on this processor */
|
||||
|
||||
/* ordering from here on irrelevant */
|
||||
|
||||
ulong ticks; /* of the clock since boot time */
|
||||
Label sched; /* scheduler wakeup */
|
||||
Lock alarmlock; /* access to alarm list */
|
||||
void *alarm; /* alarms bound to this clock */
|
||||
int inclockintr;
|
||||
|
||||
Proc* readied; /* for runproc */
|
||||
ulong schedticks; /* next forced context switch */
|
||||
|
||||
vlong cpuhz; /* hwrpb->cfreq */
|
||||
uvlong cyclefreq; /* Frequency of user readable cycle counter */
|
||||
ulong pcclast;
|
||||
uvlong fastclock;
|
||||
Perf perf; /* performance counters */
|
||||
|
||||
int tlbfault; /* only used by devproc; no access to tlb */
|
||||
int tlbpurge; /* ... */
|
||||
int pfault;
|
||||
int cs;
|
||||
int syscall;
|
||||
int load;
|
||||
int intr;
|
||||
int flushmmu; /* make current proc flush it's mmu state */
|
||||
int ilockdepth;
|
||||
|
||||
ulong spuriousintr;
|
||||
int lastintr;
|
||||
|
||||
PCB;
|
||||
|
||||
/* MUST BE LAST */
|
||||
int stack[1];
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
Lock;
|
||||
char machs[MAXMACH];
|
||||
int exiting;
|
||||
}active;
|
||||
|
||||
/*
|
||||
* Implementation-dependant functions (outside of Alpha architecture proper).
|
||||
* Called PCArch because that's what mkdevc calls it (for the PC).
|
||||
*/
|
||||
struct PCArch
|
||||
{
|
||||
char* id;
|
||||
int (*ident)(void);
|
||||
|
||||
void (*coreinit)(void); /* set up core logic, PCI mappings etc */
|
||||
void (*corehello)(void); /* identify core logic to user */
|
||||
void (*coredetach)(void); /* restore core logic before return to console */
|
||||
void *(*pcicfg)(int, int); /* map and point to PCI cfg space */
|
||||
void *(*pcimem)(int, int); /* map and point to PCI memory space */
|
||||
int (*intrenable)(Vctl*);
|
||||
int (*intrvecno)(int);
|
||||
int (*intrdisable)(int);
|
||||
|
||||
int (*_inb)(int);
|
||||
ushort (*_ins)(int);
|
||||
ulong (*_inl)(int);
|
||||
void (*_outb)(int, int);
|
||||
void (*_outs)(int, ushort);
|
||||
void (*_outl)(int, ulong);
|
||||
void (*_insb)(int, void*, int);
|
||||
void (*_inss)(int, void*, int);
|
||||
void (*_insl)(int, void*, int);
|
||||
void (*_outsb)(int, void*, int);
|
||||
void (*_outss)(int, void*, int);
|
||||
void (*_outsl)(int, void*, int);
|
||||
};
|
||||
|
||||
/*
|
||||
* a parsed plan9.ini line
|
||||
*/
|
||||
#define NISAOPT 8
|
||||
|
||||
struct ISAConf {
|
||||
char *type;
|
||||
ulong port;
|
||||
int irq;
|
||||
ulong dma;
|
||||
ulong mem;
|
||||
ulong size;
|
||||
ulong freq;
|
||||
|
||||
int nopt;
|
||||
char *opt[NISAOPT];
|
||||
};
|
||||
|
||||
extern PCArch *arch;
|
||||
|
||||
#define MACHP(n) ((Mach *)((int)&mach0+n*BY2PG))
|
||||
extern Mach mach0;
|
||||
|
||||
extern register Mach *m;
|
||||
extern register Proc *up;
|
||||
|
||||
/*
|
||||
* hardware info about a device
|
||||
*/
|
||||
typedef struct {
|
||||
ulong port;
|
||||
int size;
|
||||
} Devport;
|
||||
|
||||
struct DevConf
|
||||
{
|
||||
ulong intnum; /* interrupt number */
|
||||
char *type; /* card type, malloced */
|
||||
int nports; /* Number of ports */
|
||||
Devport *ports; /* The ports themselves */
|
||||
};
|
||||
|
||||
extern FPsave initfp;
|
|
@ -1,533 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
#include "../port/error.h"
|
||||
#include "axp.h"
|
||||
|
||||
typedef struct IOMap IOMap;
|
||||
struct IOMap
|
||||
{
|
||||
IOMap *next;
|
||||
char tag[13];
|
||||
ulong start;
|
||||
ulong end;
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
Lock;
|
||||
IOMap *m;
|
||||
IOMap *free;
|
||||
IOMap maps[32]; // some initial free maps
|
||||
|
||||
QLock ql; // lock for reading map
|
||||
} iomap;
|
||||
|
||||
enum {
|
||||
Qdir = 0,
|
||||
Qioalloc = 1,
|
||||
Qiob,
|
||||
Qiow,
|
||||
Qiol,
|
||||
Qbase,
|
||||
|
||||
Qmax = 16,
|
||||
};
|
||||
|
||||
typedef long Rdwrfn(Chan*, void*, long, vlong);
|
||||
|
||||
static Rdwrfn *readfn[Qmax];
|
||||
static Rdwrfn *writefn[Qmax];
|
||||
|
||||
static Dirtab archdir[] = {
|
||||
".", { Qdir, 0, QTDIR }, 0, 0555,
|
||||
"ioalloc", { Qioalloc, 0 }, 0, 0444,
|
||||
"iob", { Qiob, 0 }, 0, 0660,
|
||||
"iow", { Qiow, 0 }, 0, 0660,
|
||||
"iol", { Qiol, 0 }, 0, 0660,
|
||||
};
|
||||
Lock archwlock; /* the lock is only for changing archdir */
|
||||
int narchdir = Qbase;
|
||||
int (*_pcmspecial)(char *, ISAConf *);
|
||||
void (*_pcmspecialclose)(int);
|
||||
|
||||
/*
|
||||
* Add a file to the #P listing. Once added, you can't delete it.
|
||||
* You can't add a file with the same name as one already there,
|
||||
* and you get a pointer to the Dirtab entry so you can do things
|
||||
* like change the Qid version. Changing the Qid path is disallowed.
|
||||
*/
|
||||
Dirtab*
|
||||
addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
|
||||
{
|
||||
int i;
|
||||
Dirtab d;
|
||||
Dirtab *dp;
|
||||
|
||||
memset(&d, 0, sizeof d);
|
||||
strcpy(d.name, name);
|
||||
d.perm = perm;
|
||||
|
||||
lock(&archwlock);
|
||||
if(narchdir >= Qmax){
|
||||
unlock(&archwlock);
|
||||
return nil;
|
||||
}
|
||||
|
||||
for(i=0; i<narchdir; i++)
|
||||
if(strcmp(archdir[i].name, name) == 0){
|
||||
unlock(&archwlock);
|
||||
return nil;
|
||||
}
|
||||
|
||||
d.qid.path = narchdir;
|
||||
archdir[narchdir] = d;
|
||||
readfn[narchdir] = rdfn;
|
||||
writefn[narchdir] = wrfn;
|
||||
dp = &archdir[narchdir++];
|
||||
unlock(&archwlock);
|
||||
|
||||
return dp;
|
||||
}
|
||||
|
||||
void
|
||||
ioinit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nelem(iomap.maps)-1; i++)
|
||||
iomap.maps[i].next = &iomap.maps[i+1];
|
||||
iomap.maps[i].next = nil;
|
||||
iomap.free = iomap.maps;
|
||||
|
||||
// a dummy entry at 2^17
|
||||
ioalloc(0x20000, 1, 0, "dummy");
|
||||
}
|
||||
|
||||
//
|
||||
// alloc some io port space and remember who it was
|
||||
// alloced to. if port < 0, find a free region.
|
||||
//
|
||||
int
|
||||
ioalloc(int port, int size, int align, char *tag)
|
||||
{
|
||||
IOMap *m, **l;
|
||||
int i;
|
||||
|
||||
lock(&iomap);
|
||||
if(port < 0){
|
||||
// find a free port above 0x400 and below 0x1000
|
||||
port = 0x400;
|
||||
for(l = &iomap.m; *l; l = &(*l)->next){
|
||||
m = *l;
|
||||
i = m->start - port;
|
||||
if(i > size)
|
||||
break;
|
||||
if(align > 0)
|
||||
port = ((port+align-1)/align)*align;
|
||||
else
|
||||
port = m->end;
|
||||
}
|
||||
if(*l == nil){
|
||||
unlock(&iomap);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
// see if the space clashes with previously allocated ports
|
||||
for(l = &iomap.m; *l; l = &(*l)->next){
|
||||
m = *l;
|
||||
if(m->end <= port)
|
||||
continue;
|
||||
if(m->start >= port+size)
|
||||
break;
|
||||
unlock(&iomap);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
m = iomap.free;
|
||||
if(m == nil){
|
||||
print("ioalloc: out of maps");
|
||||
unlock(&iomap);
|
||||
return port;
|
||||
}
|
||||
iomap.free = m->next;
|
||||
m->next = *l;
|
||||
m->start = port;
|
||||
m->end = port + size;
|
||||
strncpy(m->tag, tag, sizeof(m->tag));
|
||||
m->tag[sizeof(m->tag)-1] = 0;
|
||||
*l = m;
|
||||
|
||||
archdir[0].qid.vers++;
|
||||
|
||||
unlock(&iomap);
|
||||
return m->start;
|
||||
}
|
||||
|
||||
void
|
||||
iofree(int port)
|
||||
{
|
||||
IOMap *m, **l;
|
||||
|
||||
lock(&iomap);
|
||||
for(l = &iomap.m; *l; l = &(*l)->next){
|
||||
if((*l)->start == port){
|
||||
m = *l;
|
||||
*l = m->next;
|
||||
m->next = iomap.free;
|
||||
iomap.free = m;
|
||||
break;
|
||||
}
|
||||
if((*l)->start > port)
|
||||
break;
|
||||
}
|
||||
archdir[0].qid.vers++;
|
||||
unlock(&iomap);
|
||||
}
|
||||
|
||||
int
|
||||
iounused(int start, int end)
|
||||
{
|
||||
IOMap *m;
|
||||
|
||||
for(m = iomap.m; m; m = m->next){
|
||||
if(start >= m->start && start < m->end
|
||||
|| start <= m->start && end > m->start)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
checkport(int start, int end)
|
||||
{
|
||||
/* standard vga regs are OK */
|
||||
if(start >= 0x2b0 && end <= 0x2df+1)
|
||||
return;
|
||||
if(start >= 0x3c0 && end <= 0x3da+1)
|
||||
return;
|
||||
|
||||
if(iounused(start, end))
|
||||
return;
|
||||
error(Eperm);
|
||||
}
|
||||
|
||||
static Chan*
|
||||
archattach(char* spec)
|
||||
{
|
||||
return devattach('P', spec);
|
||||
}
|
||||
|
||||
Walkqid*
|
||||
archwalk(Chan* c, Chan *nc, char** name, int nname)
|
||||
{
|
||||
return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
|
||||
}
|
||||
|
||||
static int
|
||||
archstat(Chan* c, uchar* dp, int n)
|
||||
{
|
||||
return devstat(c, dp, n, archdir, narchdir, devgen);
|
||||
}
|
||||
|
||||
static Chan*
|
||||
archopen(Chan* c, int omode)
|
||||
{
|
||||
return devopen(c, omode, archdir, nelem(archdir), devgen);
|
||||
}
|
||||
|
||||
static void
|
||||
archclose(Chan*)
|
||||
{
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
Linelen= 31,
|
||||
};
|
||||
|
||||
static long
|
||||
archread(Chan *c, void *a, long n, vlong offset)
|
||||
{
|
||||
char buf[Linelen+1], *p;
|
||||
int port;
|
||||
ushort *sp;
|
||||
ulong *lp;
|
||||
IOMap *m;
|
||||
Rdwrfn *fn;
|
||||
|
||||
switch((ulong)c->qid.path){
|
||||
|
||||
case Qdir:
|
||||
return devdirread(c, a, n, archdir, nelem(archdir), devgen);
|
||||
|
||||
case Qiob:
|
||||
port = offset;
|
||||
checkport(offset, offset+n);
|
||||
for(p = a; port < offset+n; port++)
|
||||
*p++ = inb(port);
|
||||
return n;
|
||||
|
||||
case Qiow:
|
||||
if((n & 0x01) || (offset & 0x01))
|
||||
error(Ebadarg);
|
||||
checkport(offset, offset+n+1);
|
||||
n /= 2;
|
||||
sp = a;
|
||||
for(port = offset; port < offset+n; port += 2)
|
||||
*sp++ = ins(port);
|
||||
return n*2;
|
||||
|
||||
case Qiol:
|
||||
if((n & 0x03) || (offset & 0x03))
|
||||
error(Ebadarg);
|
||||
checkport(offset, offset+n+3);
|
||||
n /= 4;
|
||||
lp = a;
|
||||
for(port = offset; port < offset+n; port += 4)
|
||||
*lp++ = inl(port);
|
||||
return n*4;
|
||||
|
||||
case Qioalloc:
|
||||
break;
|
||||
|
||||
default:
|
||||
if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
|
||||
return fn(c, a, n, offset);
|
||||
error(Eperm);
|
||||
break;
|
||||
}
|
||||
|
||||
offset = offset/Linelen;
|
||||
n = n/Linelen;
|
||||
p = a;
|
||||
lock(&iomap);
|
||||
for(m = iomap.m; n > 0 && m != nil; m = m->next){
|
||||
if(offset-- > 0)
|
||||
continue;
|
||||
if(strcmp(m->tag, "dummy") == 0)
|
||||
break;
|
||||
sprint(buf, "%8lux %8lux %-12.12s\n", m->start, m->end-1, m->tag);
|
||||
memmove(p, buf, Linelen);
|
||||
p += Linelen;
|
||||
n--;
|
||||
}
|
||||
unlock(&iomap);
|
||||
|
||||
return p - (char*)a;
|
||||
}
|
||||
|
||||
static long
|
||||
archwrite(Chan *c, void *a, long n, vlong offset)
|
||||
{
|
||||
char *p;
|
||||
int port;
|
||||
ushort *sp;
|
||||
ulong *lp;
|
||||
Rdwrfn *fn;
|
||||
|
||||
switch((ulong)c->qid.path){
|
||||
|
||||
case Qiob:
|
||||
p = a;
|
||||
checkport(offset, offset+n);
|
||||
for(port = offset; port < offset+n; port++)
|
||||
outb(port, *p++);
|
||||
return n;
|
||||
|
||||
case Qiow:
|
||||
if((n & 01) || (offset & 01))
|
||||
error(Ebadarg);
|
||||
checkport(offset, offset+n+1);
|
||||
n /= 2;
|
||||
sp = a;
|
||||
for(port = offset; port < offset+n; port += 2)
|
||||
outs(port, *sp++);
|
||||
return n*2;
|
||||
|
||||
case Qiol:
|
||||
if((n & 0x03) || (offset & 0x03))
|
||||
error(Ebadarg);
|
||||
checkport(offset, offset+n+3);
|
||||
n /= 4;
|
||||
lp = a;
|
||||
for(port = offset; port < offset+n; port += 4)
|
||||
outl(port, *lp++);
|
||||
return n*4;
|
||||
|
||||
default:
|
||||
if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
|
||||
return fn(c, a, n, offset);
|
||||
error(Eperm);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Dev archdevtab = {
|
||||
'P',
|
||||
"arch",
|
||||
|
||||
devreset,
|
||||
devinit,
|
||||
devshutdown,
|
||||
archattach,
|
||||
archwalk,
|
||||
archstat,
|
||||
archopen,
|
||||
devcreate,
|
||||
archclose,
|
||||
archread,
|
||||
devbread,
|
||||
archwrite,
|
||||
devbwrite,
|
||||
devremove,
|
||||
devwstat,
|
||||
};
|
||||
|
||||
PCArch* arch;
|
||||
extern PCArch* knownarch[];
|
||||
|
||||
PCArch archgeneric = {
|
||||
"generic", /* id */
|
||||
0, /* ident */
|
||||
|
||||
0, /* coreinit */
|
||||
0, /* coredetach */
|
||||
};
|
||||
|
||||
static char *sysnames[] =
|
||||
{
|
||||
[1] "Alpha Demo. Unit",
|
||||
[2] "DEC 4000; Cobra",
|
||||
[3] "DEC 7000; Ruby",
|
||||
[4] "DEC 3000/500; Flamingo family (TC)",
|
||||
[6] "DEC 2000/300; Jensen (EISA/ISA)",
|
||||
[7] "DEC 3000/300; Pelican (TC)",
|
||||
[8] "Avalon A12; Avalon Multicomputer",
|
||||
[9] "DEC 2100/A500; Sable",
|
||||
[10] "DEC APXVME/64; AXPvme (VME?)",
|
||||
[11] "DEC AXPPCI/33; NoName (PCI/ISA)",
|
||||
[12] "DEC 21000; TurboLaser (PCI/EISA)",
|
||||
[13] "DEC 2100/A50; Avanti (PCI/ISA)",
|
||||
[14] "DEC MUSTANG; Mustang",
|
||||
[15] "DEC KN20AA; kn20aa (PCI/EISA)",
|
||||
[17] "DEC 1000; Mikasa (PCI/ISA?)",
|
||||
[19] "EB66; EB66 (PCI/ISA?)", // DEC?
|
||||
[20] "EB64P; EB64+ (PCI/ISA?)", // DEC?
|
||||
[21] "Alphabook1; Alphabook",
|
||||
[22] "DEC 4100; Rawhide (PCI/EISA)",
|
||||
[23] "DEC EV45/PBP; Lego",
|
||||
[24] "DEC 2100A/A500; Lynx",
|
||||
[26] "DEC AlphaPC 164", // only supported one: "EB164 (PCI/ISA)"
|
||||
[27] "DEC 1000A; Noritake",
|
||||
[28] "DEC AlphaVME/224; Cortex",
|
||||
[30] "DEC 550; Miata (PCI/ISA)",
|
||||
[32] "DEC EV56/PBP; Takara",
|
||||
[33] "DEC AlphaVME/320; Yukon (VME?)",
|
||||
[34] "DEC 6600; MonetGoldrush",
|
||||
// 200 and up is Alpha Processor Inc. machines
|
||||
// [201] "API UP1000; Nautilus",
|
||||
};
|
||||
|
||||
static char *cpunames[] =
|
||||
{
|
||||
[1] "EV3",
|
||||
[2] "EV4: 21064",
|
||||
[3] "Simulation",
|
||||
[4] "LCA4: 2106[68]",
|
||||
[5] "EV5: 21164",
|
||||
[6] "EV45: 21064A",
|
||||
[7] "21164A", /* only supported one: EV56 */
|
||||
[8] "EV6: 21264",
|
||||
[9] "PCA256: 21164PC",
|
||||
};
|
||||
|
||||
void
|
||||
cpuidprint(void)
|
||||
{
|
||||
int i, maj, min;
|
||||
Hwcpu *cpu;
|
||||
Hwdsr *dsr;
|
||||
char *s;
|
||||
|
||||
print("\n");
|
||||
|
||||
if (hwrpb->rev >= 6) {
|
||||
dsr = (Hwdsr*)((ulong)hwrpb + hwrpb->dsroff);
|
||||
|
||||
s = (char*)dsr + dsr->sysnameoff + 8;
|
||||
print("%s\n", s);
|
||||
}
|
||||
else {
|
||||
s = "<unknown>";
|
||||
if (hwrpb->systype < nelem(sysnames))
|
||||
s = sysnames[hwrpb->systype];
|
||||
print("%s (%llux, %llux, %llux)\n", s, hwrpb->systype, hwrpb->sysvar, hwrpb->sysrev);
|
||||
}
|
||||
|
||||
for (i = 0; i < hwrpb->ncpu; i++) {
|
||||
cpu = (Hwcpu*) ((ulong)hwrpb + hwrpb->cpuoff + i*hwrpb->cpulen);
|
||||
s = "<unknown>";
|
||||
maj = (ulong)cpu->cputype;
|
||||
min = (ulong)(cpu->cputype>>32);
|
||||
if (maj < nelem(cpunames))
|
||||
s = cpunames[maj];
|
||||
print("cpu%d: %s-%d (%d.%d, %llux, %llux)\n",
|
||||
i, s, min, maj, min, cpu->cpuvar, cpu->cpurev);
|
||||
}
|
||||
|
||||
print("\n");
|
||||
}
|
||||
|
||||
static long
|
||||
cputyperead(Chan*, void *a, long n, vlong offset)
|
||||
{
|
||||
char str[32], *cputype;
|
||||
ulong mhz, maj;
|
||||
Hwcpu *cpu;
|
||||
|
||||
mhz = (m->cpuhz+999999)/1000000;
|
||||
cpu = (Hwcpu*) ((ulong)hwrpb + hwrpb->cpuoff); /* NB CPU 0 */
|
||||
cputype = "unknown";
|
||||
maj = (ulong)cpu->cputype;
|
||||
if (maj < nelem(cpunames))
|
||||
cputype = cpunames[maj];
|
||||
|
||||
snprint(str, sizeof(str), "%s %lud\n", cputype, mhz);
|
||||
return readstr(offset, a, n, str);
|
||||
}
|
||||
|
||||
void
|
||||
archinit(void)
|
||||
{
|
||||
PCArch **p;
|
||||
|
||||
arch = 0;
|
||||
for(p = knownarch; *p; p++){
|
||||
if((*p)->ident && (*p)->ident() == 0){
|
||||
arch = *p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(arch == 0)
|
||||
arch = &archgeneric;
|
||||
|
||||
addarchfile("cputype", 0444, cputyperead, nil);
|
||||
}
|
||||
|
||||
int
|
||||
pcmspecial(char *idstr, ISAConf *isa)
|
||||
{
|
||||
return (_pcmspecial != nil)? _pcmspecial(idstr, isa): -1;
|
||||
}
|
||||
|
||||
void
|
||||
pcmspecialclose(int a)
|
||||
{
|
||||
if (_pcmspecialclose != nil)
|
||||
_pcmspecialclose(a);
|
||||
}
|
|
@ -1,407 +0,0 @@
|
|||
/*
|
||||
* VGA controller
|
||||
*/
|
||||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
#include "../port/error.h"
|
||||
|
||||
#define Image IMAGE
|
||||
#include <draw.h>
|
||||
#include <memdraw.h>
|
||||
#include <cursor.h>
|
||||
#include "screen.h"
|
||||
|
||||
extern uchar *vgabios;
|
||||
|
||||
enum {
|
||||
Qdir,
|
||||
Qvgactl,
|
||||
Qvgabios,
|
||||
};
|
||||
|
||||
static Dirtab vgadir[] = {
|
||||
".", { Qdir, 0, QTDIR }, 0, 0550,
|
||||
"vgactl", { Qvgactl, 0 }, 0, 0660,
|
||||
"vgabios", { Qvgabios, 0 }, 0x10000, 0440,
|
||||
};
|
||||
|
||||
static void
|
||||
vgareset(void)
|
||||
{
|
||||
/* reserve the 'standard' vga registers */
|
||||
if(ioalloc(0x2b0, 0x2df-0x2b0+1, 0, "vga") < 0)
|
||||
panic("vga ports already allocated");
|
||||
if(ioalloc(0x3c0, 0x3da-0x3c0+1, 0, "vga") < 0)
|
||||
panic("vga ports already allocated");
|
||||
conf.monitor = 1;
|
||||
}
|
||||
|
||||
static Chan*
|
||||
vgaattach(char* spec)
|
||||
{
|
||||
if(*spec && strcmp(spec, "0"))
|
||||
error(Eio);
|
||||
return devattach('v', spec);
|
||||
}
|
||||
|
||||
Walkqid*
|
||||
vgawalk(Chan* c, Chan *nc, char** name, int nname)
|
||||
{
|
||||
return devwalk(c, nc, name, nname, vgadir, nelem(vgadir), devgen);
|
||||
}
|
||||
|
||||
static int
|
||||
vgastat(Chan* c, uchar* dp, int n)
|
||||
{
|
||||
return devstat(c, dp, n, vgadir, nelem(vgadir), devgen);
|
||||
}
|
||||
|
||||
static Chan*
|
||||
vgaopen(Chan* c, int omode)
|
||||
{
|
||||
return devopen(c, omode, vgadir, nelem(vgadir), devgen);
|
||||
}
|
||||
|
||||
static void
|
||||
vgaclose(Chan*)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
checkport(int start, int end)
|
||||
{
|
||||
/* standard vga regs are OK */
|
||||
if(start >= 0x2b0 && end <= 0x2df+1)
|
||||
return;
|
||||
if(start >= 0x3c0 && end <= 0x3da+1)
|
||||
return;
|
||||
|
||||
if(iounused(start, end))
|
||||
return;
|
||||
error(Eperm);
|
||||
}
|
||||
|
||||
static long
|
||||
vgaread(Chan* c, void* a, long n, vlong off)
|
||||
{
|
||||
int len;
|
||||
char *p, *s;
|
||||
VGAscr *scr;
|
||||
ulong offset = off;
|
||||
char chbuf[30];
|
||||
|
||||
switch((ulong)c->qid.path){
|
||||
|
||||
case Qdir:
|
||||
return devdirread(c, a, n, vgadir, nelem(vgadir), devgen);
|
||||
|
||||
case Qvgactl:
|
||||
scr = &vgascreen[0];
|
||||
|
||||
p = malloc(READSTR);
|
||||
if(waserror()){
|
||||
free(p);
|
||||
nexterror();
|
||||
}
|
||||
|
||||
len = 0;
|
||||
|
||||
if(scr->dev)
|
||||
s = scr->dev->name;
|
||||
else
|
||||
s = "cga";
|
||||
len += snprint(p+len, READSTR-len, "type %s\n", s);
|
||||
|
||||
if(scr->gscreen) {
|
||||
len += snprint(p+len, READSTR-len, "size %dx%dx%d %s\n",
|
||||
scr->gscreen->r.max.x, scr->gscreen->r.max.y,
|
||||
scr->gscreen->depth, chantostr(chbuf, scr->gscreen->chan));
|
||||
|
||||
if(Dx(scr->gscreen->r) != Dx(physgscreenr)
|
||||
|| Dy(scr->gscreen->r) != Dy(physgscreenr))
|
||||
len += snprint(p+len, READSTR-len, "actualsize %dx%d\n",
|
||||
physgscreenr.max.x, physgscreenr.max.y);
|
||||
}
|
||||
|
||||
len += snprint(p+len, READSTR-len, "blanktime %lud\n", blanktime);
|
||||
len += snprint(p+len, READSTR-len, "hwaccel %s\n", hwaccel ? "on" : "off");
|
||||
len += snprint(p+len, READSTR-len, "hwblank %s\n", hwblank ? "on" : "off");
|
||||
snprint(p+len, READSTR-len, "addr 0x%lux\n", scr->paddr);
|
||||
n = readstr(offset, a, n, p);
|
||||
poperror();
|
||||
free(p);
|
||||
|
||||
return n;
|
||||
|
||||
case Qvgabios:
|
||||
if(vgabios == nil)
|
||||
error(Egreg);
|
||||
if(offset&0x80000000)
|
||||
offset &= ~0x800E0000;
|
||||
if(offset+n > 0x10000)
|
||||
n = 0x10000-offset;
|
||||
if(n < 0)
|
||||
return 0;
|
||||
memmove(a, vgabios+offset, n);
|
||||
return n;
|
||||
|
||||
default:
|
||||
error(Egreg);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char Ebusy[] = "vga already configured";
|
||||
|
||||
static void
|
||||
vgactl(char* a)
|
||||
{
|
||||
int align, i, n, size, x, y, z;
|
||||
char *chanstr, *field[6], *p;
|
||||
ulong chan;
|
||||
VGAscr *scr;
|
||||
extern VGAdev *vgadev[];
|
||||
extern VGAcur *vgacur[];
|
||||
Rectangle r;
|
||||
|
||||
n = tokenize(a, field, nelem(field));
|
||||
if(n < 1)
|
||||
error(Ebadarg);
|
||||
|
||||
scr = &vgascreen[0];
|
||||
if(strcmp(field[0], "hwgc") == 0){
|
||||
if(n < 2)
|
||||
error(Ebadarg);
|
||||
|
||||
if(strcmp(field[1], "off") == 0){
|
||||
lock(&cursor);
|
||||
if(scr->cur){
|
||||
if(scr->cur->disable)
|
||||
scr->cur->disable(scr);
|
||||
scr->cur = nil;
|
||||
}
|
||||
unlock(&cursor);
|
||||
return;
|
||||
}
|
||||
|
||||
for(i = 0; vgacur[i]; i++){
|
||||
if(strcmp(field[1], vgacur[i]->name))
|
||||
continue;
|
||||
lock(&cursor);
|
||||
if(scr->cur && scr->cur->disable)
|
||||
scr->cur->disable(scr);
|
||||
scr->cur = vgacur[i];
|
||||
if(scr->cur->enable)
|
||||
scr->cur->enable(scr);
|
||||
unlock(&cursor);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(strcmp(field[0], "type") == 0){
|
||||
if(n < 2)
|
||||
error(Ebadarg);
|
||||
|
||||
for(i = 0; vgadev[i]; i++){
|
||||
if(strcmp(field[1], vgadev[i]->name))
|
||||
continue;
|
||||
if(scr->dev && scr->dev->disable)
|
||||
scr->dev->disable(scr);
|
||||
scr->dev = vgadev[i];
|
||||
if(scr->dev->enable)
|
||||
scr->dev->enable(scr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(strcmp(field[0], "size") == 0){
|
||||
if(n < 3)
|
||||
error(Ebadarg);
|
||||
if(drawhasclients())
|
||||
error(Ebusy);
|
||||
|
||||
x = strtoul(field[1], &p, 0);
|
||||
if(x == 0 || x > 2048)
|
||||
error(Ebadarg);
|
||||
if(*p)
|
||||
p++;
|
||||
|
||||
y = strtoul(p, &p, 0);
|
||||
if(y == 0 || y > 2048)
|
||||
error(Ebadarg);
|
||||
if(*p)
|
||||
p++;
|
||||
|
||||
z = strtoul(p, &p, 0);
|
||||
|
||||
chanstr = field[2];
|
||||
if((chan = strtochan(chanstr)) == 0)
|
||||
error("bad channel");
|
||||
|
||||
if(chantodepth(chan) != z)
|
||||
error("depth, channel do not match");
|
||||
|
||||
cursoroff(1);
|
||||
deletescreenimage();
|
||||
if(screensize(x, y, z, chan))
|
||||
error(Egreg);
|
||||
vgascreenwin(scr);
|
||||
cursoron(1);
|
||||
return;
|
||||
}
|
||||
else if(strcmp(field[0], "actualsize") == 0){
|
||||
if(scr->gscreen == nil)
|
||||
error("set the screen size first");
|
||||
|
||||
if(n < 2)
|
||||
error(Ebadarg);
|
||||
x = strtoul(field[1], &p, 0);
|
||||
if(x == 0 || x > 2048)
|
||||
error(Ebadarg);
|
||||
if(*p)
|
||||
p++;
|
||||
|
||||
y = strtoul(p, nil, 0);
|
||||
if(y == 0 || y > 2048)
|
||||
error(Ebadarg);
|
||||
|
||||
if(x > scr->gscreen->r.max.x || y > scr->gscreen->r.max.y)
|
||||
error("physical screen bigger than virtual");
|
||||
|
||||
r = Rect(0,0,x,y);
|
||||
if(!eqrect(r, scr->gscreen->r)){
|
||||
if(scr->cur == nil || scr->cur->doespanning == 0)
|
||||
error("virtual screen not supported");
|
||||
}
|
||||
|
||||
physgscreenr = r;
|
||||
return;
|
||||
}
|
||||
else if(strcmp(field[0], "palettedepth") == 0){
|
||||
if(n < 2)
|
||||
error(Ebadarg);
|
||||
|
||||
x = strtoul(field[1], &p, 0);
|
||||
if(x != 8 && x != 6)
|
||||
error(Ebadarg);
|
||||
|
||||
scr->palettedepth = x;
|
||||
return;
|
||||
}
|
||||
else if(strcmp(field[0], "drawinit") == 0){
|
||||
if(scr && scr->dev && scr->dev->drawinit)
|
||||
scr->dev->drawinit(scr);
|
||||
return;
|
||||
}
|
||||
else if(strcmp(field[0], "linear") == 0){
|
||||
if(n < 2)
|
||||
error(Ebadarg);
|
||||
|
||||
size = strtoul(field[1], 0, 0);
|
||||
if(n < 3)
|
||||
align = 0;
|
||||
else
|
||||
align = strtoul(field[2], 0, 0);
|
||||
if(screenaperture(size, align))
|
||||
error("not enough free address space");
|
||||
return;
|
||||
}
|
||||
/* else if(strcmp(field[0], "memset") == 0){
|
||||
if(n < 4)
|
||||
error(Ebadarg);
|
||||
memset((void*)strtoul(field[1], 0, 0), atoi(field[2]), atoi(field[3]));
|
||||
return;
|
||||
}
|
||||
*/
|
||||
else if(strcmp(field[0], "blank") == 0){
|
||||
if(n < 1)
|
||||
error(Ebadarg);
|
||||
drawblankscreen(1);
|
||||
return;
|
||||
}
|
||||
else if(strcmp(field[0], "blanktime") == 0){
|
||||
if(n < 2)
|
||||
error(Ebadarg);
|
||||
blanktime = strtoul(field[1], 0, 0);
|
||||
return;
|
||||
}
|
||||
else if(strcmp(field[0], "hwaccel") == 0){
|
||||
if(n < 2)
|
||||
error(Ebadarg);
|
||||
if(strcmp(field[1], "on") == 0)
|
||||
hwaccel = 1;
|
||||
else if(strcmp(field[1], "off") == 0)
|
||||
hwaccel = 0;
|
||||
return;
|
||||
}
|
||||
else if(strcmp(field[0], "hwblank") == 0){
|
||||
if(n < 2)
|
||||
error(Ebadarg);
|
||||
if(strcmp(field[1], "on") == 0)
|
||||
hwblank = 1;
|
||||
else if(strcmp(field[1], "off") == 0)
|
||||
hwblank = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
error(Ebadarg);
|
||||
}
|
||||
|
||||
static long
|
||||
vgawrite(Chan* c, void* a, long n, vlong off)
|
||||
{
|
||||
char *p;
|
||||
ulong offset = off;
|
||||
|
||||
switch((ulong)c->qid.path){
|
||||
|
||||
case Qdir:
|
||||
error(Eperm);
|
||||
|
||||
case Qvgactl:
|
||||
if(offset || n >= READSTR)
|
||||
error(Ebadarg);
|
||||
p = malloc(READSTR);
|
||||
if(waserror()){
|
||||
free(p);
|
||||
nexterror();
|
||||
}
|
||||
memmove(p, a, n);
|
||||
p[n] = 0;
|
||||
vgactl(p);
|
||||
poperror();
|
||||
free(p);
|
||||
return n;
|
||||
|
||||
default:
|
||||
error(Egreg);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Dev vgadevtab = {
|
||||
'v',
|
||||
"vga",
|
||||
|
||||
vgareset,
|
||||
devinit,
|
||||
devshutdown,
|
||||
vgaattach,
|
||||
vgawalk,
|
||||
vgastat,
|
||||
vgaopen,
|
||||
devcreate,
|
||||
vgaclose,
|
||||
vgaread,
|
||||
devbread,
|
||||
vgawrite,
|
||||
devbwrite,
|
||||
devremove,
|
||||
devwstat,
|
||||
};
|
|
@ -1,331 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
#include "io.h"
|
||||
|
||||
typedef struct DMAport DMAport;
|
||||
typedef struct DMA DMA;
|
||||
typedef struct DMAxfer DMAxfer;
|
||||
|
||||
/*
|
||||
* state of a dma transfer
|
||||
*/
|
||||
struct DMAxfer
|
||||
{
|
||||
ulong bpa; /* bounce buffer physical address */
|
||||
void* bva; /* bounce buffer virtual address */
|
||||
int blen; /* bounce buffer length */
|
||||
void* va; /* virtual address destination/src */
|
||||
long len; /* bytes to be transferred */
|
||||
int isread;
|
||||
};
|
||||
|
||||
/*
|
||||
* the dma controllers. the first half of this structure specifies
|
||||
* the I/O ports used by the DMA controllers.
|
||||
*/
|
||||
struct DMAport
|
||||
{
|
||||
uchar addr[4]; /* current address (4 channels) */
|
||||
uchar count[4]; /* current count (4 channels) */
|
||||
uchar page[4]; /* page registers (4 channels) */
|
||||
uchar cmd; /* command status register */
|
||||
uchar req; /* request registers */
|
||||
uchar sbm; /* single bit mask register */
|
||||
uchar mode; /* mode register */
|
||||
uchar cbp; /* clear byte pointer */
|
||||
uchar mc; /* master clear */
|
||||
uchar cmask; /* clear mask register */
|
||||
uchar wam; /* write all mask register bit */
|
||||
};
|
||||
|
||||
struct DMA
|
||||
{
|
||||
DMAport;
|
||||
int shift;
|
||||
Lock;
|
||||
DMAxfer x[4];
|
||||
};
|
||||
|
||||
DMA dma[2] = {
|
||||
{ 0x00, 0x02, 0x04, 0x06,
|
||||
0x01, 0x03, 0x05, 0x07,
|
||||
0x87, 0x83, 0x81, 0x82,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0 },
|
||||
|
||||
{ 0xc0, 0xc4, 0xc8, 0xcc,
|
||||
0xc2, 0xc6, 0xca, 0xce,
|
||||
0x8f, 0x8b, 0x89, 0x8a,
|
||||
0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
|
||||
1 },
|
||||
};
|
||||
|
||||
extern int i8237dma;
|
||||
static void* i8237bva[2];
|
||||
static int i8237used;
|
||||
|
||||
/*
|
||||
* DMA must be in the first 16MB. This gets called early by the
|
||||
* initialisation routines of any devices which require DMA to ensure
|
||||
* the allocated bounce buffers are below the 16MB limit.
|
||||
*/
|
||||
void
|
||||
_i8237alloc(void)
|
||||
{
|
||||
void* bva;
|
||||
|
||||
if(i8237dma <= 0)
|
||||
return;
|
||||
if(i8237dma > 2)
|
||||
i8237dma = 2;
|
||||
|
||||
bva = xspanalloc(64*1024*i8237dma, BY2PG, 64*1024);
|
||||
if(bva == nil || PADDR(bva)+64*1024*i8237dma > 16*MB){
|
||||
/*
|
||||
* This will panic with the current
|
||||
* implementation of xspanalloc().
|
||||
if(bva != nil)
|
||||
xfree(bva);
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
i8237bva[0] = bva;
|
||||
if(i8237dma == 2)
|
||||
i8237bva[1] = ((uchar*)i8237bva[0])+64*1024;
|
||||
}
|
||||
|
||||
static void
|
||||
dmastatus(DMA *dp, int chan, char c)
|
||||
{
|
||||
int a, l, s;
|
||||
|
||||
ilock(dp);
|
||||
outb(dp->cbp, 0);
|
||||
a = inb(dp->addr[chan]);
|
||||
a |= inb(dp->addr[chan])<<8;
|
||||
a |= inb(dp->page[chan])<<16;
|
||||
a |= inb(0x400|dp->page[chan])<<24;
|
||||
outb(dp->cbp, 0);
|
||||
l = inb(dp->count[chan]);
|
||||
l |= inb(dp->count[chan])<<8;
|
||||
s = inb(dp->cmd);
|
||||
iunlock(dp);
|
||||
print("%c: addr %uX len %uX stat %uX\n", c, a, l, s);
|
||||
}
|
||||
|
||||
int
|
||||
dmainit(int chan, int maxtransfer)
|
||||
{
|
||||
DMA *dp;
|
||||
DMAxfer *xp;
|
||||
static int once;
|
||||
|
||||
if(once == 0){
|
||||
if(ioalloc(0x00, 0x10, 0, "dma") < 0
|
||||
|| ioalloc(0x80, 0x10, 0, "dma") < 0
|
||||
|| ioalloc(0xd0, 0x10, 0, "dma") < 0)
|
||||
panic("dmainit");
|
||||
outb(dma[0].mc, 0);
|
||||
outb(dma[1].mc, 0);
|
||||
outb(dma[0].cmask, 0);
|
||||
outb(dma[1].cmask, 0);
|
||||
outb(dma[1].mode, 0xC0);
|
||||
once = 1;
|
||||
}
|
||||
|
||||
if(maxtransfer > 64*1024)
|
||||
maxtransfer = 64*1024;
|
||||
|
||||
dp = &dma[(chan>>2)&1];
|
||||
chan = chan & 3;
|
||||
xp = &dp->x[chan];
|
||||
if(xp->bva != nil){
|
||||
if(xp->blen < maxtransfer)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
//dmastatus(dp, chan, 'I');
|
||||
|
||||
if(i8237used >= i8237dma || i8237bva[i8237used] == nil){
|
||||
print("no i8237 DMA bounce buffer < 16MB\n");
|
||||
return 1;
|
||||
}
|
||||
xp->bva = i8237bva[i8237used++];
|
||||
xp->bpa = PADDR(xp->bva);
|
||||
xp->blen = maxtransfer;
|
||||
xp->len = 0;
|
||||
xp->isread = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
xdmastatus(int chan)
|
||||
{
|
||||
DMA *dp;
|
||||
|
||||
dp = &dma[(chan>>2)&1];
|
||||
chan = chan & 3;
|
||||
|
||||
dmastatus(dp, chan, 'X');
|
||||
}
|
||||
|
||||
/*
|
||||
* setup a dma transfer. if the destination is not in kernel
|
||||
* memory, allocate a page for the transfer.
|
||||
*
|
||||
* we assume BIOS has set up the command register before we
|
||||
* are booted.
|
||||
*
|
||||
* return the updated transfer length (we can't transfer across 64k
|
||||
* boundaries)
|
||||
*/
|
||||
long
|
||||
dmasetup(int chan, void *va, long len, int isread)
|
||||
{
|
||||
DMA *dp;
|
||||
ulong pa;
|
||||
uchar mode;
|
||||
DMAxfer *xp;
|
||||
|
||||
dp = &dma[(chan>>2)&1];
|
||||
chan = chan & 3;
|
||||
xp = &dp->x[chan];
|
||||
//print("va%lux+", va);
|
||||
#define tryPCI
|
||||
#ifndef PCIWADDR
|
||||
#define PCIWADDR(va) PADDR(va)
|
||||
#endif /* PCIWADDR */
|
||||
#ifdef notdef
|
||||
|
||||
/*
|
||||
* if this isn't kernel memory or crossing 64k boundary or above 16 meg
|
||||
* use the bounce buffer.
|
||||
*/
|
||||
pa = PADDR(va);
|
||||
if((((ulong)va)&0xF0000000) != KZERO
|
||||
|| (pa&0xFFFF0000) != ((pa+len)&0xFFFF0000)
|
||||
|| pa >= 16*MB) {
|
||||
if(xp->bva == nil)
|
||||
return -1;
|
||||
if(len > xp->blen)
|
||||
len = xp->blen;
|
||||
if(!isread)
|
||||
memmove(xp->bva, va, len);
|
||||
xp->va = va;
|
||||
xp->len = len;
|
||||
xp->isread = isread;
|
||||
pa = xp->bpa;
|
||||
}
|
||||
else
|
||||
xp->len = 0;
|
||||
#endif /* notdef */
|
||||
#ifdef tryISA
|
||||
pa = ISAWADDR(va);
|
||||
#endif /* tryISA */
|
||||
#ifdef tryPCI
|
||||
pa = PCIWADDR(va);
|
||||
if((((ulong)va)&0xF0000000) != KZERO){
|
||||
if(xp->bva == nil)
|
||||
return -1;
|
||||
if(len > xp->blen)
|
||||
len = xp->blen;
|
||||
if(!isread)
|
||||
memmove(xp->bva, va, len);
|
||||
xp->va = va;
|
||||
xp->len = len;
|
||||
xp->isread = isread;
|
||||
pa = PCIWADDR(xp->bva);
|
||||
}
|
||||
else
|
||||
xp->len = 0;
|
||||
#endif /* tryPCI */
|
||||
|
||||
/*
|
||||
* this setup must be atomic
|
||||
*/
|
||||
mode = (isread ? 0x44 : 0x48) | chan;
|
||||
ilock(dp);
|
||||
outb(dp->cbp, 0); /* set count & address to their first byte */
|
||||
outb(dp->mode, mode); /* single mode dma (give CPU a chance at mem) */
|
||||
outb(dp->addr[chan], pa>>dp->shift); /* set address */
|
||||
outb(dp->addr[chan], pa>>(8+dp->shift));
|
||||
outb(dp->page[chan], pa>>16);
|
||||
#ifdef tryPCI
|
||||
outb(0x400|dp->page[chan], pa>>24);
|
||||
#endif /* tryPCI */
|
||||
outb(dp->cbp, 0); /* set count & address to their first byte */
|
||||
outb(dp->count[chan], (len>>dp->shift)-1); /* set count */
|
||||
outb(dp->count[chan], ((len>>dp->shift)-1)>>8);
|
||||
outb(dp->sbm, chan); /* enable the channel */
|
||||
iunlock(dp);
|
||||
//dmastatus(dp, chan, 'S');
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int
|
||||
dmadone(int chan)
|
||||
{
|
||||
DMA *dp;
|
||||
|
||||
dp = &dma[(chan>>2)&1];
|
||||
chan = chan & 3;
|
||||
|
||||
return inb(dp->cmd) & (1<<chan);
|
||||
}
|
||||
|
||||
/*
|
||||
* this must be called after a dma has been completed.
|
||||
*
|
||||
* if a page has been allocated for the dma,
|
||||
* copy the data into the actual destination
|
||||
* and free the page.
|
||||
*/
|
||||
void
|
||||
dmaend(int chan)
|
||||
{
|
||||
DMA *dp;
|
||||
DMAxfer *xp;
|
||||
|
||||
dp = &dma[(chan>>2)&1];
|
||||
chan = chan & 3;
|
||||
|
||||
//dmastatus(dp, chan, 'E');
|
||||
/*
|
||||
* disable the channel
|
||||
*/
|
||||
ilock(dp);
|
||||
outb(dp->sbm, 4|chan);
|
||||
iunlock(dp);
|
||||
|
||||
xp = &dp->x[chan];
|
||||
if(xp->len == 0 || !xp->isread)
|
||||
return;
|
||||
|
||||
/*
|
||||
* copy out of temporary page
|
||||
*/
|
||||
memmove(xp->va, xp->bva, xp->len);
|
||||
xp->len = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
int
|
||||
dmacount(int chan)
|
||||
{
|
||||
int retval;
|
||||
DMA *dp;
|
||||
|
||||
dp = &dma[(chan>>2)&1];
|
||||
outb(dp->cbp, 0);
|
||||
retval = inb(dp->count[chan]);
|
||||
retval |= inb(dp->count[chan]) << 8;
|
||||
return((retval<<dp->shift)+1);
|
||||
}
|
||||
*/
|
|
@ -1,41 +0,0 @@
|
|||
enum {
|
||||
MaxEther = 24,
|
||||
Ntypes = 8,
|
||||
};
|
||||
|
||||
typedef struct Ether Ether;
|
||||
struct Ether {
|
||||
ISAConf; /* hardware info */
|
||||
|
||||
int ctlrno;
|
||||
int tbdf; /* type+busno+devno+funcno */
|
||||
int minmtu;
|
||||
int maxmtu;
|
||||
uchar ea[Eaddrlen];
|
||||
|
||||
void (*attach)(Ether*); /* filled in by reset routine */
|
||||
void (*detach)(Ether*); /* NEW, from ../pc */
|
||||
void (*transmit)(Ether*);
|
||||
void (*interrupt)(Ureg*, void*);
|
||||
long (*ifstat)(Ether*, void*, long, ulong);
|
||||
long (*ctl)(Ether*, void*, long); /* custom ctl messages */
|
||||
/* START NEW, from ../pc */
|
||||
void (*power)(Ether*, int); /* power on/off */
|
||||
void (*shutdown)(Ether*); /* shutdown hardware before reboot */
|
||||
/* END NEW */
|
||||
void *ctlr;
|
||||
|
||||
Queue* oq;
|
||||
|
||||
Netif;
|
||||
};
|
||||
|
||||
extern Block* etheriq(Ether*, Block*, int);
|
||||
extern void addethercard(char*, int(*)(Ether*));
|
||||
extern ulong ethercrc(uchar*, int);
|
||||
extern int parseether(uchar*, char*);
|
||||
|
||||
#define NEXT(x, l) (((x)+1)%(l))
|
||||
#define PREV(x, l) (((x) == 0) ? (l)-1: (x)-1)
|
||||
#define HOWMANY(x, y) (((x)+((y)-1))/(y))
|
||||
#define ROUNDUP(x, y) (HOWMANY((x), (y))*(y))
|
|
@ -1,62 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "ureg.h"
|
||||
#include "../port/error.h"
|
||||
|
||||
/*
|
||||
* find out fault address and type of access.
|
||||
* Call common fault handler.
|
||||
*/
|
||||
void
|
||||
faultalpha(Ureg *ur)
|
||||
{
|
||||
ulong addr, cause;
|
||||
int read, user;
|
||||
char buf[ERRMAX];
|
||||
uvlong x;
|
||||
|
||||
x = ur->a0&0xffffffff80000000LL;
|
||||
if (x != 0LL && x != 0xffffffff80000000LL)
|
||||
iprint("faultalpha bad addr %llux pc %llux\n", ur->a0, ur->pc);
|
||||
|
||||
addr = (ulong)ur->a0;
|
||||
cause = (ulong)ur->a2;
|
||||
addr &= ~(BY2PG-1);
|
||||
read = (cause !=1);
|
||||
user = (ulong)ur->status&UMODE;
|
||||
|
||||
/* print("fault %s pc=0x%lux addr=0x%lux 0x%lux\n",
|
||||
read? (cause != 0) ? "ifetch" : "read" : "write", (ulong)ur->pc, addr, (ulong)ur->a1); /**/
|
||||
|
||||
if(fault(addr, read) == 0)
|
||||
return;
|
||||
|
||||
if(user){
|
||||
sprint(buf, "sys: trap: fault %s addr=0x%lux",
|
||||
read? (cause != 0) ? "ifetch" : "read" : "write", (ulong)ur->a0);
|
||||
postnote(up, 1, buf, NDebug);
|
||||
return;
|
||||
}
|
||||
|
||||
iprint("kernel %s vaddr=0x%lux\n", read? (cause != 0) ? "ifetch" : "read" : "write", (ulong)ur->a0);
|
||||
if(0)
|
||||
mmudump();
|
||||
dumpregs(ur);
|
||||
_dumpstack(ur);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* called in sysfile.c
|
||||
*/
|
||||
void
|
||||
evenaddr(ulong addr)
|
||||
{
|
||||
if(addr & 3){
|
||||
postnote(up, 1, "sys: odd address", NDebug);
|
||||
error(Ebadarg);
|
||||
}
|
||||
}
|
|
@ -1,66 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
|
||||
/*
|
||||
* SMC FDC37C93x Plug and Play Compatible Ultra I/O Controller.
|
||||
*/
|
||||
enum { /* I/O Ports */
|
||||
Config = 0x370, /* could also be 0x3F0 */
|
||||
|
||||
Index = 0,
|
||||
Data = 1,
|
||||
};
|
||||
|
||||
static int fddregs[] = {
|
||||
0x30,
|
||||
0x60, 0x61,
|
||||
0x70,
|
||||
0x74,
|
||||
0xF0,
|
||||
0xF1,
|
||||
0xF2,
|
||||
0xF4,
|
||||
0xF5,
|
||||
0,
|
||||
};
|
||||
|
||||
#define OUTB(p, d) outb(p, d); microdelay(10);
|
||||
|
||||
void
|
||||
fdc37c93xdump(void)
|
||||
{
|
||||
int config, i, x;
|
||||
|
||||
config = Config;
|
||||
|
||||
OUTB(config, 0x55);
|
||||
OUTB(config, 0x55);
|
||||
|
||||
OUTB(config+Index, 0x20);
|
||||
x = inb(config+Data);
|
||||
print("fdc37c93x: Device ID 0x%2.2uX\n", x);
|
||||
OUTB(config+Index, 0x22);
|
||||
x = inb(config+Data);
|
||||
print("fdc37c93x: Power/Control 0x%2.2uX\n", x);
|
||||
|
||||
OUTB(config+Index, 0x07);
|
||||
OUTB(config+Data, 0);
|
||||
for(i = 0; fddregs[i]; i++){
|
||||
OUTB(config+Index, fddregs[i]);
|
||||
x = inb(config+Data);
|
||||
print("FDD%2.2uX: 0x%2.2uX\n", fddregs[i], x);
|
||||
}
|
||||
|
||||
OUTB(config+Index, 0x70);
|
||||
OUTB(config+Data, 0x06);
|
||||
OUTB(config+Index, 0x74);
|
||||
OUTB(config+Data, 0x02);
|
||||
OUTB(config+Index, 0x30);
|
||||
OUTB(config+Data, 0x01);
|
||||
|
||||
OUTB(config, 0xAA);
|
||||
}
|
|
@ -1,181 +0,0 @@
|
|||
typedef struct FController FController;
|
||||
typedef struct FDrive FDrive;
|
||||
typedef struct FType FType;
|
||||
|
||||
static void floppyintr(Ureg*);
|
||||
static int floppyon(FDrive*);
|
||||
static void floppyoff(FDrive*);
|
||||
static void floppysetdef(FDrive*);
|
||||
|
||||
/*
|
||||
* a floppy drive
|
||||
*/
|
||||
struct FDrive
|
||||
{
|
||||
FType *t; /* floppy type */
|
||||
int dt; /* drive type */
|
||||
int dev;
|
||||
|
||||
ulong lasttouched; /* time last touched */
|
||||
int cyl; /* current arm position */
|
||||
int confused; /* needs to be recalibrated */
|
||||
int vers;
|
||||
int maxtries; /* max read attempts before Eio */
|
||||
|
||||
int tcyl; /* target cylinder */
|
||||
int thead; /* target head */
|
||||
int tsec; /* target sector */
|
||||
long len; /* size of xfer */
|
||||
|
||||
uchar *cache; /* track cache */
|
||||
int ccyl;
|
||||
int chead;
|
||||
|
||||
Rendez r; /* waiting here for motor to spin up */
|
||||
};
|
||||
|
||||
/*
|
||||
* controller for 4 floppys
|
||||
*/
|
||||
struct FController
|
||||
{
|
||||
QLock; /* exclusive access to the contoller */
|
||||
|
||||
int ndrive;
|
||||
FDrive *d; /* the floppy drives */
|
||||
FDrive *selected;
|
||||
int rate; /* current rate selected */
|
||||
uchar cmd[14]; /* command */
|
||||
int ncmd; /* # command bytes */
|
||||
uchar stat[14]; /* command status */
|
||||
int nstat; /* # status bytes */
|
||||
int confused; /* controler needs to be reset */
|
||||
Rendez r; /* wait here for command termination */
|
||||
int motor; /* bit mask of spinning disks */
|
||||
Rendez kr; /* for motor watcher */
|
||||
};
|
||||
|
||||
/*
|
||||
* floppy types (all MFM encoding)
|
||||
*/
|
||||
struct FType
|
||||
{
|
||||
char *name;
|
||||
int dt; /* compatible drive type */
|
||||
int bytes; /* bytes/sector */
|
||||
int sectors; /* sectors/track */
|
||||
int heads; /* number of heads */
|
||||
int steps; /* steps per cylinder */
|
||||
int tracks; /* tracks/disk */
|
||||
int gpl; /* intersector gap length for read/write */
|
||||
int fgpl; /* intersector gap length for format */
|
||||
int rate; /* rate code */
|
||||
|
||||
/*
|
||||
* these depend on previous entries and are set filled in
|
||||
* by floppyinit
|
||||
*/
|
||||
int bcode; /* coded version of bytes for the controller */
|
||||
long cap; /* drive capacity in bytes */
|
||||
long tsize; /* track size in bytes */
|
||||
};
|
||||
/* bits in the registers */
|
||||
enum
|
||||
{
|
||||
/* status registers a & b */
|
||||
Psra= 0x3f0,
|
||||
Psrb= 0x3f1,
|
||||
|
||||
/* digital output register */
|
||||
Pdor= 0x3f2,
|
||||
Fintena= 0x8, /* enable floppy interrupt */
|
||||
Fena= 0x4, /* 0 == reset controller */
|
||||
|
||||
/* main status register */
|
||||
Pmsr= 0x3f4,
|
||||
Fready= 0x80, /* ready to be touched */
|
||||
Ffrom= 0x40, /* data from controller */
|
||||
Ffloppybusy= 0x10, /* operation not over */
|
||||
|
||||
/* data register */
|
||||
Pfdata= 0x3f5,
|
||||
Frecal= 0x07, /* recalibrate cmd */
|
||||
Fseek= 0x0f, /* seek cmd */
|
||||
Fsense= 0x08, /* sense cmd */
|
||||
Fread= 0x66, /* read cmd */
|
||||
Freadid= 0x4a, /* read track id */
|
||||
Fspec= 0x03, /* set hold times */
|
||||
Fwrite= 0x45, /* write cmd */
|
||||
Fformat= 0x4d, /* format cmd */
|
||||
Fmulti= 0x80, /* or'd with Fread or Fwrite for multi-head */
|
||||
Fdumpreg= 0x0e, /* dump internal registers */
|
||||
|
||||
/* digital input register */
|
||||
Pdir= 0x3F7, /* disk changed port (read only) */
|
||||
Pdsr= 0x3F7, /* data rate select port (write only) */
|
||||
Fchange= 0x80, /* disk has changed */
|
||||
|
||||
/* status 0 byte */
|
||||
Drivemask= 3<<0,
|
||||
Seekend= 1<<5,
|
||||
Codemask= (3<<6)|(3<<3),
|
||||
Cmdexec= 1<<6,
|
||||
|
||||
/* status 1 byte */
|
||||
Overrun= 0x10,
|
||||
};
|
||||
|
||||
|
||||
static void
|
||||
pcfloppyintr(Ureg *ur, void *a)
|
||||
{
|
||||
USED(a);
|
||||
|
||||
floppyintr(ur);
|
||||
}
|
||||
|
||||
void
|
||||
floppysetup0(FController *fl)
|
||||
{
|
||||
fl->ndrive = 0;
|
||||
if(ioalloc(Psra, 6, 0, "floppy") < 0)
|
||||
return;
|
||||
if(ioalloc(Pdir, 1, 0, "floppy") < 0){
|
||||
iofree(Psra);
|
||||
return;
|
||||
}
|
||||
fl->ndrive = 1;
|
||||
}
|
||||
|
||||
void
|
||||
floppysetup1(FController *fl)
|
||||
{
|
||||
if(fl->ndrive > 0){
|
||||
fl->d[0].dt = 4;
|
||||
floppysetdef(&fl->d[0]);
|
||||
}
|
||||
if(fl->ndrive > 1){
|
||||
fl->d[1].dt = 4;
|
||||
floppysetdef(&fl->d[1]);
|
||||
}
|
||||
|
||||
intrenable(IrqFLOPPY, pcfloppyintr, fl, BUSUNKNOWN, "floppy");
|
||||
}
|
||||
|
||||
/*
|
||||
* eject disk
|
||||
*/
|
||||
void
|
||||
floppyeject(FDrive *dp)
|
||||
{
|
||||
floppyon(dp);
|
||||
dp->vers++;
|
||||
floppyoff(dp);
|
||||
}
|
||||
|
||||
int
|
||||
floppyexec(char *a, long b, int c)
|
||||
{
|
||||
USED(a, b, c);
|
||||
return b;
|
||||
}
|
|
@ -1,128 +0,0 @@
|
|||
#include "../port/portfns.h"
|
||||
|
||||
Dirtab* addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,void*,long,vlong));
|
||||
void archinit(void);
|
||||
void arginit(void);
|
||||
void arith(void);
|
||||
ulong cankaddr(ulong);
|
||||
void clock(Ureg*);
|
||||
void clockinit(void);
|
||||
void clockintrsched(void);
|
||||
#define coherence mb
|
||||
int cistrcmp(char*, char*);
|
||||
int cistrncmp(char*, char*, int);
|
||||
int cmpswap(long*, long, long);
|
||||
void cpuidprint(void);
|
||||
void cserve(ulong, ulong);
|
||||
#define cycles(x) do{}while(0)
|
||||
void timeradd(Timer *);
|
||||
void timerdel(Timer *);
|
||||
int dmacount(int);
|
||||
int dmadone(int);
|
||||
void dmaend(int);
|
||||
int dmainit(int, int);
|
||||
long dmasetup(int, void*, long, int);
|
||||
void _dumpstack(Ureg *);
|
||||
void evenaddr(ulong);
|
||||
void fataltrap(Ureg *, char *);
|
||||
void fault0(void);
|
||||
void faultalpha(Ureg*);
|
||||
ulong fcr31(void);
|
||||
void firmware(void);
|
||||
void fpenab(int);
|
||||
void fptrap(Ureg*);
|
||||
int getcfields(char*, char**, int, char*);
|
||||
char *getconf(char*);
|
||||
int havetimer(void);
|
||||
int i8042auxcmd(int);
|
||||
void i8042auxenable(void (*)(int, int));
|
||||
void i8042reset(void);
|
||||
void i8250console(void);
|
||||
void i8250mouse(char*, int(*)(Queue*,int), int);
|
||||
void i8250setmouseputc(char*, int (*)(Queue*, int));
|
||||
void i8259init(void);
|
||||
int i8259enable(int, int, Vctl*);
|
||||
#define idlehands() /* nothing to do in the runproc */
|
||||
void icflush(void);
|
||||
void illegal0(void);
|
||||
void intr0(void);
|
||||
void intrenable(int, void (*)(Ureg*, void*), void*, int, char*);
|
||||
int intrdisable(int, void (*)(Ureg *, void *), void*, int, char*);
|
||||
int ioalloc(int, int, int, char*);
|
||||
void iofree(int);
|
||||
void ioinit(void);
|
||||
int iounused(int, int);
|
||||
int irqallocread(char*, long, vlong);
|
||||
int isaconfig(char*, int, ISAConf*);
|
||||
#define kexit(a)
|
||||
#define kmapinval()
|
||||
void *kmapv(uvlong, int);
|
||||
int kprint(char*, ...);
|
||||
void links(void);
|
||||
void mb(void);
|
||||
void memholes(void);
|
||||
ulong meminit(void);
|
||||
void mmudump(void);
|
||||
void mmuinit(void);
|
||||
void mmupark(void);
|
||||
#define mtrr(a, b, c)
|
||||
ulong pcibarsize(Pcidev*, int);
|
||||
int pcicfgr8(Pcidev*, int);
|
||||
int pcicfgr16(Pcidev*, int);
|
||||
int pcicfgr32(Pcidev*, int);
|
||||
void pcicfgw8(Pcidev*, int, int);
|
||||
void pcicfgw16(Pcidev*, int, int);
|
||||
void pcicfgw32(Pcidev*, int, int);
|
||||
void pciclrbme(Pcidev*);
|
||||
void pcihinv(Pcidev*);
|
||||
Pcidev* pcimatch(Pcidev*, int, int);
|
||||
Pcidev* pcimatchtbdf(int);
|
||||
void pcireset(void);
|
||||
void pcisetbme(Pcidev*);
|
||||
int pcmspecial(char*, ISAConf*);
|
||||
int (*_pcmspecial)(char *, ISAConf *);
|
||||
void pcmspecialclose(int);
|
||||
void (*_pcmspecialclose)(int);
|
||||
void prflush(void);
|
||||
void printinit(void);
|
||||
#define procrestore(p)
|
||||
void procsave(Proc*);
|
||||
void procsetup(Proc*);
|
||||
void procfork(Proc*);
|
||||
void restfpregs(FPsave*);
|
||||
uvlong rpcc(uvlong*);
|
||||
void screeninit(void);
|
||||
void (*screenputs)(char*, int);
|
||||
void setpcb(PCB *);
|
||||
PCB *swpctx(PCB *);
|
||||
void syscall0(void);
|
||||
int tas(ulong*);
|
||||
void tlbflush(int, ulong);
|
||||
void touser(void*);
|
||||
void trapinit(void);
|
||||
void unaligned(void);
|
||||
ulong upaalloc(int, int);
|
||||
void upafree(ulong, int);
|
||||
#define userureg(ur) ((ur)->status & UMODE)
|
||||
void* vmap(ulong, int);
|
||||
void wrent(int, void*);
|
||||
void wrvptptr(uvlong);
|
||||
void vunmap(void*, int);
|
||||
|
||||
#define waserror() (up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
|
||||
#define KADDR(a) ((void*)((ulong)(a)|KZERO))
|
||||
#define PADDR(a) ((ulong)(a)&~KZERO)
|
||||
|
||||
#define inb(p) (arch->_inb)(p)
|
||||
#define ins(p) (arch->_ins)(p)
|
||||
#define inl(p) (arch->_inl)(p)
|
||||
#define outb(p, x) (arch->_outb)((p), (x))
|
||||
#define outs(p, x) (arch->_outs)((p), (x))
|
||||
#define outl(p, x) (arch->_outl)((p), (x))
|
||||
|
||||
#define insb(p, buf, len) (arch->_insb)((p), (buf), (len))
|
||||
#define inss(p, buf, len) (arch->_inss)((p), (buf), (len))
|
||||
#define insl(p, buf, len) (arch->_insl)((p), (buf), (len))
|
||||
#define outsb(p, buf, len) (arch->_outsb)((p), (buf), (len))
|
||||
#define outss(p, buf, len) (arch->_outss)((p), (buf), (len))
|
||||
#define outsl(p, buf, len) (arch->_outsl)((p), (buf), (len))
|
|
@ -1,46 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "ureg.h"
|
||||
#include "io.h"
|
||||
#include "../port/error.h"
|
||||
|
||||
char *fpcause[] =
|
||||
{
|
||||
"invalid operation",
|
||||
"division by zero",
|
||||
"overflow",
|
||||
"underflow",
|
||||
"inexact operation",
|
||||
"integer overflow",
|
||||
};
|
||||
char *fpexcname(Ureg*, ulong, char*);
|
||||
|
||||
void
|
||||
fptrap(Ureg *ur)
|
||||
{
|
||||
char buf[ERRMAX];
|
||||
int i;
|
||||
ulong reason;
|
||||
|
||||
ur->pc &= ~2;
|
||||
reason = (ulong)ur->a0;
|
||||
for (i = 1; i < 6; i++)
|
||||
if (reason & (1<<i)) {
|
||||
sprint(buf, "fp: %s", fpcause[i-1]);
|
||||
goto found;
|
||||
}
|
||||
sprint(buf, "fp: code 0x%lux", reason);
|
||||
|
||||
found:
|
||||
fataltrap(ur, buf);
|
||||
}
|
||||
|
||||
char*
|
||||
fpexcname(Ureg *ur, ulong fcr31, char *buf)
|
||||
{
|
||||
USED(ur, fcr31, buf);
|
||||
return buf;
|
||||
}
|
|
@ -1,152 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
|
||||
/*
|
||||
* 8259 interrupt controllers
|
||||
*/
|
||||
enum
|
||||
{
|
||||
Int0ctl= 0x20, /* control port (ICW1, OCW2, OCW3) */
|
||||
Int0aux= 0x21, /* everything else (ICW2, ICW3, ICW4, OCW1) */
|
||||
Int1ctl= 0xA0, /* control port */
|
||||
Int1aux= 0xA1, /* everything else (ICW2, ICW3, ICW4, OCW1) */
|
||||
|
||||
Icw1= 0x10, /* select bit in ctl register */
|
||||
Ocw2= 0x00,
|
||||
Ocw3= 0x08,
|
||||
|
||||
EOI= 0x20, /* non-specific end of interrupt */
|
||||
|
||||
Elcr1= 0x4D0, /* Edge/Level Triggered Register */
|
||||
Elcr2= 0x4D1,
|
||||
};
|
||||
|
||||
static int int0mask; /* interrupts enabled for first 8259 */
|
||||
static int int1mask; /* interrupts enabled for second 8259 */
|
||||
|
||||
int elcr; /* mask of level-triggered interrupts */
|
||||
|
||||
void
|
||||
i8259init(void)
|
||||
{
|
||||
int /*elcr1, */ x;
|
||||
|
||||
ioalloc(Int0ctl, 2, 0, "i8259.0");
|
||||
ioalloc(Int1ctl, 2, 0, "i8259.1");
|
||||
int0mask = 0xFF;
|
||||
int1mask = 0xFF;
|
||||
|
||||
/*
|
||||
* Set up the first 8259 interrupt processor.
|
||||
* Make 8259 interrupts start at CPU vector Int0vec.
|
||||
* Set the 8259 as master with edge triggered
|
||||
* input with fully nested interrupts.
|
||||
*/
|
||||
outb(Int0ctl, (1<<4)|(0<<3)|(1<<0)); /* ICW1 - master, edge triggered,
|
||||
ICW4 will be sent */
|
||||
outb(Int0aux, VectorPIC); /* ICW2 - interrupt vector offset */
|
||||
outb(Int0aux, 0x04); /* ICW3 - have slave on level 2 */
|
||||
outb(Int0aux, 0x01); /* ICW4 - 8086 mode, not buffered */
|
||||
|
||||
/*
|
||||
* Set up the second 8259 interrupt processor.
|
||||
* Make 8259 interrupts start at CPU vector VectorPIC+8.
|
||||
* Set the 8259 as slave with edge triggered
|
||||
* input with fully nested interrupts.
|
||||
*/
|
||||
outb(Int1ctl, (1<<4)|(0<<3)|(1<<0)); /* ICW1 - master, edge triggered,
|
||||
ICW4 will be sent */
|
||||
outb(Int1aux, VectorPIC+8); /* ICW2 - interrupt vector offset */
|
||||
outb(Int1aux, 0x02); /* ICW3 - I am a slave on level 2 */
|
||||
outb(Int1aux, 0x01); /* ICW4 - 8086 mode, not buffered */
|
||||
outb(Int1aux, int1mask);
|
||||
|
||||
/*
|
||||
* pass #2 8259 interrupts to #1
|
||||
*/
|
||||
int0mask &= ~0x04;
|
||||
outb(Int0aux, int0mask);
|
||||
|
||||
/*
|
||||
* Set Ocw3 to return the ISR when ctl read.
|
||||
* After initialisation status read is set to IRR.
|
||||
* Read IRR first to possibly deassert an outstanding
|
||||
* interrupt.
|
||||
*/
|
||||
x = inb(Int0ctl); USED(x);
|
||||
outb(Int0ctl, Ocw3|0x03);
|
||||
x = inb(Int1ctl); USED(x);
|
||||
outb(Int1ctl, Ocw3|0x03);
|
||||
|
||||
/*
|
||||
* Check for Edge/Level register.
|
||||
* This check may not work for all chipsets.
|
||||
*/
|
||||
/* elcr1 = inb(Elcr1);
|
||||
outb(Elcr1, 0);
|
||||
if(inb(Elcr1) == 0){
|
||||
outb(Elcr1, 0x20);
|
||||
if(inb(Elcr1) == 0x20)
|
||||
elcr = (inb(Elcr2)<<8)|elcr1;
|
||||
}
|
||||
outb(Elcr1, elcr1);
|
||||
if(elcr)
|
||||
iprint("ELCR: %4.4uX\n", elcr);
|
||||
/**/
|
||||
}
|
||||
|
||||
int
|
||||
i8259isr(int v)
|
||||
{
|
||||
int isr;
|
||||
|
||||
/*
|
||||
* tell the 8259 that we're done with the
|
||||
* highest level interrupt (interrupts are still
|
||||
* off at this point)
|
||||
*/
|
||||
isr = 0;
|
||||
if(v >= VectorPIC && v <= MaxVectorPIC){
|
||||
isr = inb(Int0ctl);
|
||||
outb(Int0ctl, EOI);
|
||||
if(v >= VectorPIC+8){
|
||||
isr |= inb(Int1ctl)<<8;
|
||||
outb(Int1ctl, EOI);
|
||||
}
|
||||
}
|
||||
|
||||
return isr & (1<<(v-VectorPIC));
|
||||
}
|
||||
|
||||
int
|
||||
i8259enable(int v, int, Vctl* vctl)
|
||||
{
|
||||
if(v > MaxIrqPIC){
|
||||
print("i8259enable: vector %d out of range\n", v);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* enable corresponding interrupt in 8259
|
||||
*/
|
||||
if(v < 8){
|
||||
int0mask &= ~(1<<v);
|
||||
outb(Int0aux, int0mask);
|
||||
}
|
||||
else{
|
||||
int1mask &= ~(1<<(v-8));
|
||||
outb(Int1aux, int1mask);
|
||||
}
|
||||
|
||||
if(elcr & (1<<v))
|
||||
vctl->eoi = i8259isr;
|
||||
else
|
||||
vctl->isr = i8259isr;
|
||||
vctl->isintr = 1;
|
||||
|
||||
return v;
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
#include "/sys/src/libc/9syscall/sys.h"
|
||||
|
||||
/*
|
||||
* we pass in the argument of the exec parameters as 0(FP)
|
||||
*/
|
||||
|
||||
TEXT main(SB),$16
|
||||
|
||||
MOVQ $setSB(SB), R29
|
||||
MOVQ $boot(SB), R0
|
||||
ADDQ $24, R30, R1 /* get a pointer to 0(FP) */
|
||||
MOVL R0, 8(R30)
|
||||
MOVL R1, 12(R30)
|
||||
JSR exec(SB)
|
||||
|
||||
MOVQ $(1<<4), R0
|
||||
MOVL R0, 8(R30)
|
||||
MOVQ $RFORK, R0
|
||||
CALL_PAL $0x83
|
||||
MOVQ $RFORK, R0
|
||||
CALL_PAL $0x83
|
||||
MOVQ $RFORK, R0
|
||||
CALL_PAL $0x83
|
||||
again:
|
||||
ADDL $1, R1
|
||||
MOVQ $0, R0 /* print r1 */
|
||||
CALL_PAL $0x83
|
||||
MOVQ $100000000, R2
|
||||
foo:
|
||||
SUBQ $1, R2
|
||||
BNE R2, foo
|
||||
MOVQ $1000, R0
|
||||
MOVL R0, 8(R30)
|
||||
MOVQ $SLEEP, R0
|
||||
CALL_PAL $0x83
|
||||
JMP again
|
||||
|
||||
TEXT exec(SB), $0
|
||||
MOVQ $EXEC, R0
|
||||
CALL_PAL $0x83
|
||||
RET
|
||||
|
||||
DATA boot+0(SB)/5,$"/boot"
|
||||
DATA boot+5(SB)/5,$"/boot"
|
||||
DATA bootv+0(SB)/4,$boot+6(SB)
|
||||
GLOBL boot+0(SB),$11
|
||||
GLOBL bootv+0(SB),$8
|
|
@ -1,176 +0,0 @@
|
|||
enum {
|
||||
IrqCLOCK = 0,
|
||||
IrqKBD = 1,
|
||||
IrqUART1 = 3,
|
||||
IrqUART0 = 4,
|
||||
IrqPCMCIA = 5,
|
||||
IrqFLOPPY = 6,
|
||||
IrqLPT = 7,
|
||||
IrqIRQ7 = 7,
|
||||
IrqAUX = 12, /* PS/2 port */
|
||||
IrqIRQ13 = 13, /* coprocessor on 386 */
|
||||
IrqATA0 = 14,
|
||||
IrqATA1 = 15,
|
||||
MaxIrqPIC = 15,
|
||||
|
||||
VectorPIC = 64,
|
||||
MaxVectorPIC = VectorPIC+MaxIrqPIC,
|
||||
VectorPCI = 16, /* PCI bus (PLD) */
|
||||
};
|
||||
|
||||
typedef struct Vctl {
|
||||
Vctl* next; /* handlers on this vector */
|
||||
|
||||
char name[KNAMELEN]; /* of driver */
|
||||
int isintr; /* interrupt or fault/trap */
|
||||
int irq;
|
||||
int tbdf;
|
||||
int (*isr)(int); /* get isr bit for this irq */
|
||||
int (*eoi)(int); /* eoi */
|
||||
|
||||
void (*f)(Ureg*, void*); /* handler to call */
|
||||
void* a; /* argument to call it with */
|
||||
} Vctl;
|
||||
|
||||
enum {
|
||||
BusCBUS = 0, /* Corollary CBUS */
|
||||
BusCBUSII, /* Corollary CBUS II */
|
||||
BusEISA, /* Extended ISA */
|
||||
BusFUTURE, /* IEEE Futurebus */
|
||||
BusINTERN, /* Internal bus */
|
||||
BusISA, /* Industry Standard Architecture */
|
||||
BusMBI, /* Multibus I */
|
||||
BusMBII, /* Multibus II */
|
||||
BusMCA, /* Micro Channel Architecture */
|
||||
BusMPI, /* MPI */
|
||||
BusMPSA, /* MPSA */
|
||||
BusNUBUS, /* Apple Macintosh NuBus */
|
||||
BusPCI, /* Peripheral Component Interconnect */
|
||||
BusPCMCIA, /* PC Memory Card International Association */
|
||||
BusTC, /* DEC TurboChannel */
|
||||
BusVL, /* VESA Local bus */
|
||||
BusVME, /* VMEbus */
|
||||
BusXPRESS, /* Express System Bus */
|
||||
};
|
||||
|
||||
#define MKBUS(t,b,d,f) (((t)<<24)|(((b)&0xFF)<<16)|(((d)&0x1F)<<11)|(((f)&0x07)<<8))
|
||||
#define BUSFNO(tbdf) (((tbdf)>>8)&0x07)
|
||||
#define BUSDNO(tbdf) (((tbdf)>>11)&0x1F)
|
||||
#define BUSBNO(tbdf) (((tbdf)>>16)&0xFF)
|
||||
#define BUSTYPE(tbdf) ((tbdf)>>24)
|
||||
#define BUSDF(tbdf) ((tbdf)&0x000FF00)
|
||||
#define BUSBDF(tbdf) ((tbdf)&0x0FFFF00)
|
||||
#define BUSUNKNOWN (-1)
|
||||
|
||||
enum {
|
||||
MaxEISA = 16,
|
||||
EISAconfig = 0xC80,
|
||||
};
|
||||
|
||||
/*
|
||||
* PCI support code.
|
||||
*/
|
||||
enum { /* type 0 and type 1 pre-defined header */
|
||||
PciVID = 0x00, /* vendor ID */
|
||||
PciDID = 0x02, /* device ID */
|
||||
PciPCR = 0x04, /* command */
|
||||
PciPSR = 0x06, /* status */
|
||||
PciRID = 0x08, /* revision ID */
|
||||
PciCCRp = 0x09, /* programming interface class code */
|
||||
PciCCRu = 0x0A, /* sub-class code */
|
||||
PciCCRb = 0x0B, /* base class code */
|
||||
PciCLS = 0x0C, /* cache line size */
|
||||
PciLTR = 0x0D, /* latency timer */
|
||||
PciHDT = 0x0E, /* header type */
|
||||
PciBST = 0x0F, /* BIST */
|
||||
|
||||
PciBAR0 = 0x10, /* base address */
|
||||
PciBAR1 = 0x14,
|
||||
PciROM = 0x30,
|
||||
|
||||
PciINTL = 0x3C, /* interrupt line */
|
||||
PciINTP = 0x3D, /* interrupt pin */
|
||||
};
|
||||
|
||||
enum { /* type 0 pre-defined header */
|
||||
PciCIS = 0x28, /* cardbus CIS pointer */
|
||||
PciSVID = 0x2C, /* subsystem vendor ID */
|
||||
PciSID = 0x2E, /* subsystem ID */
|
||||
PciEBAR0 = 0x30, /* xpansion ROM base address */
|
||||
PciMGNT = 0x3E, /* burst period length */
|
||||
PciMLT = 0x3F, /* maximum latency between bursts */
|
||||
};
|
||||
|
||||
enum { /* type 1 pre-defined header */
|
||||
PciPBN = 0x18, /* primary bus number */
|
||||
PciSBN = 0x19, /* secondary bus number */
|
||||
PciUBN = 0x1A, /* subordinate bus number */
|
||||
PciSLTR = 0x1B, /* secondary latency timer */
|
||||
PciIBR = 0x1C, /* I/O base */
|
||||
PciILR = 0x1D, /* I/O limit */
|
||||
PciSPSR = 0x1E, /* secondary status */
|
||||
PciMBR = 0x20, /* memory base */
|
||||
PciMLR = 0x22, /* memory limit */
|
||||
PciPMBR = 0x24, /* prefetchable memory base */
|
||||
PciPMLR = 0x26, /* prefetchable memory limit */
|
||||
PciPUBR = 0x28, /* prefetchable base upper 32 bits */
|
||||
PciPULR = 0x2C, /* prefetchable limit upper 32 bits */
|
||||
PciIUBR = 0x30, /* I/O base upper 16 bits */
|
||||
PciIULR = 0x32, /* I/O limit upper 16 bits */
|
||||
PciEBAR1 = 0x28, /* expansion ROM base address */
|
||||
PciBCR = 0x3E, /* bridge control register */
|
||||
};
|
||||
|
||||
typedef struct Pcidev Pcidev;
|
||||
typedef struct Pcidev {
|
||||
int tbdf; /* type+bus+device+function */
|
||||
ushort vid; /* vendor ID */
|
||||
ushort did; /* device ID */
|
||||
|
||||
ushort pcr;
|
||||
|
||||
uchar rid;
|
||||
uchar ccrp;
|
||||
uchar ccru;
|
||||
uchar ccrb;
|
||||
uchar cls;
|
||||
uchar ltr;
|
||||
|
||||
struct {
|
||||
ulong bar; /* base address */
|
||||
int size;
|
||||
} mem[6];
|
||||
|
||||
uchar intl; /* interrupt line */
|
||||
|
||||
Pcidev* list;
|
||||
Pcidev* link; /* next device on this bno */
|
||||
|
||||
Pcidev* bridge; /* down a bus */
|
||||
struct {
|
||||
ulong bar;
|
||||
int size;
|
||||
} ioa, mema;
|
||||
|
||||
int pmrb; /* power management register block */
|
||||
};
|
||||
|
||||
#define PCIWINDOW 0x40000000
|
||||
#define PCIWADDR(va) (PADDR(va)+PCIWINDOW)
|
||||
#define ISAWINDOW 0x00800000
|
||||
#define ISAWADDR(va) (PADDR(va)+ISAWINDOW)
|
||||
|
||||
/*
|
||||
* PCMCIA support code.
|
||||
*/
|
||||
/*
|
||||
* Map between ISA memory space and PCMCIA card memory space.
|
||||
*/
|
||||
struct PCMmap {
|
||||
ulong ca; /* card address */
|
||||
ulong cea; /* card end address */
|
||||
ulong isa; /* ISA address */
|
||||
int len; /* length of the ISA area */
|
||||
int attr; /* attribute memory */
|
||||
int ref;
|
||||
};
|
|
@ -1,438 +0,0 @@
|
|||
#include "mem.h"
|
||||
#include "osf1pal.h"
|
||||
|
||||
#define SP R30
|
||||
|
||||
#define HI_IPL 6 /* use 7 to disable mchecks */
|
||||
|
||||
TEXT _main(SB), $-8
|
||||
MOVQ $setSB(SB), R29
|
||||
MOVQ R29, R16
|
||||
CALL_PAL $PALwrkgp
|
||||
MOVQ $mach0(SB), R(MACH)
|
||||
MOVQ $(BY2PG-8)(R(MACH)), R30
|
||||
MOVQ R31, R(USER)
|
||||
MOVQ R31, 0(R(MACH))
|
||||
|
||||
MOVQ $edata(SB), R1
|
||||
MOVQ $end(SB), R2
|
||||
clrbss:
|
||||
MOVQ R31, (R1)
|
||||
ADDQ $8, R1
|
||||
CMPUGT R1, R2, R3
|
||||
BEQ R3, clrbss
|
||||
|
||||
MOVL R0, bootconf(SB) /* passed in from boot loader */
|
||||
|
||||
_fpinit:
|
||||
MOVQ $1, R16
|
||||
CALL_PAL $PALwrfen
|
||||
|
||||
MOVQ initfpcr(SB), R1 /* MOVQ $0x2800800000000000, R1 */
|
||||
MOVQ R1, (R30)
|
||||
MOVT (R30), F1
|
||||
MOVT F1, FPCR
|
||||
|
||||
MOVT $0.5, F28
|
||||
ADDT F28, F28, F29
|
||||
ADDT F29, F29, F30
|
||||
|
||||
MOVT F31, F1
|
||||
MOVT F31, F2
|
||||
MOVT F31, F3
|
||||
MOVT F31, F4
|
||||
MOVT F31, F5
|
||||
MOVT F31, F6
|
||||
MOVT F31, F7
|
||||
MOVT F31, F8
|
||||
MOVT F31, F9
|
||||
MOVT F31, F10
|
||||
MOVT F31, F11
|
||||
MOVT F31, F12
|
||||
MOVT F31, F13
|
||||
MOVT F31, F14
|
||||
MOVT F31, F15
|
||||
MOVT F31, F16
|
||||
MOVT F31, F17
|
||||
MOVT F31, F18
|
||||
MOVT F31, F19
|
||||
MOVT F31, F20
|
||||
MOVT F31, F21
|
||||
MOVT F31, F22
|
||||
MOVT F31, F23
|
||||
MOVT F31, F24
|
||||
MOVT F31, F25
|
||||
MOVT F31, F26
|
||||
MOVT F31, F27
|
||||
|
||||
JSR main(SB)
|
||||
MOVQ $_divq(SB), R31 /* touch _divq etc.; doesn't need to execute */
|
||||
MOVQ $_divl(SB), R31 /* touch _divl etc.; doesn't need to execute */
|
||||
RET
|
||||
|
||||
TEXT setpcb(SB), $-8
|
||||
MOVQ R30, (R0)
|
||||
AND $0x7FFFFFFF, R0, R16 /* make address physical */
|
||||
CALL_PAL $PALswpctx
|
||||
RET
|
||||
|
||||
GLOBL mach0(SB), $(MAXMACH*BY2PG)
|
||||
GLOBL init_ptbr(SB), $8
|
||||
|
||||
TEXT firmware(SB), $-8
|
||||
CALL_PAL $PALhalt
|
||||
|
||||
TEXT xxfirmware(SB), $-8
|
||||
CALL_PAL $PALhalt
|
||||
|
||||
TEXT splhi(SB), $0
|
||||
|
||||
MOVL R26, 4(R(MACH)) /* save PC in m->splpc */
|
||||
MOVQ $HI_IPL, R16
|
||||
CALL_PAL $PALswpipl
|
||||
RET
|
||||
|
||||
TEXT spllo(SB), $0
|
||||
MOVQ R31, R16
|
||||
CALL_PAL $PALswpipl
|
||||
RET
|
||||
|
||||
TEXT splx(SB), $0
|
||||
MOVL R26, 4(R(MACH)) /* save PC in m->splpc */
|
||||
|
||||
TEXT splxpc(SB), $0 /* for iunlock */
|
||||
MOVQ R0, R16
|
||||
CALL_PAL $PALswpipl
|
||||
RET
|
||||
|
||||
TEXT spldone(SB), $0
|
||||
RET
|
||||
|
||||
TEXT islo(SB), $0
|
||||
CALL_PAL $PALrdps
|
||||
AND $IPL, R0
|
||||
XOR $HI_IPL, R0
|
||||
RET
|
||||
|
||||
TEXT mb(SB), $-8
|
||||
MB
|
||||
RET
|
||||
|
||||
TEXT icflush(SB), $-8
|
||||
CALL_PAL $PALimb
|
||||
RET
|
||||
|
||||
TEXT tlbflush(SB), $-8
|
||||
MOVQ R0, R16
|
||||
MOVL 4(FP), R17
|
||||
CALL_PAL $PALtbi
|
||||
RET
|
||||
|
||||
TEXT swpctx(SB), $-8
|
||||
MOVQ R0, R16
|
||||
AND $0x7FFFFFFF, R16 /* make address physical */
|
||||
CALL_PAL $PALswpctx
|
||||
RET
|
||||
|
||||
TEXT wrent(SB), $-8
|
||||
MOVQ R0, R17
|
||||
MOVL 4(FP), R16
|
||||
CALL_PAL $PALwrent
|
||||
RET
|
||||
|
||||
TEXT wrvptptr(SB), $-8
|
||||
MOVQ R0, R16
|
||||
CALL_PAL $PALwrvptptr
|
||||
RET
|
||||
|
||||
TEXT cserve(SB), $-8
|
||||
MOVQ R0, R16
|
||||
MOVL 4(FP), R17
|
||||
CALL_PAL $PALcserve
|
||||
RET
|
||||
|
||||
TEXT setlabel(SB), $-8
|
||||
MOVL R30, 0(R0)
|
||||
MOVL R26, 4(R0)
|
||||
MOVQ $0, R0
|
||||
RET
|
||||
|
||||
TEXT gotolabel(SB), $-8
|
||||
MOVL 0(R0), R30
|
||||
MOVL 4(R0), R26
|
||||
MOVQ $1, R0
|
||||
RET
|
||||
|
||||
TEXT tas(SB), $-8
|
||||
MOVQ R0, R1 /* l */
|
||||
tas1:
|
||||
MOVLL (R1), R0 /* l->key */
|
||||
BNE R0, tas2
|
||||
MOVQ $1, R2
|
||||
MOVLC R2, (R1) /* l->key = 1 */
|
||||
BEQ R2, tas1 /* write failed, try again? */
|
||||
tas2:
|
||||
RET
|
||||
|
||||
TEXT cmpswap(SB), $-8
|
||||
MOVQ R0, R1 /* p */
|
||||
MOVL old+4(FP), R2
|
||||
MOVL new+8(FP), R3
|
||||
MOVLL (R1), R0
|
||||
CMPEQ R0, R2, R4
|
||||
BEQ R4, fail /* if R0 != [sic] R2, goto fail */
|
||||
MOVQ R3, R0
|
||||
MOVLC R0, (R1)
|
||||
RET
|
||||
fail:
|
||||
MOVL $0, R0
|
||||
RET
|
||||
|
||||
TEXT fpenab(SB), $-8
|
||||
MOVQ R0, R16
|
||||
CALL_PAL $PALwrfen
|
||||
RET
|
||||
|
||||
TEXT rpcc(SB), $0
|
||||
MOVL R0, R1
|
||||
MOVL $0, R0
|
||||
WORD $0x6000C000 /* RPCC R0 */
|
||||
BEQ R1, _ret
|
||||
MOVQ R0, (R1)
|
||||
_ret:
|
||||
RET
|
||||
|
||||
/*
|
||||
* Exception handlers. The stack frame looks like this:
|
||||
*
|
||||
* R30+0: (unused) link reg storage (R26) (32 bits)
|
||||
* R30+4: padding for alignment (32 bits)
|
||||
* R30+8: trap()'s first arg storage (R0) (32 bits -- type Ureg*)
|
||||
* R30+12: padding for alignment (32 bits)
|
||||
* R30+16: first 31 fields of Ureg, saved here (31*64 bits)
|
||||
* R30+264: other 6 fields of Ureg, saved by PALcode (6*64 bits)
|
||||
* R30+312: previous value of KSP before trap
|
||||
*/
|
||||
|
||||
TEXT arith(SB), $-8
|
||||
SUBQ $(4*BY2WD+31*BY2V), R30
|
||||
MOVQ R0, (4*BY2WD+4*BY2V)(R30)
|
||||
MOVQ $1, R0
|
||||
JMP trapcommon
|
||||
|
||||
TEXT illegal0(SB), $-8
|
||||
SUBQ $(4*BY2WD+31*BY2V), R30
|
||||
MOVQ R0, (4*BY2WD+4*BY2V)(R30)
|
||||
MOVQ $2, R0
|
||||
JMP trapcommon
|
||||
|
||||
TEXT fault0(SB), $-8
|
||||
SUBQ $(4*BY2WD+31*BY2V), R30
|
||||
MOVQ R0, (4*BY2WD+4*BY2V)(R30)
|
||||
MOVQ $4, R0
|
||||
JMP trapcommon
|
||||
|
||||
TEXT unaligned(SB), $-8
|
||||
SUBQ $(4*BY2WD+31*BY2V), R30
|
||||
MOVQ R0, (4*BY2WD+4*BY2V)(R30)
|
||||
MOVQ $6, R0
|
||||
JMP trapcommon
|
||||
|
||||
TEXT intr0(SB), $-8
|
||||
SUBQ $(4*BY2WD+31*BY2V), R30
|
||||
MOVQ R0, (4*BY2WD+4*BY2V)(R30)
|
||||
MOVQ $3, R0
|
||||
|
||||
trapcommon:
|
||||
MOVQ R0, (4*BY2WD+0*BY2V)(R30)
|
||||
MOVQ R16, (4*BY2WD+1*BY2V)(R30)
|
||||
MOVQ R17, (4*BY2WD+2*BY2V)(R30)
|
||||
MOVQ R18, (4*BY2WD+3*BY2V)(R30)
|
||||
|
||||
/* R0 already saved, (4*BY2WD+4*BY2V)(R30) */
|
||||
MOVQ R1, (4*BY2WD+5*BY2V)(R30)
|
||||
MOVQ R2, (4*BY2WD+6*BY2V)(R30)
|
||||
MOVQ R3, (4*BY2WD+7*BY2V)(R30)
|
||||
MOVQ R4, (4*BY2WD+8*BY2V)(R30)
|
||||
MOVQ R5, (4*BY2WD+9*BY2V)(R30)
|
||||
MOVQ R6, (4*BY2WD+10*BY2V)(R30)
|
||||
MOVQ R7, (4*BY2WD+11*BY2V)(R30)
|
||||
MOVQ R8, (4*BY2WD+12*BY2V)(R30)
|
||||
MOVQ R9, (4*BY2WD+13*BY2V)(R30)
|
||||
MOVQ R10, (4*BY2WD+14*BY2V)(R30)
|
||||
MOVQ R11, (4*BY2WD+15*BY2V)(R30)
|
||||
MOVQ R12, (4*BY2WD+16*BY2V)(R30)
|
||||
MOVQ R13, (4*BY2WD+17*BY2V)(R30)
|
||||
MOVQ R14, (4*BY2WD+18*BY2V)(R30)
|
||||
MOVQ R15, (4*BY2WD+19*BY2V)(R30)
|
||||
MOVQ R19, (4*BY2WD+20*BY2V)(R30)
|
||||
MOVQ R20, (4*BY2WD+21*BY2V)(R30)
|
||||
MOVQ R21, (4*BY2WD+22*BY2V)(R30)
|
||||
MOVQ R22, (4*BY2WD+23*BY2V)(R30)
|
||||
MOVQ R23, (4*BY2WD+24*BY2V)(R30)
|
||||
MOVQ R24, (4*BY2WD+25*BY2V)(R30)
|
||||
MOVQ R25, (4*BY2WD+26*BY2V)(R30)
|
||||
MOVQ R26, (4*BY2WD+27*BY2V)(R30)
|
||||
MOVQ R27, (4*BY2WD+28*BY2V)(R30)
|
||||
MOVQ R28, (4*BY2WD+29*BY2V)(R30)
|
||||
|
||||
MOVQ $HI_IPL, R16
|
||||
CALL_PAL $PALswpipl
|
||||
|
||||
CALL_PAL $PALrdusp
|
||||
MOVQ R0, (4*BY2WD+30*BY2V)(R30) /* save USP */
|
||||
|
||||
MOVQ $mach0(SB), R(MACH)
|
||||
MOVQ $(4*BY2WD)(R30), R0
|
||||
JSR trap(SB)
|
||||
trapret:
|
||||
MOVQ (4*BY2WD+30*BY2V)(R30), R16 /* USP */
|
||||
CALL_PAL $PALwrusp /* ... */
|
||||
MOVQ (4*BY2WD+4*BY2V)(R30), R0
|
||||
MOVQ (4*BY2WD+5*BY2V)(R30), R1
|
||||
MOVQ (4*BY2WD+6*BY2V)(R30), R2
|
||||
MOVQ (4*BY2WD+7*BY2V)(R30), R3
|
||||
MOVQ (4*BY2WD+8*BY2V)(R30), R4
|
||||
MOVQ (4*BY2WD+9*BY2V)(R30), R5
|
||||
MOVQ (4*BY2WD+10*BY2V)(R30), R6
|
||||
MOVQ (4*BY2WD+11*BY2V)(R30), R7
|
||||
MOVQ (4*BY2WD+12*BY2V)(R30), R8
|
||||
MOVQ (4*BY2WD+13*BY2V)(R30), R9
|
||||
MOVQ (4*BY2WD+14*BY2V)(R30), R10
|
||||
MOVQ (4*BY2WD+15*BY2V)(R30), R11
|
||||
MOVQ (4*BY2WD+16*BY2V)(R30), R12
|
||||
MOVQ (4*BY2WD+17*BY2V)(R30), R13
|
||||
MOVQ (4*BY2WD+18*BY2V)(R30), R14
|
||||
MOVQ (4*BY2WD+19*BY2V)(R30), R15
|
||||
MOVQ (4*BY2WD+20*BY2V)(R30), R19
|
||||
MOVQ (4*BY2WD+21*BY2V)(R30), R20
|
||||
MOVQ (4*BY2WD+22*BY2V)(R30), R21
|
||||
MOVQ (4*BY2WD+23*BY2V)(R30), R22
|
||||
MOVQ (4*BY2WD+24*BY2V)(R30), R23
|
||||
MOVQ (4*BY2WD+25*BY2V)(R30), R24
|
||||
MOVQ (4*BY2WD+26*BY2V)(R30), R25
|
||||
MOVQ (4*BY2WD+27*BY2V)(R30), R26
|
||||
MOVQ (4*BY2WD+28*BY2V)(R30), R27
|
||||
MOVQ (4*BY2WD+29*BY2V)(R30), R28
|
||||
/* USP already restored from (4*BY2WD+30*BY2V)(R30) */
|
||||
ADDQ $(4*BY2WD+31*BY2V), R30
|
||||
CALL_PAL $PALrti
|
||||
|
||||
TEXT forkret(SB), $0
|
||||
MOVQ R31, R0 /* Fake out system call return */
|
||||
JMP systrapret
|
||||
|
||||
TEXT syscall0(SB), $-8
|
||||
SUBQ $(4*BY2WD+31*BY2V), R30
|
||||
MOVQ R0, (4*BY2WD+4*BY2V)(R30) /* save scallnr in R0 */
|
||||
MOVQ $HI_IPL, R16
|
||||
CALL_PAL $PALswpipl
|
||||
MOVQ $mach0(SB), R(MACH)
|
||||
CALL_PAL $PALrdusp
|
||||
MOVQ R0, (4*BY2WD+30*BY2V)(R30) /* save USP */
|
||||
MOVQ R26, (4*BY2WD+27*BY2V)(R30) /* save last return address */
|
||||
MOVQ $(4*BY2WD)(R30), R0 /* pass address of Ureg */
|
||||
JSR syscall(SB)
|
||||
systrapret:
|
||||
MOVQ (4*BY2WD+30*BY2V)(R30), R16 /* USP */
|
||||
CALL_PAL $PALwrusp /* consider doing this in execregs... */
|
||||
MOVQ (4*BY2WD+27*BY2V)(R30), R26 /* restore last return address */
|
||||
ADDQ $(4*BY2WD+31*BY2V), R30
|
||||
CALL_PAL $PALretsys
|
||||
|
||||
/*
|
||||
* Take first processor into user mode
|
||||
* - argument is stack pointer to user
|
||||
*/
|
||||
|
||||
TEXT touser(SB), $-8
|
||||
MOVQ R0, R16
|
||||
CALL_PAL $PALwrusp /* set USP to value passed */
|
||||
SUBQ $(6*BY2V), R30 /* create frame for retsys */
|
||||
MOVQ $(UTZERO+32), R26 /* header appears in text */
|
||||
MOVQ R26, (1*BY2V)(R30) /* PC -- only reg that matters */
|
||||
CALL_PAL $PALretsys
|
||||
|
||||
TEXT rfnote(SB), $0
|
||||
SUBL $(2*BY2WD), R0, SP
|
||||
JMP trapret
|
||||
|
||||
TEXT savefpregs(SB), $-8
|
||||
MOVT F0, 0x00(R0)
|
||||
MOVT F1, 0x08(R0)
|
||||
MOVT F2, 0x10(R0)
|
||||
MOVT F3, 0x18(R0)
|
||||
MOVT F4, 0x20(R0)
|
||||
MOVT F5, 0x28(R0)
|
||||
MOVT F6, 0x30(R0)
|
||||
MOVT F7, 0x38(R0)
|
||||
MOVT F8, 0x40(R0)
|
||||
MOVT F9, 0x48(R0)
|
||||
MOVT F10, 0x50(R0)
|
||||
MOVT F11, 0x58(R0)
|
||||
MOVT F12, 0x60(R0)
|
||||
MOVT F13, 0x68(R0)
|
||||
MOVT F14, 0x70(R0)
|
||||
MOVT F15, 0x78(R0)
|
||||
MOVT F16, 0x80(R0)
|
||||
MOVT F17, 0x88(R0)
|
||||
MOVT F18, 0x90(R0)
|
||||
MOVT F19, 0x98(R0)
|
||||
MOVT F20, 0xA0(R0)
|
||||
MOVT F21, 0xA8(R0)
|
||||
MOVT F22, 0xB0(R0)
|
||||
MOVT F23, 0xB8(R0)
|
||||
MOVT F24, 0xC0(R0)
|
||||
MOVT F25, 0xC8(R0)
|
||||
MOVT F26, 0xD0(R0)
|
||||
MOVT F27, 0xD8(R0)
|
||||
MOVT F28, 0xE0(R0)
|
||||
MOVT F29, 0xE8(R0)
|
||||
MOVT F30, 0xF0(R0)
|
||||
MOVT F31, 0xF8(R0)
|
||||
MOVT FPCR, F0
|
||||
MOVT F0, 0x100(R0)
|
||||
|
||||
MOVQ $0, R16
|
||||
CALL_PAL $PALwrfen /* disable */
|
||||
RET
|
||||
|
||||
TEXT restfpregs(SB), $-8
|
||||
MOVQ $1, R16
|
||||
CALL_PAL $PALwrfen /* enable */
|
||||
|
||||
MOVT 0x100(R0), F0
|
||||
MOVT F0, FPCR
|
||||
MOVT 0x00(R0), F0
|
||||
MOVT 0x08(R0), F1
|
||||
MOVT 0x10(R0), F2
|
||||
MOVT 0x18(R0), F3
|
||||
MOVT 0x20(R0), F4
|
||||
MOVT 0x28(R0), F5
|
||||
MOVT 0x30(R0), F6
|
||||
MOVT 0x38(R0), F7
|
||||
MOVT 0x40(R0), F8
|
||||
MOVT 0x48(R0), F9
|
||||
MOVT 0x50(R0), F10
|
||||
MOVT 0x58(R0), F11
|
||||
MOVT 0x60(R0), F12
|
||||
MOVT 0x68(R0), F13
|
||||
MOVT 0x70(R0), F14
|
||||
MOVT 0x78(R0), F15
|
||||
MOVT 0x80(R0), F16
|
||||
MOVT 0x88(R0), F17
|
||||
MOVT 0x90(R0), F18
|
||||
MOVT 0x98(R0), F19
|
||||
MOVT 0xA0(R0), F20
|
||||
MOVT 0xA8(R0), F21
|
||||
MOVT 0xB0(R0), F22
|
||||
MOVT 0xB8(R0), F23
|
||||
MOVT 0xC0(R0), F24
|
||||
MOVT 0xC8(R0), F25
|
||||
MOVT 0xD0(R0), F26
|
||||
MOVT 0xD8(R0), F27
|
||||
MOVT 0xE0(R0), F28
|
||||
MOVT 0xE8(R0), F29
|
||||
MOVT 0xF0(R0), F30
|
||||
MOVT 0xF8(R0), F31
|
||||
RET
|
|
@ -1,604 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
#include "init.h"
|
||||
#include "pool.h"
|
||||
#include "/sys/src/boot/alphapc/conf.h"
|
||||
#include "axp.h"
|
||||
|
||||
char argbuf[128]; /* arguments passed to initcode and /boot */
|
||||
|
||||
Hwrpb *hwrpb;
|
||||
Bootconf *bootconf;
|
||||
Conf conf;
|
||||
FPsave initfp;
|
||||
/* setfcr(FPPDBL|FPRNR|FPINVAL|FPZDIV|FPOVFL) */
|
||||
uvlong initfpcr = (1LL<62)|(1LL<61)|(1LL<60)|(2LL<<58)|(1LL<48);
|
||||
|
||||
char bootargs[BOOTARGSLEN];
|
||||
char *confname[MAXCONF];
|
||||
char *confval[MAXCONF];
|
||||
int nconf;
|
||||
|
||||
static void
|
||||
options(void)
|
||||
{
|
||||
long i, n;
|
||||
char *cp, *line[MAXCONF], *p, *q;
|
||||
|
||||
cp = bootargs;
|
||||
strncpy(cp, bootconf->bootargs, BOOTARGSLEN);
|
||||
cp[BOOTARGSLEN-1] = 0;
|
||||
/* can't print in this routine, see below in main() */
|
||||
|
||||
/*
|
||||
* Strip out '\r', change '\t' -> ' '.
|
||||
*/
|
||||
p = cp;
|
||||
for(q = cp; *q; q++){
|
||||
if(*q == '\r')
|
||||
continue;
|
||||
if(*q == '\t')
|
||||
*q = ' ';
|
||||
*p++ = *q;
|
||||
}
|
||||
*p = 0;
|
||||
|
||||
n = getfields(cp, line, MAXCONF, 1, "\n");
|
||||
for(i = 0; i < n; i++){
|
||||
if(*line[i] == '#')
|
||||
continue;
|
||||
cp = strchr(line[i], '=');
|
||||
if(cp == nil)
|
||||
continue;
|
||||
*cp++ = '\0';
|
||||
confname[nconf] = line[i];
|
||||
confval[nconf] = cp;
|
||||
nconf++;
|
||||
}
|
||||
}
|
||||
|
||||
/* debugging only */
|
||||
static void
|
||||
dumpopts(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
print("dumpopts: found /alpha/conf options at %#p\n",
|
||||
bootconf->bootargs);
|
||||
for(i = 0; i < nconf; i++)
|
||||
print("dumpopts: read %s=%s\n", confname[i], confval[i]);
|
||||
}
|
||||
|
||||
extern void (*i8237alloc)(void);
|
||||
|
||||
void
|
||||
main(void)
|
||||
{
|
||||
hwrpb = (Hwrpb*)0x10000000;
|
||||
hwrpb = (Hwrpb*)(KZERO|hwrpb->phys);
|
||||
arginit();
|
||||
machinit();
|
||||
options();
|
||||
ioinit();
|
||||
clockinit();
|
||||
confinit();
|
||||
archinit();
|
||||
xinit();
|
||||
memholes();
|
||||
if(i8237alloc != nil)
|
||||
i8237alloc();
|
||||
mmuinit();
|
||||
if(arch->coreinit)
|
||||
arch->coreinit();
|
||||
trapinit();
|
||||
screeninit();
|
||||
printinit();
|
||||
/* it's now safe to print */
|
||||
/* dumpopts(); /* DEBUG */
|
||||
i8250console();
|
||||
quotefmtinstall();
|
||||
print("\nPlan 9\n");
|
||||
|
||||
cpuidprint();
|
||||
if(arch->corehello)
|
||||
arch->corehello();
|
||||
|
||||
procinit0();
|
||||
initseg();
|
||||
timersinit();
|
||||
links();
|
||||
chandevreset();
|
||||
pageinit();
|
||||
swapinit();
|
||||
savefpregs(&initfp);
|
||||
initfp.fpstatus = 0x68028000;
|
||||
userinit();
|
||||
schedinit();
|
||||
}
|
||||
|
||||
/* cpu->state bits */
|
||||
enum {
|
||||
Cpubootinprog = 1, /* boot in progress */
|
||||
Cpucanrestart = 2, /* restart possible */
|
||||
Cpuavail = 4, /* processor available */
|
||||
Cpuexists = 8, /* processor present */
|
||||
Cpuuserhalted = 0x10, /* user halted */
|
||||
Cpuctxtokay = 0x20, /* context valid */
|
||||
Cpupalokay = 0x40, /* PALcode valid */
|
||||
Cpupalmemokay = 0x80, /* PALcode memory valid */
|
||||
Cpupalloaded = 0x100, /* PALcode loaded */
|
||||
Cpuhaltmask = 0xff0000, /* halt request mask */
|
||||
Cpuhaltdflt = 0,
|
||||
Cpuhaltsaveexit = 0x10000,
|
||||
Cpuhaltcoldboot = 0x20000,
|
||||
Cpuhaltwarmboot = 0x30000,
|
||||
Cpuhaltstayhalted = 0x40000,
|
||||
Cpumustbezero = 0xffffffffff000000ULL, /* 24:63 -- must be zero */
|
||||
};
|
||||
|
||||
/*
|
||||
* initialize a processor's mach structure. each processor does this
|
||||
* for itself.
|
||||
*/
|
||||
void
|
||||
machinit(void)
|
||||
{
|
||||
int n;
|
||||
Hwcpu *cpu;
|
||||
|
||||
icflush();
|
||||
n = m->machno;
|
||||
memset(m, 0, sizeof(Mach));
|
||||
m->machno = n;
|
||||
|
||||
active.exiting = 0;
|
||||
active.machs[0] = 1;
|
||||
|
||||
cpu = (Hwcpu*) ((ulong)hwrpb + hwrpb->cpuoff + n*hwrpb->cpulen);
|
||||
cpu->state &= ~Cpubootinprog;
|
||||
if (0)
|
||||
cpu->state |= Cpuhaltstayhalted;
|
||||
}
|
||||
|
||||
void
|
||||
init0(void)
|
||||
{
|
||||
int i;
|
||||
char buf[2*KNAMELEN];
|
||||
|
||||
up->nerrlab = 0;
|
||||
|
||||
spllo();
|
||||
|
||||
/*
|
||||
* These are o.k. because rootinit is null.
|
||||
* Then early kproc's will have a root and dot.
|
||||
*/
|
||||
up->slash = namec("#/", Atodir, 0, 0);
|
||||
pathclose(up->slash->path);
|
||||
up->slash->path = newpath("/");
|
||||
up->dot = cclone(up->slash);
|
||||
|
||||
chandevinit();
|
||||
|
||||
if(!waserror()){
|
||||
snprint(buf, sizeof(buf), "alpha %s alphapc", conffile);
|
||||
ksetenv("terminal", buf, 0);
|
||||
ksetenv("cputype", "alpha", 0);
|
||||
if(cpuserver)
|
||||
ksetenv("service", "cpu", 0);
|
||||
else
|
||||
ksetenv("service", "terminal", 0);
|
||||
for(i = 0; i < nconf; i++)
|
||||
if(confname[i]){
|
||||
if(confname[i][0] != '*')
|
||||
ksetenv(confname[i], confval[i], 0);
|
||||
ksetenv(confname[i], confval[i], 1);
|
||||
}
|
||||
poperror();
|
||||
}
|
||||
|
||||
kproc("alarm", alarmkproc, 0);
|
||||
touser((uchar*)(USTKTOP - sizeof(argbuf)));
|
||||
}
|
||||
|
||||
void
|
||||
userinit(void)
|
||||
{
|
||||
Proc *p;
|
||||
Segment *s;
|
||||
KMap *k;
|
||||
char **av;
|
||||
Page *pg;
|
||||
|
||||
p = newproc();
|
||||
p->pgrp = newpgrp();
|
||||
p->egrp = smalloc(sizeof(Egrp));
|
||||
p->egrp->ref = 1;
|
||||
p->fgrp = dupfgrp(nil);
|
||||
p->rgrp = newrgrp();
|
||||
p->procmode = 0640;
|
||||
|
||||
kstrdup(&eve, "");
|
||||
kstrdup(&p->text, "*init*");
|
||||
kstrdup(&p->user, eve);
|
||||
|
||||
procsetup(p);
|
||||
|
||||
/*
|
||||
* Kernel Stack
|
||||
*/
|
||||
p->sched.pc = (ulong)init0;
|
||||
p->sched.sp = (ulong)p->kstack+KSTACK-MAXSYSARG*BY2WD;
|
||||
/*
|
||||
* User Stack, pass input arguments to boot process
|
||||
*/
|
||||
s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
|
||||
p->seg[SSEG] = s;
|
||||
pg = newpage(1, 0, USTKTOP-BY2PG);
|
||||
segpage(s, pg);
|
||||
k = kmap(pg);
|
||||
for(av = (char**)argbuf; *av; av++)
|
||||
*av += (USTKTOP - sizeof(argbuf)) - (ulong)argbuf;
|
||||
|
||||
memmove((uchar*)VA(k) + BY2PG - sizeof(argbuf), argbuf, sizeof argbuf);
|
||||
kunmap(k);
|
||||
|
||||
/*
|
||||
* Text
|
||||
*/
|
||||
s = newseg(SG_TEXT, UTZERO, 1);
|
||||
s->flushme++;
|
||||
p->seg[TSEG] = s;
|
||||
pg = newpage(1, 0, UTZERO);
|
||||
pg->txtflush = ~0;
|
||||
segpage(s, pg);
|
||||
k = kmap(s->map[0]->pages[0]);
|
||||
memmove((uchar*)VA(k), initcode, sizeof initcode);
|
||||
kunmap(k);
|
||||
|
||||
ready(p);
|
||||
}
|
||||
|
||||
void
|
||||
procsetup(Proc *p)
|
||||
{
|
||||
p->fpstate = FPinit;
|
||||
fpenab(0);
|
||||
}
|
||||
|
||||
void
|
||||
procfork(Proc *)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
procsave(Proc *p)
|
||||
{
|
||||
if(p->fpstate == FPactive){
|
||||
if(p->state == Moribund)
|
||||
fpenab(0);
|
||||
else
|
||||
savefpregs(&up->fpsave);
|
||||
p->fpstate = FPinactive;
|
||||
}
|
||||
|
||||
/*
|
||||
* Switch to the prototype page tables for this processor.
|
||||
* While this processor is in the scheduler, the process could run
|
||||
* on another processor and exit, returning the page tables to
|
||||
* the free list where they could be reallocated and overwritten.
|
||||
* When this processor eventually has to get an entry from the
|
||||
* trashed page tables it will crash.
|
||||
*/
|
||||
mmupark();
|
||||
}
|
||||
|
||||
void
|
||||
setupboot(int halt)
|
||||
{
|
||||
int n = 0; // cpu id of primary cpu, not just m->machno
|
||||
Hwcpu *cpu = (Hwcpu*)((ulong)hwrpb + hwrpb->cpuoff + n*hwrpb->cpulen);
|
||||
|
||||
cpu->state &= ~(Cpucanrestart | Cpuhaltmask);
|
||||
cpu->state |= (halt? Cpuhaltstayhalted: Cpuhaltwarmboot);
|
||||
}
|
||||
|
||||
void
|
||||
reboot(void *, void *, ulong)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
exit(int)
|
||||
{
|
||||
cpushutdown();
|
||||
splhi();
|
||||
if(arch->coredetach)
|
||||
arch->coredetach();
|
||||
setupboot(1); // set up to halt
|
||||
for (;;)
|
||||
firmware();
|
||||
}
|
||||
|
||||
void
|
||||
confinit(void)
|
||||
{
|
||||
ulong ktop, kpages;
|
||||
Bank *b, *eb;
|
||||
extern void _main(void);
|
||||
int userpcnt;
|
||||
char *p;
|
||||
|
||||
if(p = getconf("*kernelpercent"))
|
||||
userpcnt = 100 - strtol(p, 0, 0);
|
||||
else
|
||||
userpcnt = 0;
|
||||
|
||||
/*
|
||||
* The console firmware divides memory into 1 or more banks.
|
||||
* FInd the bank with the kernel in it.
|
||||
*/
|
||||
b = bootconf->bank;
|
||||
eb = b+bootconf->nbank;
|
||||
ktop = PGROUND((ulong)end);
|
||||
ktop = PADDR(ktop);
|
||||
while(b < eb) {
|
||||
if(b->min < ktop && ktop < b->max)
|
||||
break;
|
||||
b++;
|
||||
}
|
||||
if(b == eb)
|
||||
panic("confinit");
|
||||
|
||||
/*
|
||||
* Split the bank of memory into 2 banks to fool the allocator into
|
||||
* allocating low memory pages from bank 0 for any peripherals
|
||||
* which only have a 24bit address counter.
|
||||
*/
|
||||
conf.mem[0].npage = (8*1024*1024)/BY2PG;
|
||||
conf.mem[0].base = 0;
|
||||
|
||||
conf.mem[1].npage = (b->max-8*1024*1024)/BY2PG;
|
||||
conf.mem[1].base = 8*1024*1024;
|
||||
|
||||
conf.npage = conf.mem[0].npage+conf.mem[1].npage;
|
||||
conf.upages = (conf.npage*70)/100;
|
||||
|
||||
conf.mem[0].npage -= ktop/BY2PG;
|
||||
conf.mem[0].base += ktop;
|
||||
conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
|
||||
|
||||
/*
|
||||
* Fix up the bank we found to be the remnant, below the kernel.
|
||||
* This, and the other banks, will be passed to xhole() later.
|
||||
* BUG: conf.upages needs to be adjusted, but how? In practice,
|
||||
* we only have 1 bank, and the remnant is small.
|
||||
*/
|
||||
b->max = (uvlong)_main & ~(BY2PG-1);
|
||||
|
||||
conf.nmach = 1;
|
||||
conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
|
||||
if(cpuserver)
|
||||
conf.nproc *= 3;
|
||||
if(conf.nproc > 2000)
|
||||
conf.nproc = 2000;
|
||||
conf.nimage = 200;
|
||||
conf.nswap = conf.nproc*80;
|
||||
conf.nswppo = 4096;
|
||||
conf.copymode = 0; /* copy on write */
|
||||
|
||||
if(cpuserver) {
|
||||
if(userpcnt < 10)
|
||||
userpcnt = 70;
|
||||
kpages = conf.npage - (conf.npage*userpcnt)/100;
|
||||
|
||||
/*
|
||||
* Hack for the big boys. Only good while physmem < 4GB.
|
||||
* Give the kernel a max. of 16MB + enough to allocate the
|
||||
* page pool.
|
||||
* This is an overestimate as conf.upages < conf.npages.
|
||||
* The patch of nimage is a band-aid, scanning the whole
|
||||
* page list in imagereclaim just takes too long.
|
||||
*/
|
||||
if(kpages > (16*MB + conf.npage*sizeof(Page))/BY2PG){
|
||||
kpages = (16*MB + conf.npage*sizeof(Page))/BY2PG;
|
||||
conf.nimage = 2000;
|
||||
kpages += (conf.nproc*KSTACK)/BY2PG;
|
||||
}
|
||||
} else {
|
||||
if(userpcnt < 10) {
|
||||
if(conf.npage*BY2PG < 16*MB)
|
||||
userpcnt = 40;
|
||||
else
|
||||
userpcnt = 60;
|
||||
}
|
||||
kpages = conf.npage - (conf.npage*userpcnt)/100;
|
||||
|
||||
/*
|
||||
* Make sure terminals with low memory get at least
|
||||
* 4MB on the first Image chunk allocation.
|
||||
*/
|
||||
if(conf.npage*BY2PG < 16*MB)
|
||||
imagmem->minarena = 4*1024*1024;
|
||||
}
|
||||
conf.upages = conf.npage - kpages;
|
||||
conf.ialloc = (kpages/2)*BY2PG;
|
||||
|
||||
/*
|
||||
* Guess how much is taken by the large permanent
|
||||
* datastructures. Mntcache and Mntrpc are not accounted for.
|
||||
*/
|
||||
kpages *= BY2PG;
|
||||
kpages -= conf.upages*sizeof(Page)
|
||||
+ conf.nproc*sizeof(Proc)
|
||||
+ conf.nimage*sizeof(Image)
|
||||
+ conf.nswap
|
||||
+ conf.nswppo*sizeof(Page*);
|
||||
mainmem->maxsize = kpages;
|
||||
if(!cpuserver){
|
||||
/*
|
||||
* give terminals lots of image memory, too; the dynamic
|
||||
* allocation will balance the load properly, hopefully.
|
||||
* be careful with 32-bit overflow.
|
||||
*/
|
||||
imagmem->maxsize = kpages;
|
||||
}
|
||||
|
||||
// conf.monitor = 1; /* BUG */
|
||||
}
|
||||
|
||||
void
|
||||
memholes(void)
|
||||
{
|
||||
Bank *b, *eb;
|
||||
|
||||
b = bootconf->bank;
|
||||
eb = b+bootconf->nbank;
|
||||
while(b < eb) {
|
||||
if(b->min < (1LL<<32) && b->max < (1LL<<32))
|
||||
xhole(b->min, b->max-b->min);
|
||||
b++;
|
||||
}
|
||||
}
|
||||
|
||||
char *sp;
|
||||
|
||||
char *
|
||||
pusharg(char *p)
|
||||
{
|
||||
int n;
|
||||
|
||||
n = strlen(p)+1;
|
||||
sp -= n;
|
||||
memmove(sp, p, n);
|
||||
return sp;
|
||||
}
|
||||
|
||||
void
|
||||
arginit(void)
|
||||
{
|
||||
char **av;
|
||||
|
||||
av = (char**)argbuf;
|
||||
sp = argbuf + sizeof(argbuf);
|
||||
*av++ = pusharg("boot");
|
||||
*av = 0;
|
||||
}
|
||||
|
||||
char *
|
||||
getconf(char *name)
|
||||
{
|
||||
int n;
|
||||
|
||||
for(n = 0; n < nconf; n++)
|
||||
if(cistrcmp(confname[n], name) == 0) {
|
||||
return confval[n];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
isaconfig(char *class, int ctlrno, ISAConf *isa)
|
||||
{
|
||||
char cc[32], *p;
|
||||
int i, n;
|
||||
|
||||
snprint(cc, sizeof cc, "%s%d", class, ctlrno);
|
||||
for(n = 0; n < nconf; n++){
|
||||
if(cistrcmp(confname[n], cc) != 0)
|
||||
continue;
|
||||
isa->nopt = tokenize(confval[n], isa->opt, NISAOPT);
|
||||
for(i = 0; i < isa->nopt; i++){
|
||||
p = isa->opt[i];
|
||||
if(cistrncmp(p, "type=", 5) == 0)
|
||||
isa->type = p + 5;
|
||||
else if(cistrncmp(p, "port=", 5) == 0)
|
||||
isa->port = strtoul(p+5, &p, 0);
|
||||
else if(cistrncmp(p, "irq=", 4) == 0)
|
||||
isa->irq = strtoul(p+4, &p, 0);
|
||||
else if(cistrncmp(p, "dma=", 4) == 0)
|
||||
isa->dma = strtoul(p+4, &p, 0);
|
||||
else if(cistrncmp(p, "mem=", 4) == 0)
|
||||
isa->mem = strtoul(p+4, &p, 0);
|
||||
else if(cistrncmp(p, "size=", 5) == 0)
|
||||
isa->size = strtoul(p+5, &p, 0);
|
||||
else if(cistrncmp(p, "freq=", 5) == 0)
|
||||
isa->freq = strtoul(p+5, &p, 0);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cistrcmp(char *a, char *b)
|
||||
{
|
||||
int ac, bc;
|
||||
|
||||
for(;;){
|
||||
ac = *a++;
|
||||
bc = *b++;
|
||||
|
||||
if(ac >= 'A' && ac <= 'Z')
|
||||
ac = 'a' + (ac - 'A');
|
||||
if(bc >= 'A' && bc <= 'Z')
|
||||
bc = 'a' + (bc - 'A');
|
||||
ac -= bc;
|
||||
if(ac)
|
||||
return ac;
|
||||
if(bc == 0)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cistrncmp(char *a, char *b, int n)
|
||||
{
|
||||
unsigned ac, bc;
|
||||
|
||||
while(n > 0){
|
||||
ac = *a++;
|
||||
bc = *b++;
|
||||
n--;
|
||||
|
||||
if(ac >= 'A' && ac <= 'Z')
|
||||
ac = 'a' + (ac - 'A');
|
||||
if(bc >= 'A' && bc <= 'Z')
|
||||
bc = 'a' + (bc - 'A');
|
||||
|
||||
ac -= bc;
|
||||
if(ac)
|
||||
return ac;
|
||||
if(bc == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
getcfields(char* lp, char** fields, int n, char* sep)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; lp && *lp && i < n; i++){
|
||||
while(*lp && strchr(sep, *lp) != 0)
|
||||
*lp++ = 0;
|
||||
if(*lp == 0)
|
||||
break;
|
||||
fields[i] = lp;
|
||||
while(*lp && strchr(sep, *lp) == 0){
|
||||
if(*lp == '\\' && *(lp+1) == '\n')
|
||||
*lp++ = ' ';
|
||||
lp++;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
/*
|
||||
* Memory and machine-specific definitions. Used in C and assembler.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Sizes
|
||||
*/
|
||||
#define BI2BY 8 /* bits per byte */
|
||||
#define BI2WD 32 /* bits per word */
|
||||
#define BY2WD 4 /* bytes per word */
|
||||
#define BY2V 8 /* bytes per vlong */
|
||||
#define BY2PG 8192 /* bytes per page */
|
||||
#define WD2PG (BY2PG/BY2WD) /* words per page */
|
||||
#define PGSHIFT 13 /* log(BY2PG) */
|
||||
#define ROUND(s, sz) (((s)+((sz)-1))&~((sz)-1))
|
||||
#define PGROUND(s) ROUND(s, BY2PG)
|
||||
#define BLOCKALIGN 8
|
||||
|
||||
#define BY2PTE 8 /* bytes per pte entry */
|
||||
#define PTE2PG (BY2PG/BY2PTE) /* pte entries per page */
|
||||
|
||||
#define MAXMACH 1 /* max # cpus system can run */
|
||||
#define KSTACK 4096 /* Size of kernel stack */
|
||||
|
||||
/*
|
||||
* Time
|
||||
*/
|
||||
#define HZ 100 /* clock frequency */
|
||||
#define MS2HZ (1000/HZ)
|
||||
#define TK2SEC(t) ((t)/HZ) /* ticks to seconds */
|
||||
|
||||
/*
|
||||
* Magic registers
|
||||
*/
|
||||
#define MACH 15 /* R15 is m-> */
|
||||
#define USER 14 /* R14 is up-> */
|
||||
|
||||
|
||||
/*
|
||||
* Fundamental addresses
|
||||
*/
|
||||
/* XXX MACHADDR, MACHP(n) */
|
||||
|
||||
/*
|
||||
* MMU
|
||||
*
|
||||
* A PTE is 64 bits, but a ulong is 32! Hence we encode
|
||||
* the PTEs specially for fault.c, and decode them in putmmu().
|
||||
* This means that we can only map the first 2G of physical
|
||||
* space via putmmu() - ie only physical memory, not devices.
|
||||
*/
|
||||
#define PTEVALID 0x3301
|
||||
#define PTEKVALID 0x1101
|
||||
#define PTEASM 0x0010
|
||||
#define PTEGH(s) ((s)<<5)
|
||||
#define PTEWRITE 0
|
||||
#define PTERONLY 0x4
|
||||
#define PTEUNCACHED 0
|
||||
#define PPN(n) (((n)>>PGSHIFT)<<14)
|
||||
#define FIXPTE(x) ((((uvlong)(x)>>14)<<32)|((x) & 0x3fff))
|
||||
#define PTEPFN(pa) (((uvlong)(pa)>>PGSHIFT)<<32)
|
||||
#define NCOLOR 1
|
||||
#define getpgcolor(a) 0
|
||||
|
||||
#define PTEMAPMEM (1024*1024)
|
||||
#define PTEPERTAB (PTEMAPMEM/BY2PG)
|
||||
#define SEGMAPSIZE 512
|
||||
#define SSEGMAPSIZE 16
|
||||
|
||||
/*
|
||||
* Address spaces
|
||||
*/
|
||||
#define UZERO 0 /* base of user address space */
|
||||
#define UTZERO (UZERO+BY2PG) /* first address in user text */
|
||||
#define KZERO 0x80000000 /* base of kernel address space */
|
||||
#define KTZERO (KZERO+0x400000) /* first address in kernel text */
|
||||
#define USTKTOP KZERO /* byte just beyond user stack */
|
||||
#define USTKSIZE (4*1024*1024) /* size of user stack */
|
||||
|
||||
/*
|
||||
* Processor Status (as returned by rdps)
|
||||
*/
|
||||
#define UMODE 0x8
|
||||
#define IPL 0x7
|
||||
|
||||
|
||||
#define isphys(x) (((ulong)x&KZERO)!=0)
|
|
@ -1,197 +0,0 @@
|
|||
#define QUAD 8
|
||||
#define ALIGN 64
|
||||
#define BLOCK 64
|
||||
|
||||
TEXT memmove(SB), $0
|
||||
MOVL from+4(FP), R7
|
||||
MOVL n+8(FP), R10
|
||||
MOVQ R0, R6
|
||||
|
||||
CMPUGE R7, R0, R5
|
||||
BNE R5, _forward
|
||||
|
||||
MOVQ R6, R8 /* end to address */
|
||||
ADDL R10, R6, R6 /* to+n */
|
||||
ADDL R10, R7, R7 /* from+n */
|
||||
|
||||
CMPUGE $ALIGN, R10, R1 /* need at least ALIGN bytes */
|
||||
BNE R1, _b1tail
|
||||
|
||||
_balign:
|
||||
AND $(ALIGN-1), R6, R1
|
||||
BEQ R1, _baligned
|
||||
|
||||
MOVBU -1(R7), R2
|
||||
ADDL $-1, R6, R6
|
||||
MOVB R2, (R6)
|
||||
ADDL $-1, R7, R7
|
||||
JMP _balign
|
||||
|
||||
_baligned:
|
||||
AND $(QUAD-1), R7, R1 /* is the source quad-aligned */
|
||||
BNE R1, _bunaligned
|
||||
|
||||
ADDL $(BLOCK-1), R8, R9
|
||||
_bblock:
|
||||
CMPUGE R9, R6, R1
|
||||
BNE R1, _b8tail
|
||||
|
||||
MOVQ -64(R7), R22
|
||||
MOVQ -56(R7), R23
|
||||
MOVQ -48(R7), R24
|
||||
MOVQ -40(R7), R25
|
||||
MOVQ -32(R7), R2
|
||||
MOVQ -24(R7), R3
|
||||
MOVQ -16(R7), R4
|
||||
MOVQ -8(R7), R5
|
||||
|
||||
SUBL $64, R6, R6
|
||||
SUBL $64, R7, R7
|
||||
|
||||
MOVQ R22, (R6)
|
||||
MOVQ R23, 8(R6)
|
||||
MOVQ R24, 16(R6)
|
||||
MOVQ R25, 24(R6)
|
||||
MOVQ R2, 32(R6)
|
||||
MOVQ R3, 40(R6)
|
||||
MOVQ R4, 48(R6)
|
||||
MOVQ R5, 56(R6)
|
||||
JMP _bblock
|
||||
|
||||
_b8tail:
|
||||
ADDL $(QUAD-1), R8, R9
|
||||
_b8block:
|
||||
CMPUGE R9, R6, R1
|
||||
BNE R1, _b1tail
|
||||
|
||||
MOVQ -8(R7), R2
|
||||
SUBL $8, R6
|
||||
MOVQ R2, (R6)
|
||||
SUBL $8, R7
|
||||
JMP _b8block
|
||||
|
||||
_b1tail:
|
||||
CMPUGE R8, R6, R1
|
||||
BNE R1, _ret
|
||||
|
||||
MOVBU -1(R7), R2
|
||||
SUBL $1, R6, R6
|
||||
MOVB R2, (R6)
|
||||
SUBL $1, R7, R7
|
||||
JMP _b1tail
|
||||
_ret:
|
||||
RET
|
||||
|
||||
_bunaligned:
|
||||
ADDL $(16-1), R8, R9
|
||||
|
||||
_bu8block:
|
||||
CMPUGE R9, R6, R1
|
||||
BNE R1, _b1tail
|
||||
|
||||
MOVQU -16(R7), R4
|
||||
MOVQU -8(R7), R3
|
||||
MOVQU (R7), R2
|
||||
SUBL $16, R6
|
||||
EXTQH R7, R2, R2
|
||||
EXTQL R7, R3, R5
|
||||
OR R5, R2, R11
|
||||
EXTQH R7, R3, R3
|
||||
EXTQL R7, R4, R4
|
||||
OR R3, R4, R13
|
||||
MOVQ R11, 8(R6)
|
||||
MOVQ R13, (R6)
|
||||
SUBL $16, R7
|
||||
JMP _bu8block
|
||||
|
||||
_forward:
|
||||
ADDL R10, R6, R8 /* end to address */
|
||||
|
||||
CMPUGE $ALIGN, R10, R1 /* need at least ALIGN bytes */
|
||||
BNE R1, _f1tail
|
||||
|
||||
_falign:
|
||||
AND $(ALIGN-1), R6, R1
|
||||
BEQ R1, _faligned
|
||||
|
||||
MOVBU (R7), R2
|
||||
ADDL $1, R6, R6
|
||||
ADDL $1, R7, R7
|
||||
MOVB R2, -1(R6)
|
||||
JMP _falign
|
||||
|
||||
_faligned:
|
||||
AND $(QUAD-1), R7, R1 /* is the source quad-aligned */
|
||||
BNE R1, _funaligned
|
||||
|
||||
SUBL $(BLOCK-1), R8, R9
|
||||
_fblock:
|
||||
CMPUGT R9, R6, R1
|
||||
BEQ R1, _f8tail
|
||||
|
||||
MOVQ (R7), R2
|
||||
MOVQ 8(R7), R3
|
||||
MOVQ 16(R7), R4
|
||||
MOVQ 24(R7), R5
|
||||
MOVQ 32(R7), R22
|
||||
MOVQ 40(R7), R23
|
||||
MOVQ 48(R7), R24
|
||||
MOVQ 56(R7), R25
|
||||
|
||||
ADDL $64, R6, R6
|
||||
ADDL $64, R7, R7
|
||||
|
||||
MOVQ R2, -64(R6)
|
||||
MOVQ R3, -56(R6)
|
||||
MOVQ R4, -48(R6)
|
||||
MOVQ R5, -40(R6)
|
||||
MOVQ R22, -32(R6)
|
||||
MOVQ R23, -24(R6)
|
||||
MOVQ R24, -16(R6)
|
||||
MOVQ R25, -8(R6)
|
||||
JMP _fblock
|
||||
|
||||
_f8tail:
|
||||
SUBL $(QUAD-1), R8, R9
|
||||
_f8block:
|
||||
CMPUGT R9, R6, R1
|
||||
BEQ R1, _f1tail
|
||||
|
||||
MOVQ (R7), R2
|
||||
ADDL $8, R6
|
||||
ADDL $8, R7
|
||||
MOVQ R2, -8(R6)
|
||||
JMP _f8block
|
||||
|
||||
_f1tail:
|
||||
CMPUGT R8, R6, R1
|
||||
BEQ R1, _fret
|
||||
MOVBU (R7), R2
|
||||
ADDL $1, R6, R6
|
||||
ADDL $1, R7, R7
|
||||
MOVB R2, -1(R6)
|
||||
JMP _f1tail
|
||||
|
||||
_fret:
|
||||
RET
|
||||
|
||||
_funaligned:
|
||||
SUBL $(16-1), R8, R9
|
||||
_fu8block:
|
||||
CMPUGT R9, R6, R1
|
||||
BEQ R1, _f1tail
|
||||
|
||||
MOVQU (R7), R2
|
||||
MOVQU 8(R7), R3
|
||||
MOVQU 16(R7), R4
|
||||
EXTQL R7, R2, R2
|
||||
EXTQH R7, R3, R5
|
||||
OR R5, R2, R11
|
||||
EXTQL R7, R3, R3
|
||||
MOVQ R11, (R6)
|
||||
EXTQH R7, R4, R4
|
||||
OR R3, R4, R11
|
||||
MOVQ R11, 8(R6)
|
||||
ADDL $16, R6
|
||||
ADDL $16, R7
|
||||
JMP _fu8block
|
|
@ -1,61 +0,0 @@
|
|||
TEXT memset(SB), $0
|
||||
MOVL R0, R6
|
||||
MOVBU data+4(FP), R2
|
||||
MOVL n+8(FP), R10
|
||||
|
||||
ADDL R10, R0, R8
|
||||
|
||||
CMPUGE $8, R10, R1 /* need at least 8 bytes */
|
||||
BNE R1, _1loop
|
||||
|
||||
SLLQ $8, R2, R1 /* replicate the byte */
|
||||
OR R1, R2
|
||||
SLLQ $16, R2, R1
|
||||
OR R1, R2
|
||||
SLLQ $32, R2, R1
|
||||
OR R1, R2
|
||||
|
||||
_align:
|
||||
AND $(8-1), R6, R1
|
||||
BEQ R1, _aligned
|
||||
|
||||
MOVB R2, (R6)
|
||||
ADDL $1, R6, R6
|
||||
JMP _align
|
||||
|
||||
_aligned:
|
||||
SUBL $(64-1), R8, R9 /* end pointer minus slop */
|
||||
_64loop:
|
||||
CMPUGT R9, R6, R1
|
||||
BEQ R1, _8tail
|
||||
|
||||
MOVQ R2, (R6)
|
||||
MOVQ R2, 8(R6)
|
||||
MOVQ R2, 16(R6)
|
||||
MOVQ R2, 24(R6)
|
||||
MOVQ R2, 32(R6)
|
||||
MOVQ R2, 40(R6)
|
||||
MOVQ R2, 48(R6)
|
||||
MOVQ R2, 56(R6)
|
||||
ADDL $64, R6, R6
|
||||
JMP _64loop
|
||||
|
||||
_8tail:
|
||||
SUBL $(8-1), R8, R9
|
||||
_8loop:
|
||||
CMPUGT R9, R6, R1
|
||||
BEQ R1, _1loop
|
||||
|
||||
MOVQ R2, (R6)
|
||||
ADDL $8, R6
|
||||
JMP _8loop
|
||||
|
||||
_1loop:
|
||||
CMPUGT R8, R6, R1
|
||||
BEQ R1, _ret
|
||||
MOVB R2, (R6)
|
||||
ADDL $1, R6
|
||||
JMP _1loop
|
||||
|
||||
_ret:
|
||||
RET
|
|
@ -1,106 +0,0 @@
|
|||
CONF=apc
|
||||
CONFLIST=apc apccpu
|
||||
|
||||
objtype=alpha
|
||||
</$objtype/mkfile
|
||||
p=9
|
||||
|
||||
DEVS=`{rc ../port/mkdevlist $CONF}
|
||||
|
||||
PORT=\
|
||||
alarm.$O\
|
||||
alloc.$O\
|
||||
allocb.$O\
|
||||
auth.$O\
|
||||
cache.$O\
|
||||
chan.$O\
|
||||
dev.$O\
|
||||
fault.$O\
|
||||
log.$O\
|
||||
edf.$O\
|
||||
mul64fract.$O\
|
||||
page.$O\
|
||||
parse.$O\
|
||||
pgrp.$O\
|
||||
portclock.$O\
|
||||
print.$O\
|
||||
proc.$O\
|
||||
qio.$O\
|
||||
qlock.$O\
|
||||
rdb.$O\
|
||||
rebootcmd.$O\
|
||||
segment.$O\
|
||||
swap.$O\
|
||||
sysfile.$O\
|
||||
sysproc.$O\
|
||||
taslock.$O\
|
||||
tod.$O\
|
||||
xalloc.$O\
|
||||
random.$O\
|
||||
|
||||
OBJ=\
|
||||
l.$O\
|
||||
cga.$O\
|
||||
clock.$O\
|
||||
faultalpha.$O\
|
||||
fdc37c93x.$O\
|
||||
fptrap.$O\
|
||||
i8259.$O\
|
||||
main.$O\
|
||||
mmu.$O\
|
||||
trap.$O\
|
||||
$CONF.root.$O\
|
||||
$CONF.rootc.$O\
|
||||
$DEVS\
|
||||
$PORT\
|
||||
|
||||
LIB=\
|
||||
/$objtype/lib/libmemlayer.a\
|
||||
/$objtype/lib/libmemdraw.a\
|
||||
/$objtype/lib/libdraw.a\
|
||||
/$objtype/lib/libip.a\
|
||||
/$objtype/lib/libc.a\
|
||||
/$objtype/lib/libsec.a\
|
||||
|
||||
ETHER=`{echo devether.c ether*.c | sed 's/\.c/.'$O'/g'}
|
||||
VGA=`{echo devvga.c screen.c vga*.c | sed 's/\.c/.'$O'/g'}
|
||||
SDEV=`{echo devsd.c sd*.c | sed 's/\.c/.'$O'/g'}
|
||||
|
||||
loadaddr = 0x80400020
|
||||
|
||||
$p$CONF: $CONF.c $OBJ $LIB
|
||||
$CC $CFLAGS '-DKERNDATE='`{date -n} $CONF.c
|
||||
$LD -o $target -H3 -R8 -T$loadaddr -l $OBJ $CONF.$O $LIB
|
||||
size $target
|
||||
|
||||
install:V: $p$CONF
|
||||
cp $p$CONF /$objtype/$p$CONF
|
||||
|
||||
<../boot/bootmkfile
|
||||
<../port/portmkfile
|
||||
<|../port/mkbootrules $CONF
|
||||
<../pc/pcmkfile
|
||||
|
||||
init.h: initcode /sys/src/libc/9syscall/sys.h
|
||||
$AS initcode
|
||||
$LD -l -s -R8 -o init.out initcode.$O -lc
|
||||
{echo 'uchar initcode[]={'
|
||||
xd -r -1x init.out |
|
||||
sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
|
||||
echo '};'} > init.h
|
||||
|
||||
clock.$O: /$objtype/include/ureg.h axp.h
|
||||
devarch.$O: axp.h
|
||||
faultalpha.$O: /$objtype/include/ureg.h
|
||||
fptrap.$O: /$objtype/include/ureg.h
|
||||
l.$O: osf1pal.h
|
||||
main.$O: /$objtype/include/ureg.h errstr.h init.h
|
||||
mmu.$O: /sys/src/boot/alphapc/conf.h
|
||||
sd53c8xx.$O: /$objtype/include/ureg.h ../port/sd.h sd53c8xx.i
|
||||
trap.$O: /$objtype/include/ureg.h ../port/error.h ../port/systab.h
|
||||
|
||||
sd53c8xx.i: ../pc/sd53c8xx.n
|
||||
aux/na $prereq > $target
|
||||
|
||||
acid:V:
|
||||
$CC -a -w -I. ../port/qio.c>acid
|
|
@ -1,299 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "/sys/src/boot/alphapc/conf.h"
|
||||
|
||||
static uvlong origlvl1; /* physical address */
|
||||
static uvlong klvl2; /* physical, as created by boot loader */
|
||||
static uchar *nextio; /* next virtual address to be allocated by kmapv */
|
||||
extern Bootconf *bootconf;
|
||||
|
||||
#define LVL2OFF(v) ((((long)(v))>>(2*PGSHIFT-3))&(PTE2PG-1))
|
||||
#define LVL3OFF(v) ((((long)(v))>>(PGSHIFT))&(PTE2PG-1))
|
||||
|
||||
static void
|
||||
setptb(ulong pa)
|
||||
{
|
||||
m->ptbr = (uvlong)pa>>PGSHIFT;
|
||||
swpctx(m);
|
||||
}
|
||||
|
||||
void
|
||||
mmuinit(void)
|
||||
{
|
||||
uvlong *plvl2;
|
||||
|
||||
/* set PCB to new one in mach structure before stomping on old one */
|
||||
m->usp = 0;
|
||||
m->fen = 1;
|
||||
m->ptbr = bootconf->pcb->ptbr;
|
||||
origlvl1 = (m->ptbr << PGSHIFT);
|
||||
setpcb(m);
|
||||
|
||||
plvl2 = (uvlong*) (KZERO|origlvl1|(BY2PG-8));
|
||||
klvl2 = (*plvl2 >> 32)<<PGSHIFT;
|
||||
|
||||
nextio = (uchar*) (KZERO|bootconf->maxphys);
|
||||
}
|
||||
|
||||
static void
|
||||
mmuptefree(Proc* proc)
|
||||
{
|
||||
uvlong *lvl2;
|
||||
Page **last, *page;
|
||||
|
||||
if(proc->mmutop && proc->mmuused){
|
||||
lvl2 = (uvlong*)proc->mmulvl2->va;
|
||||
last = &proc->mmuused;
|
||||
for(page = *last; page; page = page->next){
|
||||
lvl2[page->daddr] = 0;
|
||||
last = &page->next;
|
||||
}
|
||||
*last = proc->mmufree;
|
||||
proc->mmufree = proc->mmuused;
|
||||
proc->mmuused = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mmuswitch(Proc *proc)
|
||||
{
|
||||
if(proc->newtlb){
|
||||
mmuptefree(proc);
|
||||
proc->newtlb = 0;
|
||||
}
|
||||
|
||||
/* tell processor about new page table and flush cached entries */
|
||||
if(proc->mmutop == 0)
|
||||
setptb(origlvl1);
|
||||
else
|
||||
setptb(proc->mmutop->pa);
|
||||
tlbflush(-1, 0);
|
||||
icflush();
|
||||
}
|
||||
|
||||
/* point to protoype page map */
|
||||
void
|
||||
mmupark(void)
|
||||
{
|
||||
setptb(origlvl1);
|
||||
icflush();
|
||||
}
|
||||
|
||||
/*
|
||||
* give all page table pages back to the free pool. This is called in sched()
|
||||
* with palloc locked.
|
||||
*/
|
||||
void
|
||||
mmurelease(Proc *proc)
|
||||
{
|
||||
Page *page, *next;
|
||||
|
||||
mmupark();
|
||||
mmuptefree(proc);
|
||||
proc->mmuused = 0;
|
||||
if(proc->mmutop) {
|
||||
proc->mmutop->next = proc->mmufree;
|
||||
proc->mmufree = proc->mmutop;
|
||||
proc->mmutop = 0;
|
||||
}
|
||||
if(proc->mmulvl2) {
|
||||
proc->mmulvl2->next = proc->mmufree;
|
||||
proc->mmufree = proc->mmulvl2;
|
||||
proc->mmulvl2 = 0;
|
||||
}
|
||||
for(page = proc->mmufree; page; page = next){
|
||||
next = page->next;
|
||||
if(--page->ref)
|
||||
panic("mmurelease: page->ref %d\n", page->ref);
|
||||
pagechainhead(page);
|
||||
}
|
||||
if(proc->mmufree)
|
||||
pagechaindone();
|
||||
proc->mmufree = 0;
|
||||
}
|
||||
|
||||
void
|
||||
mmunewtop(void)
|
||||
{
|
||||
Page *top, *lvl2;
|
||||
uvlong *ppte;
|
||||
|
||||
top = newpage(1, 0, 0);
|
||||
top->va = VA(kmap(top));
|
||||
lvl2 = newpage(1, 0, 0);
|
||||
lvl2->va = VA(kmap(lvl2));
|
||||
|
||||
ppte = (uvlong *)top->va;
|
||||
ppte[0] = PTEPFN(lvl2->pa) | PTEKVALID;
|
||||
ppte[PTE2PG-2] = PTEPFN(top->pa) | PTEKVALID;
|
||||
ppte[PTE2PG-1] = PTEPFN(klvl2) | PTEKVALID;
|
||||
|
||||
up->mmutop = top;
|
||||
up->mmulvl2 = lvl2;
|
||||
setptb(top->pa);
|
||||
tlbflush(-1, 0);
|
||||
icflush();
|
||||
}
|
||||
|
||||
void
|
||||
putmmu(uintptr va, uintptr pa, Page *pg)
|
||||
{
|
||||
int lvl2off;
|
||||
uvlong *lvl2, *pt;
|
||||
int s;
|
||||
|
||||
if(up->mmutop == 0)
|
||||
mmunewtop();
|
||||
|
||||
lvl2 = (uvlong*)up->mmulvl2->va;
|
||||
lvl2off = LVL2OFF(va);
|
||||
|
||||
/*
|
||||
* if bottom level page table missing, allocate one
|
||||
* and point the top level page at it.
|
||||
*/
|
||||
s = splhi();
|
||||
if(lvl2[lvl2off] == 0){
|
||||
if(up->mmufree == 0){
|
||||
spllo();
|
||||
pg = newpage(1, 0, 0);
|
||||
pg->va = VA(kmap(pg));
|
||||
splhi();
|
||||
} else {
|
||||
pg = up->mmufree;
|
||||
up->mmufree = pg->next;
|
||||
memset((void*)pg->va, 0, BY2PG);
|
||||
}
|
||||
lvl2[lvl2off] = PTEPFN(pg->pa) | PTEVALID;
|
||||
pg->daddr = lvl2off;
|
||||
pg->next = up->mmuused;
|
||||
up->mmuused = pg;
|
||||
}
|
||||
|
||||
/*
|
||||
* put in new mmu entry
|
||||
*/
|
||||
pt = (uvlong*)(((lvl2[lvl2off] >> 32)<<PGSHIFT)|KZERO);
|
||||
pt[LVL3OFF(va)] = FIXPTE(pa);
|
||||
|
||||
/* flush cached mmu entries */
|
||||
tlbflush(3, va);
|
||||
icflush();
|
||||
splx(s);
|
||||
}
|
||||
|
||||
void *
|
||||
kmapv(uvlong pa, int size)
|
||||
{
|
||||
void *va, *new;
|
||||
int lvl2off, i, npage, offset;
|
||||
uvlong *lvl2, *pt;
|
||||
|
||||
offset = pa&(BY2PG-1);
|
||||
npage = ((size+offset+BY2PG-1)>>PGSHIFT);
|
||||
|
||||
va = nextio+offset;
|
||||
lvl2 = (uvlong*)(KZERO|klvl2);
|
||||
for (i = 0; i < npage; i++) {
|
||||
lvl2off = LVL2OFF(nextio);
|
||||
if (lvl2[lvl2off] == 0) {
|
||||
new = xspanalloc(BY2PG, BY2PG, 0);
|
||||
memset(new, 0, BY2PG);
|
||||
lvl2[lvl2off] = PTEPFN(PADDR(new)) | PTEKVALID | PTEASM;
|
||||
}
|
||||
pt = (uvlong*)(((lvl2[lvl2off] >> 32)<<PGSHIFT)|KZERO);
|
||||
pt[LVL3OFF(nextio)] = PTEPFN(pa) | PTEKVALID | PTEASM;
|
||||
nextio += BY2PG;
|
||||
pa += BY2PG;
|
||||
}
|
||||
return va;
|
||||
}
|
||||
|
||||
void
|
||||
flushmmu(void)
|
||||
{
|
||||
int s;
|
||||
|
||||
s = splhi();
|
||||
up->newtlb = 1;
|
||||
mmuswitch(up);
|
||||
splx(s);
|
||||
|
||||
}
|
||||
|
||||
void*
|
||||
vmap(ulong pa, int size)
|
||||
{
|
||||
void *va;
|
||||
|
||||
/*
|
||||
* Viability hack. Only for PCI framebuffers.
|
||||
*/
|
||||
if(pa == 0)
|
||||
return 0;
|
||||
va = kmapv(((uvlong)0x88<<32LL)|pa, size);
|
||||
if(va == nil)
|
||||
return 0;
|
||||
return (void*)va;
|
||||
}
|
||||
|
||||
void
|
||||
vunmap(void*, int)
|
||||
{
|
||||
print("vunmap: virtual mapping not freed\n");
|
||||
}
|
||||
|
||||
void
|
||||
mmudump(void)
|
||||
{
|
||||
Page *top, *lvl2;
|
||||
|
||||
iprint("ptbr %lux up %#p\n", (ulong)m->ptbr, up);
|
||||
if(up) {
|
||||
top = up->mmutop;
|
||||
if(top != nil)
|
||||
iprint("top %lux top[N-1] %llux\n", top->va, ((uvlong *)top->va)[PTE2PG-1]);
|
||||
lvl2 = up->mmulvl2;
|
||||
if(lvl2 != nil)
|
||||
iprint("lvl2 %lux\n", lvl2->va);
|
||||
}
|
||||
}
|
||||
|
||||
ulong
|
||||
upaalloc(int, int)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
upafree(ulong, int)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
checkmmu(uintptr, uintptr)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
countpagerefs(ulong*, int)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the number of bytes that can be accessed via KADDR(pa).
|
||||
* If pa is not a valid argument to KADDR, return 0.
|
||||
*/
|
||||
ulong
|
||||
cankaddr(ulong pa)
|
||||
{
|
||||
ulong kzero;
|
||||
|
||||
kzero = -KZERO;
|
||||
if(pa >= kzero)
|
||||
return 0;
|
||||
return kzero - pa;
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
/*
|
||||
* OSF/1 PALcode instructions, in numerical order.
|
||||
* Values are from Digital EBSDK and FreeBSD/Alpha.
|
||||
*/
|
||||
|
||||
/* Privilaged PAL functions */
|
||||
#define PALhalt 0x00 /* required per Alpha architecture */
|
||||
#define PALcflush 0x01
|
||||
#define PALdraina 0x02 /* required per Alpha architecture */
|
||||
/*
|
||||
* ... 0x03 to 0x08 ?
|
||||
*/
|
||||
#define PALcserve 0x09
|
||||
#define PALswppal 0x0a
|
||||
/*
|
||||
* ... 0x0b to 0x0c ?
|
||||
*/
|
||||
#define PALwripir 0x0d
|
||||
/*
|
||||
* ... 0x0e to 0x0f ?
|
||||
*/
|
||||
#define PALrdmces 0x10
|
||||
#define PALwrmces 0x11
|
||||
/*
|
||||
* ... 0x12 to 0x2a ?
|
||||
*/
|
||||
#define PALwrfen 0x2b
|
||||
/* 0x2c OSF/1 ? */
|
||||
#define PALwrvptptr 0x2d
|
||||
/*
|
||||
* ... 0x2e to 0x2f ?
|
||||
*/
|
||||
#define PALswpctx 0x30
|
||||
#define PALwrval 0x31
|
||||
#define PALrdval 0x32
|
||||
#define PALtbi 0x33
|
||||
#define PALwrent 0x34
|
||||
#define PALswpipl 0x35
|
||||
#define PALrdps 0x36
|
||||
#define PALwrkgp 0x37
|
||||
#define PALwrusp 0x38
|
||||
#define PALwrperfmon 0x39
|
||||
#define PALrdusp 0x3a
|
||||
/* 0x3b OSF/1 ? */
|
||||
#define PALwhami 0x3c
|
||||
#define PALretsys 0x3d
|
||||
#define PALwtint 0x3e
|
||||
#define PALrti 0x3f
|
||||
|
||||
/* Unprivileged PAL functions */
|
||||
#define PALbpt 0x80
|
||||
#define PALbugchk 0x81
|
||||
#define PALcallsys 0x83
|
||||
#define PALimb 0x86 /* required per Alpha architecture */
|
||||
/*
|
||||
* ... 0x89 to 0x91 ?
|
||||
*/
|
||||
#define PALurti 0x92
|
||||
/*
|
||||
* ... 0x93 to 0x9d ?
|
||||
*/
|
||||
#define PALrdunique 0x9e
|
||||
#define PALwrunique 0x9f
|
||||
/*
|
||||
* ... 0xa0 to 0xa9 ?
|
||||
*/
|
||||
#define PALgentrap 0xaa
|
||||
/*
|
||||
* ... 0xab to 0xac ?
|
||||
*/
|
||||
#define PALdbgstop 0xad
|
||||
#define PALclrfen 0xae
|
||||
/*
|
||||
* ... 0xaf to 0xbd ?
|
||||
*/
|
||||
#define PALnphalt 0xbe
|
||||
#define PALcopypal 0xbf
|
||||
|
|
@ -1,412 +0,0 @@
|
|||
/*
|
||||
* PCI support code.
|
||||
* To do:
|
||||
* initialise bridge mappings if the PCI BIOS didn't.
|
||||
*/
|
||||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
#include "../port/error.h"
|
||||
|
||||
enum {
|
||||
MaxFNO = 7,
|
||||
MaxUBN = 255,
|
||||
};
|
||||
|
||||
enum
|
||||
{ /* command register */
|
||||
IOen = (1<<0),
|
||||
MEMen = (1<<1),
|
||||
MASen = (1<<2),
|
||||
MemWrInv = (1<<4),
|
||||
PErrEn = (1<<6),
|
||||
SErrEn = (1<<8),
|
||||
};
|
||||
|
||||
static Lock pcicfglock;
|
||||
static Lock pcicfginitlock;
|
||||
static int pcicfgmode = -1;
|
||||
static int pcimaxdno;
|
||||
static Pcidev* pciroot;
|
||||
static Pcidev* pcilist;
|
||||
static Pcidev* pcitail;
|
||||
|
||||
static int pcicfgrw32(int, int, int, int);
|
||||
|
||||
uchar *vgabios;
|
||||
|
||||
static int
|
||||
pciscan(int bno, Pcidev** list)
|
||||
{
|
||||
ulong v;
|
||||
Pcidev *p, *head, *tail;
|
||||
int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
|
||||
|
||||
maxubn = bno;
|
||||
head = nil;
|
||||
tail = nil;
|
||||
for(dno = 0; dno <= pcimaxdno; dno++){
|
||||
maxfno = 0;
|
||||
for(fno = 0; fno <= maxfno; fno++){
|
||||
/*
|
||||
* For this possible device, form the
|
||||
* bus+device+function triplet needed to address it
|
||||
* and try to read the vendor and device ID.
|
||||
* If successful, allocate a device struct and
|
||||
* start to fill it in with some useful information
|
||||
* from the device's configuration space.
|
||||
*/
|
||||
tbdf = MKBUS(BusPCI, bno, dno, fno);
|
||||
l = pcicfgrw32(tbdf, PciVID, 0, 1);
|
||||
if(l == 0xFFFFFFFF || l == 0)
|
||||
continue;
|
||||
/* optional safety checks:
|
||||
if(l == pcicfgrw32(tbdf, PciPCR, 0, 1))
|
||||
continue;
|
||||
if(l != pcicfgrw32(tbdf, PciVID, 0, 1))
|
||||
continue;
|
||||
if(l == pcicfgrw32(tbdf, PciPCR, 0, 1))
|
||||
continue;
|
||||
*/
|
||||
p = malloc(sizeof(*p));
|
||||
p->tbdf = tbdf;
|
||||
p->vid = l;
|
||||
p->did = l>>16;
|
||||
|
||||
if(pcilist != nil)
|
||||
pcitail->list = p;
|
||||
else
|
||||
pcilist = p;
|
||||
pcitail = p;
|
||||
|
||||
p->rid = pcicfgr8(p, PciRID);
|
||||
p->ccrp = pcicfgr8(p, PciCCRp);
|
||||
p->ccru = pcicfgr8(p, PciCCRu);
|
||||
p->ccrb = pcicfgr8(p, PciCCRb);
|
||||
p->pcr = pcicfgr32(p, PciPCR);
|
||||
|
||||
p->intl = pcicfgr8(p, PciINTL);
|
||||
|
||||
/*
|
||||
* If the device is a multi-function device adjust the
|
||||
* loop count so all possible functions are checked.
|
||||
*/
|
||||
hdt = pcicfgr8(p, PciHDT);
|
||||
if(hdt & 0x80)
|
||||
maxfno = MaxFNO;
|
||||
|
||||
/*
|
||||
* If appropriate, read the base address registers
|
||||
* and work out the sizes.
|
||||
*/
|
||||
switch(p->ccrb){
|
||||
|
||||
case 0x03: /* display controller */
|
||||
if(vgabios == nil) {
|
||||
v = pcicfgr32(p, PciROM);
|
||||
pcicfgw32(p, PciROM, v|1); /* enable decode */
|
||||
vgabios = kmapv(((uvlong)0x88<<32LL)|(v&~0xffff), 0x10000);
|
||||
// print("VGA BIOS %lux -> %lux\n", v, vgabios);
|
||||
}
|
||||
/* fall through */
|
||||
case 0x01: /* mass storage controller */
|
||||
case 0x02: /* network controller */
|
||||
case 0x04: /* multimedia device */
|
||||
case 0x07: /* simple communication controllers */
|
||||
case 0x08: /* base system peripherals */
|
||||
case 0x09: /* input devices */
|
||||
case 0x0A: /* docking stations */
|
||||
case 0x0B: /* processors */
|
||||
case 0x0C: /* serial bus controllers */
|
||||
if((hdt & 0x7F) != 0)
|
||||
break;
|
||||
rno = PciBAR0 - 4;
|
||||
for(i = 0; i < nelem(p->mem); i++){
|
||||
rno += 4;
|
||||
p->mem[i].bar = pcicfgr32(p, rno);
|
||||
pcicfgw32(p, rno, -1);
|
||||
v = pcicfgr32(p, rno);
|
||||
pcicfgw32(p, rno, p->mem[i].bar);
|
||||
p->mem[i].size = -(v & ~0xF);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x00:
|
||||
case 0x05: /* memory controller */
|
||||
case 0x06: /* bridge device */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(head != nil)
|
||||
tail->link = p;
|
||||
else
|
||||
head = p;
|
||||
tail = p;
|
||||
}
|
||||
}
|
||||
|
||||
*list = head;
|
||||
for(p = head; p != nil; p = p->link){
|
||||
/*
|
||||
* Find PCI-PCI bridges and recursively descend the tree.
|
||||
*/
|
||||
if(p->ccrb != 0x06 || p->ccru != 0x04)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* If the secondary or subordinate bus number is not initialised
|
||||
* try to do what the PCI BIOS should have done and fill in the
|
||||
* numbers as the tree is descended. On the way down the subordinate
|
||||
* bus number is set to the maximum as it's not known how many
|
||||
* buses are behind this one; the final value is set on the way
|
||||
* back up.
|
||||
*/
|
||||
sbn = pcicfgr8(p, PciSBN);
|
||||
ubn = pcicfgr8(p, PciUBN);
|
||||
if(sbn == 0 || ubn == 0){
|
||||
sbn = maxubn+1;
|
||||
/*
|
||||
* Make sure memory, I/O and master enables are off,
|
||||
* set the primary, secondary and subordinate bus numbers
|
||||
* and clear the secondary status before attempting to
|
||||
* scan the secondary bus.
|
||||
*
|
||||
* Initialisation of the bridge should be done here.
|
||||
*/
|
||||
pcicfgw32(p, PciPCR, 0xFFFF0000);
|
||||
l = (MaxUBN<<16)|(sbn<<8)|bno;
|
||||
pcicfgw32(p, PciPBN, l);
|
||||
pcicfgw16(p, PciSPSR, 0xFFFF);
|
||||
maxubn = pciscan(sbn, &p->bridge);
|
||||
l = (maxubn<<16)|(sbn<<8)|bno;
|
||||
pcicfgw32(p, PciPBN, l);
|
||||
}
|
||||
else{
|
||||
maxubn = ubn;
|
||||
pciscan(sbn, &p->bridge);
|
||||
}
|
||||
}
|
||||
|
||||
return maxubn;
|
||||
}
|
||||
|
||||
static void
|
||||
pcicfginit(void)
|
||||
{
|
||||
char *p;
|
||||
|
||||
lock(&pcicfginitlock);
|
||||
if(pcicfgmode == -1){
|
||||
pcicfgmode = 0;
|
||||
pcimaxdno = 15; /* was 20; what is correct value??? */
|
||||
if(p = getconf("*pcimaxdno"))
|
||||
pcimaxdno = strtoul(p, 0, 0);
|
||||
pciscan(0, &pciroot);
|
||||
}
|
||||
unlock(&pcicfginitlock);
|
||||
}
|
||||
|
||||
static int
|
||||
pcicfgrw8(int tbdf, int rno, int data, int read)
|
||||
{
|
||||
int x;
|
||||
uchar *p;
|
||||
|
||||
if(pcicfgmode == -1)
|
||||
pcicfginit();
|
||||
x = -1;
|
||||
if(BUSDNO(tbdf) > pcimaxdno)
|
||||
return x;
|
||||
|
||||
p = (uchar*)arch->pcicfg(tbdf, rno);
|
||||
if(read)
|
||||
x = *p;
|
||||
else
|
||||
*p = data;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
pcicfgr8(Pcidev* pcidev, int rno)
|
||||
{
|
||||
return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
|
||||
}
|
||||
|
||||
void
|
||||
pcicfgw8(Pcidev* pcidev, int rno, int data)
|
||||
{
|
||||
pcicfgrw8(pcidev->tbdf, rno, data, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
pcicfgrw16(int tbdf, int rno, int data, int read)
|
||||
{
|
||||
int x;
|
||||
ushort *p;
|
||||
|
||||
if(pcicfgmode == -1)
|
||||
pcicfginit();
|
||||
x = -1;
|
||||
if(BUSDNO(tbdf) > pcimaxdno)
|
||||
return x;
|
||||
|
||||
p = (ushort*)arch->pcicfg(tbdf, rno);
|
||||
if(read)
|
||||
x = *p;
|
||||
else
|
||||
*p = data;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
pcicfgr16(Pcidev* pcidev, int rno)
|
||||
{
|
||||
return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
|
||||
}
|
||||
|
||||
void
|
||||
pcicfgw16(Pcidev* pcidev, int rno, int data)
|
||||
{
|
||||
pcicfgrw16(pcidev->tbdf, rno, data, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
pcicfgrw32(int tbdf, int rno, int data, int read)
|
||||
{
|
||||
int x;
|
||||
ulong *p;
|
||||
|
||||
if(pcicfgmode == -1)
|
||||
pcicfginit();
|
||||
x = -1;
|
||||
if(BUSDNO(tbdf) > pcimaxdno)
|
||||
return x;
|
||||
|
||||
p = (ulong*)arch->pcicfg(tbdf, rno);
|
||||
if(read)
|
||||
x = *p;
|
||||
else
|
||||
*p = data;
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
int
|
||||
pcicfgr32(Pcidev* pcidev, int rno)
|
||||
{
|
||||
return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
|
||||
}
|
||||
|
||||
void
|
||||
pcicfgw32(Pcidev* pcidev, int rno, int data)
|
||||
{
|
||||
pcicfgrw32(pcidev->tbdf, rno, data, 0);
|
||||
}
|
||||
|
||||
Pcidev*
|
||||
pcimatch(Pcidev* prev, int vid, int did)
|
||||
{
|
||||
if(pcicfgmode == -1)
|
||||
pcicfginit();
|
||||
|
||||
if(prev == nil)
|
||||
prev = pcilist;
|
||||
else
|
||||
prev = prev->list;
|
||||
|
||||
while(prev != nil) {
|
||||
if((vid == 0 || prev->vid == vid)
|
||||
&& (did == 0 || prev->did == did))
|
||||
break;
|
||||
prev = prev->list;
|
||||
}
|
||||
return prev;
|
||||
}
|
||||
|
||||
Pcidev*
|
||||
pcimatchtbdf(int tbdf)
|
||||
{
|
||||
Pcidev *pcidev;
|
||||
|
||||
if(pcicfgmode == -1)
|
||||
pcicfginit();
|
||||
|
||||
for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) {
|
||||
if(pcidev->tbdf == tbdf)
|
||||
break;
|
||||
}
|
||||
return pcidev;
|
||||
}
|
||||
|
||||
void
|
||||
pcihinv(Pcidev* p)
|
||||
{
|
||||
int i;
|
||||
Pcidev *t;
|
||||
|
||||
if(pcicfgmode == -1)
|
||||
pcicfginit();
|
||||
if(p == nil) {
|
||||
p = pciroot;
|
||||
print("bus dev type vid did intl memory\n");
|
||||
}
|
||||
for(t = p; t != nil; t = t->link) {
|
||||
print("%d %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %2d ",
|
||||
BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
|
||||
t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);
|
||||
|
||||
for(i = 0; i < nelem(p->mem); i++) {
|
||||
if(t->mem[i].size == 0)
|
||||
continue;
|
||||
print("%d:%.8lux %d ", i,
|
||||
t->mem[i].bar, t->mem[i].size);
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
while(p != nil) {
|
||||
if(p->bridge != nil)
|
||||
pcihinv(p->bridge);
|
||||
p = p->link;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pcireset(void)
|
||||
{
|
||||
Pcidev *p;
|
||||
int pcr;
|
||||
|
||||
if(pcicfgmode == -1)
|
||||
pcicfginit();
|
||||
|
||||
for(p = pcilist; p != nil; p = p->list){
|
||||
pcr = pcicfgr16(p, PciPSR);
|
||||
pcicfgw16(p, PciPSR, pcr & ~0x04);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
pcisetbme(Pcidev* p)
|
||||
{
|
||||
int pcr;
|
||||
|
||||
pcr = pcicfgr16(p, PciPCR);
|
||||
pcr |= MASen;
|
||||
pcicfgw16(p, PciPCR, pcr);
|
||||
}
|
||||
|
||||
void
|
||||
pciclrbme(Pcidev* p)
|
||||
{
|
||||
int pcr;
|
||||
|
||||
pcr = pcicfgr16(p, PciPCR);
|
||||
pcr &= ~MASen;
|
||||
pcicfgw16(p, PciPCR, pcr);
|
||||
}
|
|
@ -1,172 +0,0 @@
|
|||
typedef struct Cursor Cursor;
|
||||
typedef struct Cursorinfo Cursorinfo;
|
||||
struct Cursorinfo {
|
||||
Cursor;
|
||||
Lock;
|
||||
};
|
||||
|
||||
/* devmouse.c */
|
||||
extern void mousetrack(int, int, int, int);
|
||||
extern void absmousetrack(int, int, int, int);
|
||||
extern Point mousexy(void);
|
||||
|
||||
extern void mouseaccelerate(int);
|
||||
extern int m3mouseputc(Queue*, int);
|
||||
extern int m5mouseputc(Queue*, int);
|
||||
extern int mouseputc(Queue*, int);
|
||||
|
||||
extern Cursorinfo cursor;
|
||||
extern Cursor arrow;
|
||||
|
||||
/*
|
||||
* Generic VGA registers.
|
||||
*/
|
||||
enum {
|
||||
MiscW = 0x03C2, /* Miscellaneous Output (W) */
|
||||
MiscR = 0x03CC, /* Miscellaneous Output (R) */
|
||||
Status0 = 0x03C2, /* Input status 0 (R) */
|
||||
Status1 = 0x03DA, /* Input Status 1 (R) */
|
||||
FeatureR = 0x03CA, /* Feature Control (R) */
|
||||
FeatureW = 0x03DA, /* Feature Control (W) */
|
||||
|
||||
Seqx = 0x03C4, /* Sequencer Index, Data at Seqx+1 */
|
||||
Crtx = 0x03D4, /* CRT Controller Index, Data at Crtx+1 */
|
||||
Grx = 0x03CE, /* Graphics Controller Index, Data at Grx+1 */
|
||||
Attrx = 0x03C0, /* Attribute Controller Index and Data */
|
||||
|
||||
PaddrW = 0x03C8, /* Palette Address Register, write */
|
||||
Pdata = 0x03C9, /* Palette Data Register */
|
||||
Pixmask = 0x03C6, /* Pixel Mask Register */
|
||||
PaddrR = 0x03C7, /* Palette Address Register, read */
|
||||
Pstatus = 0x03C7, /* DAC Status (RO) */
|
||||
|
||||
Pcolours = 256, /* Palette */
|
||||
Pred = 0,
|
||||
Pgreen = 1,
|
||||
Pblue = 2,
|
||||
|
||||
Pblack = 0x00,
|
||||
Pwhite = 0xFF,
|
||||
};
|
||||
|
||||
#define VGAMEM() PADDR(arch->pcimem(0xA0000, 1<<16))
|
||||
|
||||
#define vgai(port) inb(port)
|
||||
#define vgao(port, data) outb(port, data)
|
||||
|
||||
extern int vgaxi(long, uchar);
|
||||
extern int vgaxo(long, uchar, uchar);
|
||||
|
||||
/*
|
||||
*/
|
||||
typedef struct VGAdev VGAdev;
|
||||
typedef struct VGAcur VGAcur;
|
||||
typedef struct VGAscr VGAscr;
|
||||
|
||||
struct VGAdev {
|
||||
char* name;
|
||||
|
||||
void (*enable)(VGAscr*);
|
||||
void (*disable)(VGAscr*);
|
||||
void (*page)(VGAscr*, int);
|
||||
void (*linear)(VGAscr*, int, int);
|
||||
void (*drawinit)(VGAscr*);
|
||||
int (*fill)(VGAscr*, Rectangle, ulong);
|
||||
void (*flush)(VGAscr*, Rectangle);
|
||||
|
||||
};
|
||||
|
||||
struct VGAcur {
|
||||
char* name;
|
||||
|
||||
void (*enable)(VGAscr*);
|
||||
void (*disable)(VGAscr*);
|
||||
void (*load)(VGAscr*, Cursor*);
|
||||
int (*move)(VGAscr*, Point);
|
||||
|
||||
int doespanning;
|
||||
};
|
||||
|
||||
/*
|
||||
*/
|
||||
struct VGAscr {
|
||||
Lock devlock;
|
||||
VGAdev* dev;
|
||||
Pcidev* pci;
|
||||
|
||||
VGAcur* cur;
|
||||
ulong storage;
|
||||
Cursor;
|
||||
|
||||
int useflush;
|
||||
|
||||
ulong paddr; /* frame buffer */
|
||||
void* vaddr;
|
||||
int apsize;
|
||||
|
||||
ulong io; /* device specific registers */
|
||||
ulong *mmio;
|
||||
|
||||
ulong colormap[Pcolours][3];
|
||||
int palettedepth;
|
||||
|
||||
Memimage* gscreen;
|
||||
Memdata* gscreendata;
|
||||
Memsubfont* memdefont;
|
||||
|
||||
int (*fill)(VGAscr*, Rectangle, ulong);
|
||||
int (*scroll)(VGAscr*, Rectangle, Rectangle);
|
||||
void (*blank)(VGAscr*, int);
|
||||
ulong id; /* internal identifier for driver use */
|
||||
};
|
||||
|
||||
extern VGAscr vgascreen[];
|
||||
|
||||
enum {
|
||||
Backgnd = 0, /* black */
|
||||
};
|
||||
|
||||
/* mouse.c */
|
||||
extern void mousectl(Cmdbuf*);
|
||||
|
||||
/* screen.c */
|
||||
extern int hwaccel; /* use hw acceleration; default on */
|
||||
extern int hwblank; /* use hw blanking; default on */
|
||||
extern void addvgaseg(char*, ulong, ulong);
|
||||
extern uchar* attachscreen(Rectangle*, ulong*, int*, int*, int*);
|
||||
extern void flushmemscreen(Rectangle);
|
||||
extern int cursoron(int);
|
||||
extern void cursoroff(int);
|
||||
extern void setcursor(Cursor*);
|
||||
extern int screensize(int, int, int, ulong);
|
||||
extern int screenaperture(int, int);
|
||||
extern Rectangle physgscreenr; /* actual monitor size */
|
||||
extern void blankscreen(int);
|
||||
|
||||
extern VGAcur swcursor;
|
||||
extern void swcursorinit(void);
|
||||
extern void swcursorhide(void);
|
||||
extern void swcursoravoid(Rectangle);
|
||||
extern void swcursorunhide(void);
|
||||
|
||||
/* devdraw.c */
|
||||
extern void deletescreenimage(void);
|
||||
extern int drawhasclients(void);
|
||||
extern ulong blanktime;
|
||||
extern QLock drawlock;
|
||||
|
||||
/* vga.c */
|
||||
extern void vgascreenwin(VGAscr*);
|
||||
extern void vgaimageinit(ulong);
|
||||
extern void vgalinearpciid(VGAscr*, int, int);
|
||||
extern void vgalinearpci(VGAscr*);
|
||||
extern void vgalinearaddr(VGAscr*, ulong, int);
|
||||
|
||||
extern void drawblankscreen(int);
|
||||
extern void vgablank(VGAscr*, int);
|
||||
|
||||
extern Lock vgascreenlock;
|
||||
|
||||
#define ishwimage(i) (vgascreen[0].gscreendata && (i)->data->bdata == vgascreen[0].gscreendata->bdata)
|
||||
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -1,18 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "io.h"
|
||||
|
||||
/*
|
||||
* 82378ZB Saturn-I/O (SIO) PCI-to-ISA Bus Bridge.
|
||||
*/
|
||||
static Pcidev* siodev;
|
||||
|
||||
void
|
||||
siodump(void)
|
||||
{
|
||||
if(siodev == nil && (siodev = pcimatch(nil, 0x8086, 0x0484)) == nil)
|
||||
return;
|
||||
}
|
|
@ -1,902 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "../port/lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "ureg.h"
|
||||
#include "io.h"
|
||||
#include "../port/error.h"
|
||||
|
||||
void noted(Ureg*, Ureg**, ulong);
|
||||
void rfnote(Ureg**);
|
||||
void kernfault(Ureg*, int);
|
||||
void illegal(Ureg *);
|
||||
void fen(Ureg *);
|
||||
|
||||
char *regname[]={
|
||||
"type", "a0", "a1",
|
||||
"a2", "R0", "R1",
|
||||
"R2", "R3", "R4",
|
||||
"R5", "R6", "R7",
|
||||
"R8", "R9", "R10",
|
||||
"R11", "R12", "R13",
|
||||
"R14", "R15", "R19",
|
||||
"R20", "R21", "R22",
|
||||
"R23", "R24", "R25",
|
||||
"R26", "R27", "R28",
|
||||
"R30", "status", "PC",
|
||||
"R29", "R16", "R17",
|
||||
"R18",
|
||||
};
|
||||
|
||||
static Lock vctllock;
|
||||
static Vctl *vctl[256];
|
||||
|
||||
void
|
||||
intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
|
||||
{
|
||||
int vno;
|
||||
Vctl *v;
|
||||
|
||||
if(f == nil){
|
||||
print("intrenable: nil handler for %d, tbdf 0x%uX for %s\n",
|
||||
irq, tbdf, name);
|
||||
return;
|
||||
}
|
||||
|
||||
v = xalloc(sizeof(Vctl));
|
||||
v->isintr = 1;
|
||||
v->irq = irq;
|
||||
v->tbdf = tbdf;
|
||||
v->f = f;
|
||||
v->a = a;
|
||||
strncpy(v->name, name, KNAMELEN-1);
|
||||
v->name[KNAMELEN-1] = 0;
|
||||
|
||||
ilock(&vctllock);
|
||||
vno = arch->intrenable(v);
|
||||
if(vno == -1){
|
||||
iunlock(&vctllock);
|
||||
print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n",
|
||||
irq, tbdf, v->name);
|
||||
xfree(v);
|
||||
return;
|
||||
}
|
||||
if(vctl[vno]){
|
||||
if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi)
|
||||
panic("intrenable: handler: %s %s %#p %#p %#p %#p",
|
||||
vctl[vno]->name, v->name,
|
||||
vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi);
|
||||
v->next = vctl[vno];
|
||||
}
|
||||
vctl[vno] = v;
|
||||
iunlock(&vctllock);
|
||||
}
|
||||
|
||||
int
|
||||
intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name)
|
||||
{
|
||||
Vctl **pv, *v;
|
||||
int vno;
|
||||
|
||||
/*
|
||||
* For now, none of this will work with the APIC code,
|
||||
* there is no mapping between irq and vector as the IRQ
|
||||
* is pretty meaningless.
|
||||
*/
|
||||
if(arch->intrvecno == nil)
|
||||
return -1;
|
||||
vno = arch->intrvecno(irq);
|
||||
ilock(&vctllock);
|
||||
for(pv = &vctl[vno]; *pv != nil; pv = &((*pv)->next)){
|
||||
if((*pv)->irq != irq)
|
||||
continue;
|
||||
if((*pv)->tbdf != tbdf)
|
||||
continue;
|
||||
if((*pv)->f != f)
|
||||
continue;
|
||||
if((*pv)->a != a)
|
||||
continue;
|
||||
if(strcmp((*pv)->name, name) != 0)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
assert(*pv != nil);
|
||||
|
||||
v = *pv;
|
||||
*pv = (*pv)->next; /* Link out the entry */
|
||||
|
||||
if (vctl[vno] == nil && arch->intrdisable != nil)
|
||||
arch->intrdisable(irq);
|
||||
iunlock(&vctllock);
|
||||
xfree(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
irqallocread(char *buf, long n, vlong offset)
|
||||
{
|
||||
int vno;
|
||||
Vctl *v;
|
||||
long oldn;
|
||||
char str[11+1+KNAMELEN+1], *p;
|
||||
int m;
|
||||
|
||||
if(n < 0 || offset < 0)
|
||||
error(Ebadarg);
|
||||
|
||||
oldn = n;
|
||||
for(vno=0; vno<nelem(vctl); vno++){
|
||||
for(v=vctl[vno]; v; v=v->next){
|
||||
m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, KNAMELEN, v->name);
|
||||
if(m <= offset) /* if do not want this, skip entry */
|
||||
offset -= m;
|
||||
else{
|
||||
/* skip offset bytes */
|
||||
m -= offset;
|
||||
p = str+offset;
|
||||
offset = 0;
|
||||
|
||||
/* write at most max(n,m) bytes */
|
||||
if(m > n)
|
||||
m = n;
|
||||
memmove(buf, p, m);
|
||||
n -= m;
|
||||
buf += m;
|
||||
|
||||
if(n == 0)
|
||||
return oldn;
|
||||
}
|
||||
}
|
||||
}
|
||||
return oldn - n;
|
||||
}
|
||||
|
||||
typedef struct Mcheck Mcheck;
|
||||
struct Mcheck
|
||||
{
|
||||
ulong len;
|
||||
ulong inprogress;
|
||||
ulong procoff;
|
||||
ulong sysoff;
|
||||
ulong code;
|
||||
};
|
||||
|
||||
static char *
|
||||
smcheck(ulong code)
|
||||
{
|
||||
switch (code) {
|
||||
case 0x80: return "tag parity error";
|
||||
case 0x82: return "tag control parity error";
|
||||
case 0x84: return "generic hard error";
|
||||
case 0x86: return "correctable ECC error";
|
||||
case 0x88: return "uncorrectable ECC error";
|
||||
case 0x8a: return "OS-specific PAL bugcheck";
|
||||
case 0x90: return "callsys in kernel mode";
|
||||
case 0x96: return "i-cache read retryable error";
|
||||
case 0x98: return "processor detected hard error";
|
||||
|
||||
case 0x203: return "system detected uncorrectable ECC error";
|
||||
case 0x205: return "parity error detected by CIA";
|
||||
case 0x207: return "non-existent memory error";
|
||||
case 0x209: return "PCI SERR detected";
|
||||
case 0x20b: return "PCI data parity error detected";
|
||||
case 0x20d: return "PCI address parity error detected";
|
||||
case 0x20f: return "PCI master abort error";
|
||||
case 0x211: return "PCI target abort error";
|
||||
case 0x213: return "scatter/gather PTE invalid error";
|
||||
case 0x215: return "flash ROM write error";
|
||||
case 0x217: return "IOA timeout detected";
|
||||
case 0x219: return "IOCHK#, EISA add-in board parity or other catastrophic error";
|
||||
case 0x21b: return "EISA fail-safe timer timeout";
|
||||
case 0x21d: return "EISA bus time-out";
|
||||
case 0x21f: return "EISA software generated NMI";
|
||||
case 0x221: return "unexpected ev5 IRQ[3] interrupt";
|
||||
default: return "unknown mcheck";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mcheck(Ureg *ur, void *x)
|
||||
{
|
||||
Mcheck *m;
|
||||
uvlong *data;
|
||||
int i, col;
|
||||
|
||||
m = x;
|
||||
data = x;
|
||||
iprint("panic: Machine Check @%#p: %s (%lux) len %lud\n",
|
||||
m, smcheck(m->code), m->code, m->len);
|
||||
iprint("proc offset %lux sys offset %lux\n", m->procoff, m->sysoff);
|
||||
for (i = 0, col = 0; i < m->len/8; i++) {
|
||||
iprint("%.3x: %.16llux%s", 8*i, data[i], (col == 2) ? "\n" : " ");
|
||||
if (col++ == 2)
|
||||
col = 0;
|
||||
}
|
||||
if(col != 2)
|
||||
print("\n");
|
||||
print("\n");
|
||||
dumpregs(ur);
|
||||
prflush();
|
||||
firmware();
|
||||
}
|
||||
|
||||
void
|
||||
intr(Ureg *ur)
|
||||
{
|
||||
int i, vno;
|
||||
Vctl *ctl, *v;
|
||||
Mach *mach;
|
||||
|
||||
vno = (ulong)ur->a1>>4;
|
||||
vno -= 0x80;
|
||||
if(vno < nelem(vctl) && (ctl = vctl[vno])){
|
||||
if(ctl->isintr){
|
||||
m->intr++;
|
||||
if(vno >= VectorPIC && vno <= MaxVectorPIC)
|
||||
m->lastintr = vno-VectorPIC;
|
||||
}
|
||||
|
||||
if(ctl->isr)
|
||||
ctl->isr(vno);
|
||||
for(v = ctl; v != nil; v = v->next) {
|
||||
if(v->f)
|
||||
v->f(ur, v->a);
|
||||
}
|
||||
|
||||
if(ctl->eoi)
|
||||
ctl->eoi(vno);
|
||||
|
||||
if(ctl->isintr && up)
|
||||
preempted();
|
||||
}
|
||||
else if(vno >= VectorPIC && vno <= MaxVectorPIC){
|
||||
/*
|
||||
* An unknown interrupt.
|
||||
* Check for a default IRQ7. This can happen when
|
||||
* the IRQ input goes away before the acknowledge.
|
||||
* In this case, a 'default IRQ7' is generated, but
|
||||
* the corresponding bit in the ISR isn't set.
|
||||
* In fact, just ignore all such interrupts.
|
||||
*/
|
||||
iprint("cpu%d: spurious interrupt %d, last %d",
|
||||
m->machno, vno-VectorPIC, m->lastintr);
|
||||
for(i = 0; i < MAXMACH; i++){
|
||||
if(active.machs[i] == 0)
|
||||
continue;
|
||||
mach = MACHP(i);
|
||||
if(m->machno == mach->machno)
|
||||
continue;
|
||||
iprint(": cpu%d: last %d", mach->machno, mach->lastintr);
|
||||
}
|
||||
iprint("\n");
|
||||
m->spuriousintr++;
|
||||
return;
|
||||
}
|
||||
else{
|
||||
dumpregs(ur);
|
||||
print("unknown intr: %d\n", vno); /* */
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
trap(Ureg *ur)
|
||||
{
|
||||
char buf[ERRMAX];
|
||||
int clockintr, user, x;
|
||||
|
||||
user = ur->status&UMODE;
|
||||
|
||||
if(user){
|
||||
up = m->proc;
|
||||
up->dbgreg = ur;
|
||||
}
|
||||
clockintr = 0;
|
||||
switch ((int)ur->type) {
|
||||
case 1: /* arith */
|
||||
fptrap(ur);
|
||||
break;
|
||||
case 2: /* bad instr or FEN */
|
||||
illegal(ur);
|
||||
break;
|
||||
|
||||
case 3: /* intr */
|
||||
m->intr++;
|
||||
switch ((int)ur->a0) {
|
||||
case 0: /* interprocessor */
|
||||
panic("interprocessor intr");
|
||||
break;
|
||||
case 1: /* clock */
|
||||
clockintr = 1;
|
||||
clock(ur);
|
||||
break;
|
||||
case 2: /* machine check */
|
||||
mcheck(ur, (void*)(KZERO|(ulong)ur->a2));
|
||||
break;
|
||||
case 3: /* device */
|
||||
intr(ur);
|
||||
break;
|
||||
case 4: /* perf counter */
|
||||
panic("perf count");
|
||||
break;
|
||||
default:
|
||||
panic("bad intr");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: /* memory fault */
|
||||
if(up == 0)
|
||||
kernfault(ur, (ulong)ur->a1);
|
||||
|
||||
x = up->insyscall;
|
||||
up->insyscall = 1;
|
||||
spllo();
|
||||
faultalpha(ur);
|
||||
up->insyscall = x;
|
||||
break;
|
||||
case 6: /* alignment fault */
|
||||
ur->pc -= 4;
|
||||
sprint(buf, "trap: unaligned addr 0x%lux", (ulong)ur->a0);
|
||||
fataltrap(ur, buf);
|
||||
break;
|
||||
default: /* cannot happen */
|
||||
panic("bad trap type %d", (int)ur->type);
|
||||
break;
|
||||
}
|
||||
|
||||
splhi();
|
||||
|
||||
/* delaysched set because we held a lock or because our quantum ended */
|
||||
if(up && up->delaysched && clockintr){
|
||||
sched();
|
||||
splhi();
|
||||
}
|
||||
|
||||
if(user){
|
||||
if(up->procctl || up->nnote)
|
||||
notify(ur);
|
||||
kexit(ur);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
trapinit(void)
|
||||
{
|
||||
splhi();
|
||||
wrent(0, intr0);
|
||||
wrent(1, arith);
|
||||
wrent(2, fault0);
|
||||
wrent(3, illegal0);
|
||||
wrent(4, unaligned);
|
||||
wrent(5, syscall0);
|
||||
}
|
||||
|
||||
void
|
||||
fataltrap(Ureg *ur, char *reason)
|
||||
{
|
||||
char buf[ERRMAX];
|
||||
|
||||
if(ur->status&UMODE) {
|
||||
spllo();
|
||||
sprint(buf, "sys: %s", reason);
|
||||
postnote(up, 1, buf, NDebug);
|
||||
return;
|
||||
}
|
||||
print("kernel %s pc=%lux\n", reason, (ulong)ur->pc);
|
||||
dumpregs(ur);
|
||||
dumpstack();
|
||||
if(m->machno == 0)
|
||||
spllo();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
kernfault(Ureg *ur, int code)
|
||||
{
|
||||
Label l;
|
||||
char *s;
|
||||
|
||||
splhi();
|
||||
if (code == 0)
|
||||
s = "read";
|
||||
else if (code == 1)
|
||||
s = "write";
|
||||
else
|
||||
s = "ifetch";
|
||||
print("panic: kfault %s VA=0x%lux\n", s, (ulong)ur->a0);
|
||||
print("u=%#p status=0x%lux pc=0x%lux sp=0x%lux\n",
|
||||
up, (ulong)ur->status, (ulong)ur->pc, (ulong)ur->sp);
|
||||
dumpregs(ur);
|
||||
l.sp = ur->sp;
|
||||
l.pc = ur->pc;
|
||||
dumpstack();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
dumpregs(Ureg *ur)
|
||||
{
|
||||
int i, col;
|
||||
uvlong *l;
|
||||
|
||||
if(up)
|
||||
print("registers for %s %ld\n", up->text, up->pid);
|
||||
else
|
||||
print("registers for kernel\n");
|
||||
|
||||
l = &ur->type;
|
||||
col = 0;
|
||||
for (i = 0; i < sizeof regname/sizeof(char*); i++, l++) {
|
||||
print("%-7s%.16llux%s", regname[i], *l, col == 2 ? "\n" : " ");
|
||||
if (col++ == 2)
|
||||
col = 0;
|
||||
}
|
||||
print("\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Fill in enough of Ureg to get a stack trace, and call a function.
|
||||
* Used by debugging interface rdb.
|
||||
*/
|
||||
static void
|
||||
getpcsp(ulong *pc, ulong *sp)
|
||||
{
|
||||
*pc = getcallerpc(&pc);
|
||||
*sp = (ulong)&pc-8;
|
||||
}
|
||||
|
||||
void
|
||||
callwithureg(void (*fn)(Ureg*))
|
||||
{
|
||||
Ureg ureg;
|
||||
|
||||
getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp);
|
||||
ureg.r26 = getcallerpc(&fn);
|
||||
fn(&ureg);
|
||||
}
|
||||
|
||||
void
|
||||
_dumpstack(Ureg *ureg)
|
||||
{
|
||||
ulong l, sl, el, v, i, instr, op;
|
||||
extern ulong etext;
|
||||
|
||||
l=(ulong)&l;
|
||||
if(l&4)
|
||||
l += 4;
|
||||
if(up == 0){
|
||||
el = (ulong)m+BY2PG;
|
||||
sl = el-KSTACK;
|
||||
}
|
||||
else{
|
||||
sl = (ulong)up->kstack;
|
||||
el = sl + KSTACK;
|
||||
}
|
||||
if(l > el || l < sl){
|
||||
el = (ulong)m+BY2PG;
|
||||
sl = el-KSTACK;
|
||||
}
|
||||
if(l > el || l < sl)
|
||||
return;
|
||||
print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", (ulong)ureg->pc, (ulong)ureg->sp, (ulong)ureg->r26);
|
||||
|
||||
i = 0;
|
||||
for(; l<el; l+=8){
|
||||
v = *(ulong*)l - 4;
|
||||
if(KTZERO < v && v < (ulong)&etext && (v&3) == 0){
|
||||
/*
|
||||
* Check for JSR/BSR
|
||||
*/
|
||||
instr = *(ulong*)v;
|
||||
op = (instr>>26);
|
||||
if(op == 26 || op == 52){
|
||||
print("%lux=%lux ", l, v);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if(i == 4){
|
||||
i = 0;
|
||||
print("\n");
|
||||
}
|
||||
}
|
||||
if(i)
|
||||
print("\n");
|
||||
}
|
||||
|
||||
void
|
||||
dumpstack(void)
|
||||
{
|
||||
callwithureg(_dumpstack);
|
||||
}
|
||||
|
||||
int
|
||||
notify(Ureg *ur)
|
||||
{
|
||||
int l;
|
||||
ulong sp;
|
||||
Note *n;
|
||||
|
||||
if(up->procctl)
|
||||
procctl();
|
||||
if(up->nnote == 0)
|
||||
return 0;
|
||||
|
||||
if(up->fpstate == FPactive){
|
||||
savefpregs(&up->fpsave);
|
||||
up->fpstate = FPinactive;
|
||||
}
|
||||
up->fpstate |= FPillegal;
|
||||
|
||||
spllo();
|
||||
qlock(&up->debug);
|
||||
up->notepending = 0;
|
||||
|
||||
n = &up->note[0];
|
||||
if(strncmp(n->msg, "sys:", 4) == 0) {
|
||||
l = strlen(n->msg);
|
||||
if(l > ERRMAX-15) /* " pc=0x12345678\0" */
|
||||
l = ERRMAX-15;
|
||||
|
||||
sprint(n->msg+l, " pc=0x%lux", (ulong)ur->pc);
|
||||
}
|
||||
|
||||
if(n->flag != NUser && (up->notified || up->notify==0)) {
|
||||
qunlock(&up->debug);
|
||||
if(n->flag == NDebug)
|
||||
pprint("suicide: %s\n", n->msg);
|
||||
pexit(n->msg, n->flag!=NDebug);
|
||||
}
|
||||
|
||||
if(up->notified) {
|
||||
qunlock(&up->debug);
|
||||
splhi();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!up->notify) {
|
||||
qunlock(&up->debug);
|
||||
pexit(n->msg, n->flag!=NDebug);
|
||||
}
|
||||
sp = ur->usp & ~(BY2V-1);
|
||||
sp -= sizeof(Ureg);
|
||||
|
||||
if(!okaddr((uintptr)up->notify, BY2WD, 0)
|
||||
|| !okaddr(sp-ERRMAX-6*BY2WD, sizeof(Ureg)+ERRMAX-6*BY2WD, 1)) {
|
||||
qunlock(&up->debug);
|
||||
pprint("suicide: bad address or sp in notify\n");
|
||||
pexit("Suicide", 0);
|
||||
}
|
||||
|
||||
memmove((Ureg*)sp, ur, sizeof(Ureg));
|
||||
*(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
|
||||
up->ureg = (void*)sp;
|
||||
sp -= 2*BY2WD+ERRMAX;
|
||||
memmove((char*)sp, up->note[0].msg, ERRMAX);
|
||||
sp -= 4*BY2WD;
|
||||
*(ulong*)(sp+3*BY2WD) = sp+4*BY2WD; /* arg 2 is string */
|
||||
ur->r0 = (ulong)up->ureg; /* arg 1 (R0) is ureg* */
|
||||
*(ulong*)(sp+2*BY2WD) = (ulong)up->ureg; /* arg 1 0(FP) is ureg* */
|
||||
*(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */
|
||||
ur->usp = sp;
|
||||
ur->pc = (ulong)up->notify;
|
||||
up->notified = 1;
|
||||
up->nnote--;
|
||||
memmove(&up->lastnote, &up->note[0], sizeof(Note));
|
||||
memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
|
||||
|
||||
qunlock(&up->debug);
|
||||
splhi();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that status is OK to return from note.
|
||||
*/
|
||||
int
|
||||
validstatus(ulong kstatus, ulong ustatus)
|
||||
{
|
||||
if((kstatus & 7) != (ustatus & 7))
|
||||
return 0;
|
||||
if((ustatus&UMODE) != UMODE)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return user to state before notify()
|
||||
*/
|
||||
void
|
||||
noted(Ureg *kur, Ureg **urp, ulong arg0)
|
||||
{
|
||||
Ureg *nur;
|
||||
ulong oureg, sp;
|
||||
|
||||
qlock(&up->debug);
|
||||
if(arg0!=NRSTR && !up->notified) {
|
||||
qunlock(&up->debug);
|
||||
pprint("call to noted() when not notified\n");
|
||||
pexit("Suicide", 0);
|
||||
}
|
||||
up->notified = 0;
|
||||
|
||||
up->fpstate &= ~FPillegal;
|
||||
|
||||
nur = up->ureg;
|
||||
|
||||
oureg = (ulong)nur;
|
||||
if((oureg & (BY2V-1))
|
||||
|| !okaddr(oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
|
||||
qunlock(&up->debug);
|
||||
pprint("bad ureg in noted or call to noted() when not notified\n");
|
||||
pexit("Suicide", 0);
|
||||
}
|
||||
|
||||
if(!validstatus(kur->status, nur->status)) {
|
||||
qunlock(&up->debug);
|
||||
pprint("bad noted ureg status %lux\n", (ulong)nur->status);
|
||||
pexit("Suicide", 0);
|
||||
}
|
||||
|
||||
memmove(*urp, up->ureg, sizeof(Ureg));
|
||||
switch(arg0) {
|
||||
case NCONT:
|
||||
case NRSTR:
|
||||
if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
|
||||
qunlock(&up->debug);
|
||||
pprint("suicide: trap in noted\n");
|
||||
pexit("Suicide", 0);
|
||||
}
|
||||
up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
|
||||
qunlock(&up->debug);
|
||||
splhi();
|
||||
rfnote(urp);
|
||||
break;
|
||||
|
||||
case NSAVE:
|
||||
if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
|
||||
qunlock(&up->debug);
|
||||
pprint("suicide: trap in noted\n");
|
||||
pexit("Suicide", 0);
|
||||
}
|
||||
qunlock(&up->debug);
|
||||
sp = oureg-4*BY2WD-ERRMAX;
|
||||
splhi();
|
||||
(*urp)->sp = sp;
|
||||
((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
|
||||
((ulong*)sp)[0] = 0; /* arg 0 is pc */
|
||||
(*urp)->r0 = oureg; /* arg 1 is ureg* */
|
||||
rfnote(urp);
|
||||
break;
|
||||
|
||||
default:
|
||||
up->lastnote.flag = NDebug;
|
||||
/* fall through */
|
||||
|
||||
case NDFLT:
|
||||
qunlock(&up->debug);
|
||||
if(up->lastnote.flag == NDebug)
|
||||
pprint("suicide: %s\n", up->lastnote.msg);
|
||||
pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
|
||||
}
|
||||
}
|
||||
|
||||
#include "../port/systab.h"
|
||||
|
||||
long
|
||||
syscall(Ureg *aur)
|
||||
{
|
||||
int i;
|
||||
char *e;
|
||||
long ret;
|
||||
ulong sp;
|
||||
Ureg *ur;
|
||||
ulong scallnr;
|
||||
|
||||
m->syscall++;
|
||||
up = m->proc;
|
||||
up->insyscall = 1;
|
||||
ur = aur;
|
||||
up->pc = ur->pc;
|
||||
up->dbgreg = aur;
|
||||
ur->type = 5; /* for debugging */
|
||||
|
||||
scallnr = ur->r0;
|
||||
up->scallnr = ur->r0;
|
||||
spllo();
|
||||
|
||||
sp = ur->sp;
|
||||
up->nerrlab = 0;
|
||||
ret = -1;
|
||||
if(!waserror()) {
|
||||
if(scallnr >= nsyscall || systab[scallnr] == nil){
|
||||
pprint("bad sys call %d pc %lux\n", up->scallnr, (ulong)ur->pc);
|
||||
postnote(up, 1, "sys: bad sys call", NDebug);
|
||||
error(Ebadarg);
|
||||
}
|
||||
|
||||
if(sp & (BY2WD-1)){ /* XXX too weak? */
|
||||
pprint("odd sp in sys call pc %lux sp %lux\n",
|
||||
(ulong)ur->pc, (ulong)ur->sp);
|
||||
postnote(up, 1, "sys: odd stack", NDebug);
|
||||
error(Ebadarg);
|
||||
}
|
||||
|
||||
if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)))
|
||||
validaddr(sp, sizeof(Sargs), 0);
|
||||
|
||||
up->s = *((Sargs*)(sp+2*BY2WD));
|
||||
up->psstate = sysctab[scallnr];
|
||||
ret = systab[scallnr]((va_list)up->s.args);
|
||||
poperror();
|
||||
}else{
|
||||
/* failure: save the error buffer for errstr */
|
||||
e = up->syserrstr;
|
||||
up->syserrstr = up->errstr;
|
||||
up->errstr = e;
|
||||
}
|
||||
if(up->nerrlab){
|
||||
print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab);
|
||||
for(i = 0; i < NERR; i++)
|
||||
print("sp=%lux pc=%lux\n",
|
||||
up->errlab[i].sp, up->errlab[i].pc);
|
||||
panic("error stack");
|
||||
}
|
||||
|
||||
up->nerrlab = 0;
|
||||
up->psstate = 0;
|
||||
up->insyscall = 0;
|
||||
if(scallnr == NOTED) /* ugly hack */
|
||||
noted(ur, &aur, *(ulong*)(sp+2*BY2WD)); /* doesn't return */
|
||||
|
||||
if(scallnr!=RFORK && (up->procctl || up->nnote)){
|
||||
ur->r0 = ret; /* load up for noted() */
|
||||
if(notify(ur))
|
||||
return ur->r0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
forkchild(Proc *p, Ureg *ur)
|
||||
{
|
||||
Ureg *cur;
|
||||
|
||||
p->sched.sp = (ulong)p->kstack+KSTACK-(4*BY2WD+sizeof(Ureg));
|
||||
p->sched.pc = (ulong)forkret;
|
||||
|
||||
cur = (Ureg*)(p->sched.sp+4*BY2WD);
|
||||
memmove(cur, ur, sizeof(Ureg));
|
||||
|
||||
/* Things from bottom of syscall we never got to execute */
|
||||
p->psstate = 0;
|
||||
p->insyscall = 0;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
linkproc(void)
|
||||
{
|
||||
spllo();
|
||||
up->kpfun(up->kparg);
|
||||
pexit("kproc exiting", 0);
|
||||
}
|
||||
|
||||
void
|
||||
kprocchild(Proc *p, void (*func)(void*), void *arg)
|
||||
{
|
||||
p->sched.pc = (ulong)linkproc;
|
||||
p->sched.sp = (ulong)p->kstack+KSTACK;
|
||||
|
||||
p->kpfun = func;
|
||||
p->kparg = arg;
|
||||
}
|
||||
|
||||
uintptr
|
||||
execregs(uintptr entry, ulong ssize, ulong nargs)
|
||||
{
|
||||
Ureg *ur;
|
||||
ulong *sp;
|
||||
|
||||
sp = (ulong*)(USTKTOP - ssize);
|
||||
*--sp = nargs;
|
||||
|
||||
ur = (Ureg*)up->dbgreg;
|
||||
ur->usp = (ulong)sp;
|
||||
ur->pc = entry;
|
||||
return USTKTOP-BY2WD; /* address of user-level clock */
|
||||
}
|
||||
|
||||
uintptr
|
||||
userpc(void)
|
||||
{
|
||||
Ureg *ur;
|
||||
|
||||
ur = (Ureg*)up->dbgreg;
|
||||
return ur->pc;
|
||||
}
|
||||
|
||||
/* This routine must save the values of registers the user is not permitted to write
|
||||
* from devproc and then restore the saved values before returning
|
||||
*/
|
||||
void
|
||||
setregisters(Ureg *xp, char *pureg, char *uva, int n)
|
||||
{
|
||||
ulong status;
|
||||
|
||||
status = xp->status;
|
||||
memmove(pureg, uva, n);
|
||||
xp->status = status;
|
||||
}
|
||||
|
||||
/* Give enough context in the ureg to produce a kernel stack for
|
||||
* a sleeping process
|
||||
*/
|
||||
void
|
||||
setkernur(Ureg *xp, Proc *p)
|
||||
{
|
||||
xp->pc = p->sched.pc;
|
||||
xp->sp = p->sched.sp;
|
||||
xp->r26 = (ulong)sched;
|
||||
}
|
||||
|
||||
uintptr
|
||||
dbgpc(Proc *p)
|
||||
{
|
||||
Ureg *ur;
|
||||
|
||||
ur = p->dbgreg;
|
||||
if(ur == 0)
|
||||
return 0;
|
||||
|
||||
return ur->pc;
|
||||
}
|
||||
|
||||
void
|
||||
illegal(Ureg *ur)
|
||||
{
|
||||
switch ((int)ur->a0) {
|
||||
case 0: /* breakpoint */
|
||||
ur->pc -= 4;
|
||||
fataltrap(ur, "breakpoint");
|
||||
break;
|
||||
case 1: /* bugchk */
|
||||
fataltrap(ur, "trap: bugchk");
|
||||
break;
|
||||
case 2: /* gentrap */
|
||||
fataltrap(ur, "trap: gentrap");
|
||||
break;
|
||||
case 3: /* FEN */
|
||||
fen(ur);
|
||||
break;
|
||||
case 4: /* opDEC */
|
||||
fataltrap(ur, "trap: illegal instruction");
|
||||
break;
|
||||
default:
|
||||
panic("illegal illegal %d", (int)ur->a0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fen(Ureg *ur)
|
||||
{
|
||||
if(up){
|
||||
switch(up->fpstate){
|
||||
case FPinit:
|
||||
restfpregs(&initfp);
|
||||
up->fpstate = FPactive;
|
||||
//print("EI=%lux+", initfp.fpstatus);
|
||||
return;
|
||||
|
||||
case FPinactive:
|
||||
restfpregs(&up->fpsave);
|
||||
up->fpstate = FPactive;
|
||||
//print("EIA=%lux+", up->fpsave.fpstatus);
|
||||
return;
|
||||
}
|
||||
}
|
||||
fataltrap(ur, "trap: floating enable"); /* should never happen */
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
ARCH=\
|
||||
alphapc\
|
||||
bcm\
|
||||
bitsy\
|
||||
kw\
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
TEXT getcallerpc(SB), $-8
|
||||
MOVL 0(SP), R0
|
||||
RET
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
#define EXCB WORD $0x60000400 /* until 7a/7l catch up */
|
||||
|
||||
TEXT getfsr(SB), $8
|
||||
EXCB
|
||||
MOVT FPCR, F0
|
||||
EXCB
|
||||
MOVT F0, tmp-8(SP)
|
||||
MOVL tmp-4(SP), R1
|
||||
MOVQ $0x01e00000, R2
|
||||
AND R2, R1, R0
|
||||
RET
|
||||
|
||||
TEXT setfsr(SB), $8
|
||||
MOVQ $0x01e00000, R2
|
||||
EXCB
|
||||
MOVT FPCR, F0
|
||||
EXCB
|
||||
MOVT F0, tmp-8(SP)
|
||||
MOVL tmp-4(SP), R1
|
||||
ANDNOT R2, R1, R3
|
||||
AND R2, R0, R4
|
||||
OR R3, R4, R5
|
||||
MOVL R5, tmp-4(SP)
|
||||
MOVT tmp-8(SP), F0
|
||||
EXCB
|
||||
MOVT F0, FPCR
|
||||
EXCB
|
||||
RET
|
||||
|
||||
TEXT getfcr(SB), $8
|
||||
EXCB
|
||||
MOVT FPCR, F0
|
||||
EXCB
|
||||
MOVT F0, tmp-8(SP)
|
||||
MOVL tmp-4(SP), R1
|
||||
MOVQ $0x700c0000, R2
|
||||
AND R2, R1, R0
|
||||
XOR R2, R0
|
||||
RET
|
||||
|
||||
TEXT setfcr(SB), $8
|
||||
MOVQ $0x700c0000, R2
|
||||
XOR R2, R0
|
||||
EXCB
|
||||
MOVT FPCR, F0
|
||||
EXCB
|
||||
MOVT F0, tmp-8(SP)
|
||||
MOVL tmp-4(SP), R1
|
||||
ANDNOT R2, R1, R3
|
||||
AND R2, R0, R4
|
||||
OR R3, R4, R5
|
||||
MOVL R5, tmp-4(SP)
|
||||
MOVT tmp-8(SP), F0
|
||||
EXCB
|
||||
MOVT F0, FPCR
|
||||
EXCB
|
||||
RET
|
|
@ -1,12 +0,0 @@
|
|||
extern long __SEEK(long long*, int, long long, int);
|
||||
|
||||
long long
|
||||
_SEEK(int fd, long long o, int p)
|
||||
{
|
||||
long long l;
|
||||
|
||||
if(__SEEK(&l, fd, o, p) < 0)
|
||||
l = -1;
|
||||
return l;
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
void
|
||||
_cycles(unsigned long long *u)
|
||||
{
|
||||
*u = 0;
|
||||
}
|
|
@ -1,189 +0,0 @@
|
|||
/*
|
||||
* ulong
|
||||
* _udiv(ulong num, ulong den)
|
||||
* {
|
||||
* int i;
|
||||
* ulong quo;
|
||||
*
|
||||
* if(den == 0)
|
||||
* *(ulong*)-1 = 0;
|
||||
* quo = num;
|
||||
* if(quo > 1<<(32-1))
|
||||
* quo = 1<<(32-1);
|
||||
* for(i=0; den<quo; i++)
|
||||
* den <<= 1;
|
||||
* quo = 0;
|
||||
* for(; i>=0; i--) {
|
||||
* quo <<= 1;
|
||||
* if(num >= den) {
|
||||
* num -= den;
|
||||
* quo |= 1;
|
||||
* }
|
||||
* den >>= 1;
|
||||
* }
|
||||
* return quo::num;
|
||||
* }
|
||||
*/
|
||||
|
||||
#define NOPROF 1
|
||||
|
||||
/*
|
||||
* calling sequence:
|
||||
* num: 8(R30)
|
||||
* den: 12(R30)
|
||||
* returns
|
||||
* quo: 8(R30)
|
||||
* rem: 12(R30)
|
||||
*/
|
||||
TEXT _udivmodl(SB), NOPROF, $-8
|
||||
|
||||
MOVQ $-1, R11
|
||||
SLLQ $31, R11 /* (1<<31) in canonical form */
|
||||
MOVL 8(R30), R23 /* numerator */
|
||||
MOVL 12(R30), R10 /* denominator */
|
||||
BNE R10, udm20
|
||||
MOVQ R31, -1(R31) /* fault -- divide by zero; todo: use gentrap? */
|
||||
udm20:
|
||||
MOVQ R23, R12
|
||||
BGE R12, udm34
|
||||
MOVQ R11, R12
|
||||
udm34:
|
||||
MOVQ R31, R11
|
||||
udm38:
|
||||
CMPUGE R10, R12, R24
|
||||
BNE R24, udm54
|
||||
SLLL $1, R10
|
||||
ADDQ $1, R11
|
||||
JMP udm38
|
||||
udm54:
|
||||
MOVQ R31, R12
|
||||
udm58:
|
||||
BLT R11, udm8c
|
||||
SLLL $1, R12
|
||||
CMPUGE R23, R10, R24
|
||||
BEQ R24, udm7c
|
||||
SUBL R10, R23
|
||||
OR $1, R12
|
||||
udm7c:
|
||||
SRLL $1, R10
|
||||
SUBQ $1, R11
|
||||
JMP udm58
|
||||
udm8c:
|
||||
MOVL R12, 8(R30) /* quotient */
|
||||
MOVL R23, 12(R30) /* remainder */
|
||||
RET
|
||||
|
||||
/*
|
||||
* save working registers
|
||||
* and bring in num/den parameters
|
||||
*/
|
||||
TEXT _unsargl(SB), NOPROF, $-8
|
||||
MOVQ R10, 24(R30)
|
||||
MOVQ R11, 32(R30)
|
||||
MOVQ R12, 40(R30)
|
||||
MOVQ R23, 48(R30)
|
||||
MOVQ R24, 56(R30)
|
||||
|
||||
MOVL R27, 8(R30)
|
||||
MOVL 72(R30), R27
|
||||
MOVL R27, 12(R30)
|
||||
|
||||
RET
|
||||
|
||||
/*
|
||||
* save working registers
|
||||
* and bring in absolute value
|
||||
* of num/den parameters
|
||||
*/
|
||||
TEXT _absargl(SB), NOPROF, $-8
|
||||
MOVQ R10, 24(R30)
|
||||
MOVQ R11, 32(R30)
|
||||
MOVQ R12, 40(R30)
|
||||
MOVQ R23, 48(R30)
|
||||
MOVQ R24, 56(R30)
|
||||
|
||||
MOVL R27, 64(R30)
|
||||
BGE R27, ab1
|
||||
SUBL R27, R31, R27
|
||||
ab1:
|
||||
MOVL R27, 8(R30) /* numerator */
|
||||
|
||||
MOVL 72(R30), R27
|
||||
BGE R27, ab2
|
||||
SUBL R27, R31, R27
|
||||
ab2:
|
||||
MOVL R27, 12(R30) /* denominator */
|
||||
RET
|
||||
|
||||
/*
|
||||
* restore registers and
|
||||
* return to original caller
|
||||
* answer is in R27
|
||||
*/
|
||||
TEXT _retargl(SB), NOPROF, $-8
|
||||
MOVQ 24(R30), R10
|
||||
MOVQ 32(R30), R11
|
||||
MOVQ 40(R30), R12
|
||||
MOVQ 48(R30), R23
|
||||
MOVQ 56(R30), R24
|
||||
MOVL 0(R30), R26
|
||||
|
||||
ADDQ $64, R30
|
||||
RET /* back to main sequence */
|
||||
|
||||
TEXT _divl(SB), NOPROF, $-8
|
||||
SUBQ $64, R30 /* 5 reg save, 2 parameters, link */
|
||||
MOVL R26, 0(R30)
|
||||
|
||||
JSR _absargl(SB)
|
||||
JSR _udivmodl(SB)
|
||||
MOVL 8(R30), R27
|
||||
|
||||
MOVL 64(R30), R10 /* clean up the sign */
|
||||
MOVL 72(R30), R11
|
||||
XOR R11, R10
|
||||
BGE R10, div1
|
||||
SUBL R27, R31, R27
|
||||
div1:
|
||||
|
||||
JSR _retargl(SB)
|
||||
RET /* not executed */
|
||||
|
||||
TEXT _divlu(SB), NOPROF, $-8
|
||||
SUBQ $64, R30 /* 5 reg save, 2 parameters, link */
|
||||
MOVL R26, 0(R30)
|
||||
|
||||
JSR _unsargl(SB)
|
||||
JSR _udivmodl(SB)
|
||||
MOVL 8(R30), R27
|
||||
|
||||
JSR _retargl(SB)
|
||||
RET /* not executed */
|
||||
|
||||
TEXT _modl(SB), NOPROF, $-8
|
||||
SUBQ $64, R30 /* 5 reg save, 2 parameters, link */
|
||||
MOVL R26, 0(R30)
|
||||
|
||||
JSR _absargl(SB)
|
||||
JSR _udivmodl(SB)
|
||||
MOVL 12(R30), R27
|
||||
|
||||
MOVL 64(R30), R10 /* clean up the sign */
|
||||
BGE R10, div2
|
||||
SUBL R27, R31, R27
|
||||
div2:
|
||||
|
||||
JSR _retargl(SB)
|
||||
RET /* not executed */
|
||||
|
||||
TEXT _modlu(SB), NOPROF, $-8
|
||||
SUBQ $64, R30 /* 5 reg save, 2 parameters, link */
|
||||
MOVL R26, 0(R30)
|
||||
|
||||
JSR _unsargl(SB)
|
||||
JSR _udivmodl(SB)
|
||||
MOVL 12(R30), R27
|
||||
|
||||
JSR _retargl(SB)
|
||||
RET /* not executed */
|
||||
|
|
@ -1,191 +0,0 @@
|
|||
/*
|
||||
* uvlong
|
||||
* _udiv(uvlong num, uvlong den)
|
||||
* {
|
||||
* int i;
|
||||
* uvlong quo;
|
||||
*
|
||||
* if(den == 0)
|
||||
* *(ulong*)-1 = 0;
|
||||
* quo = num;
|
||||
* if(quo > 1<<(64-1))
|
||||
* quo = 1<<(64-1);
|
||||
* for(i=0; den<quo; i++)
|
||||
* den <<= 1;
|
||||
* quo = 0;
|
||||
* for(; i>=0; i--) {
|
||||
* quo <<= 1;
|
||||
* if(num >= den) {
|
||||
* num -= den;
|
||||
* quo |= 1;
|
||||
* }
|
||||
* den >>= 1;
|
||||
* }
|
||||
* return quo::num;
|
||||
* }
|
||||
*/
|
||||
|
||||
#define NOPROF 1
|
||||
|
||||
/*
|
||||
* calling sequence:
|
||||
* num: 8(R30)
|
||||
* den: 16(R30)
|
||||
* returns
|
||||
* quo: 8(R30)
|
||||
* rem: 16(R30)
|
||||
*/
|
||||
TEXT _udivmodq(SB), NOPROF, $-8
|
||||
|
||||
MOVQ $1, R11
|
||||
SLLQ $63, R11
|
||||
MOVQ 8(R30), R23 /* numerator */
|
||||
MOVQ 16(R30), R10 /* denominator */
|
||||
BNE R10, udm20
|
||||
MOVQ R31, -1(R31) /* fault -- divide by zero; todo: use gentrap? */
|
||||
udm20:
|
||||
MOVQ R23, R12
|
||||
BGE R12, udm34
|
||||
MOVQ R11, R12
|
||||
udm34:
|
||||
MOVQ R31, R11
|
||||
udm38:
|
||||
CMPUGE R10, R12, R24
|
||||
BNE R24, udm54
|
||||
SLLQ $1, R10
|
||||
ADDQ $1, R11
|
||||
JMP udm38
|
||||
udm54:
|
||||
MOVQ R31, R12
|
||||
udm58:
|
||||
BLT R11, udm8c
|
||||
SLLQ $1, R12
|
||||
CMPUGE R23, R10, R24
|
||||
BEQ R24, udm7c
|
||||
SUBQ R10, R23
|
||||
OR $1, R12
|
||||
udm7c:
|
||||
SRLQ $1, R10
|
||||
SUBQ $1, R11
|
||||
JMP udm58
|
||||
udm8c:
|
||||
MOVQ R12, 8(R30) /* quotient */
|
||||
MOVQ R23, 16(R30) /* remainder */
|
||||
RET
|
||||
|
||||
/*
|
||||
* save working registers
|
||||
* and bring in num/den parameters
|
||||
*/
|
||||
TEXT _unsargq(SB), NOPROF, $-8
|
||||
MOVQ R10, 24(R30)
|
||||
MOVQ R11, 32(R30)
|
||||
MOVQ R12, 40(R30)
|
||||
MOVQ R23, 48(R30)
|
||||
MOVQ R24, 56(R30)
|
||||
|
||||
MOVQ R27, 8(R30)
|
||||
MOVQ 72(R30), R27
|
||||
MOVQ R27, 16(R30)
|
||||
|
||||
MOVQ (R30), R10 /* debug */
|
||||
RET
|
||||
|
||||
/*
|
||||
* save working registers
|
||||
* and bring in absolute value
|
||||
* of num/den parameters
|
||||
*/
|
||||
TEXT _absargq(SB), NOPROF, $-8
|
||||
MOVQ R10, 24(R30)
|
||||
MOVQ R11, 32(R30)
|
||||
MOVQ R12, 40(R30)
|
||||
MOVQ R23, 48(R30)
|
||||
MOVQ R24, 56(R30)
|
||||
|
||||
MOVQ R27, 64(R30)
|
||||
BGE R27, ab1
|
||||
SUBQ R27, R31, R27
|
||||
ab1:
|
||||
MOVQ R27, 8(R30) /* numerator */
|
||||
|
||||
MOVQ 72(R30), R27
|
||||
BGE R27, ab2
|
||||
SUBQ R27, R31, R27
|
||||
ab2:
|
||||
MOVQ R27, 16(R30) /* denominator */
|
||||
MOVQ (R30), R10 /* debug */
|
||||
RET
|
||||
|
||||
/*
|
||||
* restore registers and
|
||||
* return to original caller
|
||||
* answer is in R27
|
||||
*/
|
||||
TEXT _retargq(SB), NOPROF, $-8
|
||||
MOVQ 24(R30), R10
|
||||
MOVQ 32(R30), R11
|
||||
MOVQ 40(R30), R12
|
||||
MOVQ 48(R30), R23
|
||||
MOVQ 56(R30), R24
|
||||
MOVL 0(R30), R26
|
||||
|
||||
ADDQ $64, R30
|
||||
RET /* back to main sequence */
|
||||
|
||||
TEXT _divq(SB), NOPROF, $-8
|
||||
SUBQ $64, R30 /* 5 reg save, 2 parameters, link */
|
||||
MOVQ R26, 0(R30)
|
||||
|
||||
JSR _absargq(SB)
|
||||
JSR _udivmodq(SB)
|
||||
MOVQ 8(R30), R27
|
||||
|
||||
MOVQ 64(R30), R10 /* clean up the sign */
|
||||
MOVQ 72(R30), R11
|
||||
XOR R11, R10
|
||||
BGE R10, div1
|
||||
SUBQ R27, R31, R27
|
||||
div1:
|
||||
|
||||
JSR _retargq(SB)
|
||||
RET /* not executed */
|
||||
|
||||
TEXT _divqu(SB), NOPROF, $-8
|
||||
SUBQ $64, R30 /* 5 reg save, 2 parameters, link */
|
||||
MOVQ R26, 0(R30)
|
||||
|
||||
JSR _unsargq(SB)
|
||||
JSR _udivmodq(SB)
|
||||
MOVQ 8(R30), R27
|
||||
|
||||
JSR _retargq(SB)
|
||||
RET /* not executed */
|
||||
|
||||
TEXT _modq(SB), NOPROF, $-8
|
||||
SUBQ $64, R30 /* 5 reg save, 2 parameters, link */
|
||||
MOVQ R26, 0(R30)
|
||||
|
||||
JSR _absargq(SB)
|
||||
JSR _udivmodq(SB)
|
||||
MOVQ 16(R30), R27
|
||||
|
||||
MOVQ 64(R30), R10 /* clean up the sign */
|
||||
BGE R10, div2
|
||||
SUBQ R27, R31, R27
|
||||
div2:
|
||||
|
||||
JSR _retargq(SB)
|
||||
RET /* not executed */
|
||||
|
||||
TEXT _modqu(SB), NOPROF, $-8
|
||||
SUBQ $64, R30 /* 5 reg save, 2 parameters, link */
|
||||
MOVQ R26, 0(R30)
|
||||
|
||||
JSR _unsargq(SB)
|
||||
JSR _udivmodq(SB)
|
||||
MOVQ 16(R30), R27
|
||||
|
||||
JSR _retargq(SB)
|
||||
RET /* not executed */
|
||||
|
|
@ -1,33 +0,0 @@
|
|||
TEXT getfsr(SB), $8
|
||||
TRAPB
|
||||
MOVT FPCR, F0
|
||||
TRAPB
|
||||
MOVT F0, tmp-8(SP)
|
||||
MOVL tmp-4(SP), R0
|
||||
RET
|
||||
|
||||
TEXT setfsr(SB), $8
|
||||
SLLQ $32, R0
|
||||
MOVQ R0, tmp-8(SP)
|
||||
MOVT tmp-8(SP), F0
|
||||
TRAPB
|
||||
MOVT F0, FPCR
|
||||
TRAPB
|
||||
RET
|
||||
|
||||
TEXT getfcr(SB), $8
|
||||
TRAPB
|
||||
MOVT FPCR, F0
|
||||
TRAPB
|
||||
MOVT F0, tmp-8(SP)
|
||||
MOVL tmp-4(SP), R0
|
||||
RET
|
||||
|
||||
TEXT setfcr(SB), $8
|
||||
SLLQ $32, R0
|
||||
MOVQ R0, tmp-8(SP)
|
||||
MOVT tmp-8(SP), F0
|
||||
TRAPB
|
||||
MOVT F0, FPCR
|
||||
TRAPB
|
||||
RET
|
|
@ -1,26 +0,0 @@
|
|||
#define _LOCK_EXTENSION
|
||||
#include "../plan9/sys9.h"
|
||||
#include <lock.h>
|
||||
|
||||
int tas(int*);
|
||||
|
||||
void
|
||||
lock(Lock *lk)
|
||||
{
|
||||
while(tas(&lk->val))
|
||||
_SLEEP(0);
|
||||
}
|
||||
|
||||
int
|
||||
canlock(Lock *lk)
|
||||
{
|
||||
if(tas(&lk->val))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
unlock(Lock *lk)
|
||||
{
|
||||
lk->val = 0;
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
#define NPRIVATES 16
|
||||
|
||||
GLOBL _tos(SB), $4
|
||||
GLOBL _errnoloc(SB), $4
|
||||
GLOBL _plan9err(SB), $4
|
||||
GLOBL _privates(SB), $4
|
||||
GLOBL _nprivates(SB), $4
|
||||
|
||||
TEXT _main(SB), 1, $(20+4+128+NPRIVATES*4)
|
||||
MOVQ $setSB(SB), R29
|
||||
|
||||
/* _tos = arg */
|
||||
MOVL R0, _tos(SB)
|
||||
|
||||
MOVL $20(R30), R1
|
||||
MOVL R1, _errnoloc(SB)
|
||||
ADDL $4, R1
|
||||
MOVL R1, _plan9err(SB)
|
||||
ADDL $128, R1
|
||||
MOVL R1, _privates(SB)
|
||||
MOVQ $NPRIVATES, R1
|
||||
MOVL R1, _nprivates(SB)
|
||||
|
||||
JSR _envsetup(SB)
|
||||
|
||||
/* main(argc, argv, environ); */
|
||||
MOVL inargc-4(FP), R0
|
||||
MOVL $inargv+0(FP), R1
|
||||
MOVL environ(SB), R2
|
||||
MOVL R0, 8(R30)
|
||||
MOVL R1, 12(R30)
|
||||
MOVL R2, 16(R30)
|
||||
JSR main(SB)
|
||||
loop:
|
||||
MOVL R0, 8(R30)
|
||||
JSR exit(SB)
|
||||
MOVQ $_divq(SB), R31 /* force loading of divq */
|
||||
MOVQ $_divl(SB), R31 /* force loading of divl */
|
||||
JMP loop
|
|
@ -1,56 +0,0 @@
|
|||
#define NPRIVATES 16
|
||||
|
||||
GLOBL _tos(SB), $4
|
||||
GLOBL _errnoloc(SB), $4
|
||||
GLOBL _plan9err(SB), $4
|
||||
GLOBL _privates(SB), $4
|
||||
GLOBL _nprivates(SB), $4
|
||||
|
||||
TEXT _mainp(SB), 1, $(20+4+128+NPRIVATES*4)
|
||||
MOVQ $setSB(SB), R29
|
||||
|
||||
/* _tos = arg */
|
||||
MOVL R0, _tos(SB)
|
||||
|
||||
MOVL $20(R30), R1
|
||||
MOVL R1, _errnoloc(SB)
|
||||
ADDL $4, R1
|
||||
MOVL R1, _plan9err(SB)
|
||||
ADDL $128, R1
|
||||
MOVL R1, _privates(SB)
|
||||
MOVQ $NPRIVATES, R1
|
||||
MOVL R1, _nprivates(SB)
|
||||
|
||||
/* _profmain(); */
|
||||
JSR _profmain(SB)
|
||||
|
||||
/* _tos->prof.pp = _tos->prof.next; */
|
||||
MOVL _tos+0(SB), R1
|
||||
MOVL 4(R1), R2
|
||||
MOVL R2, 0(R1)
|
||||
|
||||
JSR _envsetup(SB)
|
||||
|
||||
/* main(argc, argv, environ); */
|
||||
MOVL inargc-4(FP), R0
|
||||
MOVL $inargv+0(FP), R1
|
||||
MOVL environ(SB), R2
|
||||
MOVL R0, 8(R30)
|
||||
MOVL R1, 12(R30)
|
||||
MOVL R2, 16(R30)
|
||||
JSR main(SB)
|
||||
loop:
|
||||
MOVL R0, 8(R30)
|
||||
JSR exit(SB)
|
||||
MOVQ $_divq(SB), R31 /* force loading of divq */
|
||||
MOVQ $_divl(SB), R31 /* force loading of divl */
|
||||
MOVQ $_profin(SB), R31 /* force loading of profile */
|
||||
JMP loop
|
||||
|
||||
TEXT _saveret(SB), 1, $0
|
||||
TEXT _savearg(SB), 1, $0
|
||||
RET
|
||||
|
||||
TEXT _callpc(SB), 1, $0
|
||||
MOVL argp-8(FP), R0
|
||||
RET
|
|
@ -1,7 +0,0 @@
|
|||
#include <string.h>
|
||||
|
||||
void*
|
||||
memcpy(void *a1, const void *a2, size_t n)
|
||||
{
|
||||
return memmove(a1, a2, n);
|
||||
}
|
|
@ -1,197 +0,0 @@
|
|||
#define QUAD 8
|
||||
#define ALIGN 64
|
||||
#define BLOCK 64
|
||||
|
||||
TEXT memmove(SB), $0
|
||||
MOVL from+4(FP), R7
|
||||
MOVL n+8(FP), R10
|
||||
MOVQ R0, R6
|
||||
|
||||
CMPUGE R7, R0, R5
|
||||
BNE R5, _forward
|
||||
|
||||
MOVQ R6, R8 /* end to address */
|
||||
ADDL R10, R6, R6 /* to+n */
|
||||
ADDL R10, R7, R7 /* from+n */
|
||||
|
||||
CMPUGE $ALIGN, R10, R1 /* need at least ALIGN bytes */
|
||||
BNE R1, _b1tail
|
||||
|
||||
_balign:
|
||||
AND $(ALIGN-1), R6, R1
|
||||
BEQ R1, _baligned
|
||||
|
||||
MOVBU -1(R7), R2
|
||||
ADDL $-1, R6, R6
|
||||
MOVB R2, (R6)
|
||||
ADDL $-1, R7, R7
|
||||
JMP _balign
|
||||
|
||||
_baligned:
|
||||
AND $(QUAD-1), R7, R1 /* is the source quad-aligned */
|
||||
BNE R1, _bunaligned
|
||||
|
||||
ADDL $(BLOCK-1), R8, R9
|
||||
_bblock:
|
||||
CMPUGE R9, R6, R1
|
||||
BNE R1, _b8tail
|
||||
|
||||
MOVQ -64(R7), R22
|
||||
MOVQ -56(R7), R23
|
||||
MOVQ -48(R7), R24
|
||||
MOVQ -40(R7), R25
|
||||
MOVQ -32(R7), R2
|
||||
MOVQ -24(R7), R3
|
||||
MOVQ -16(R7), R4
|
||||
MOVQ -8(R7), R5
|
||||
|
||||
SUBL $64, R6, R6
|
||||
SUBL $64, R7, R7
|
||||
|
||||
MOVQ R22, (R6)
|
||||
MOVQ R23, 8(R6)
|
||||
MOVQ R24, 16(R6)
|
||||
MOVQ R25, 24(R6)
|
||||
MOVQ R2, 32(R6)
|
||||
MOVQ R3, 40(R6)
|
||||
MOVQ R4, 48(R6)
|
||||
MOVQ R5, 56(R6)
|
||||
JMP _bblock
|
||||
|
||||
_b8tail:
|
||||
ADDL $(QUAD-1), R8, R9
|
||||
_b8block:
|
||||
CMPUGE R9, R6, R1
|
||||
BNE R1, _b1tail
|
||||
|
||||
MOVQ -8(R7), R2
|
||||
SUBL $8, R6
|
||||
MOVQ R2, (R6)
|
||||
SUBL $8, R7
|
||||
JMP _b8block
|
||||
|
||||
_b1tail:
|
||||
CMPUGE R8, R6, R1
|
||||
BNE R1, _ret
|
||||
|
||||
MOVBU -1(R7), R2
|
||||
SUBL $1, R6, R6
|
||||
MOVB R2, (R6)
|
||||
SUBL $1, R7, R7
|
||||
JMP _b1tail
|
||||
_ret:
|
||||
RET
|
||||
|
||||
_bunaligned:
|
||||
ADDL $(16-1), R8, R9
|
||||
|
||||
_bu8block:
|
||||
CMPUGE R9, R6, R1
|
||||
BNE R1, _b1tail
|
||||
|
||||
MOVQU -16(R7), R4
|
||||
MOVQU -8(R7), R3
|
||||
MOVQU (R7), R2
|
||||
SUBL $16, R6
|
||||
EXTQH R7, R2, R2
|
||||
EXTQL R7, R3, R5
|
||||
OR R5, R2, R11
|
||||
EXTQH R7, R3, R3
|
||||
EXTQL R7, R4, R4
|
||||
OR R3, R4, R13
|
||||
MOVQ R11, 8(R6)
|
||||
MOVQ R13, (R6)
|
||||
SUBL $16, R7
|
||||
JMP _bu8block
|
||||
|
||||
_forward:
|
||||
ADDL R10, R6, R8 /* end to address */
|
||||
|
||||
CMPUGE $ALIGN, R10, R1 /* need at least ALIGN bytes */
|
||||
BNE R1, _f1tail
|
||||
|
||||
_falign:
|
||||
AND $(ALIGN-1), R6, R1
|
||||
BEQ R1, _faligned
|
||||
|
||||
MOVBU (R7), R2
|
||||
ADDL $1, R6, R6
|
||||
ADDL $1, R7, R7
|
||||
MOVB R2, -1(R6)
|
||||
JMP _falign
|
||||
|
||||
_faligned:
|
||||
AND $(QUAD-1), R7, R1 /* is the source quad-aligned */
|
||||
BNE R1, _funaligned
|
||||
|
||||
SUBL $(BLOCK-1), R8, R9
|
||||
_fblock:
|
||||
CMPUGT R9, R6, R1
|
||||
BEQ R1, _f8tail
|
||||
|
||||
MOVQ (R7), R2
|
||||
MOVQ 8(R7), R3
|
||||
MOVQ 16(R7), R4
|
||||
MOVQ 24(R7), R5
|
||||
MOVQ 32(R7), R22
|
||||
MOVQ 40(R7), R23
|
||||
MOVQ 48(R7), R24
|
||||
MOVQ 56(R7), R25
|
||||
|
||||
ADDL $64, R6, R6
|
||||
ADDL $64, R7, R7
|
||||
|
||||
MOVQ R2, -64(R6)
|
||||
MOVQ R3, -56(R6)
|
||||
MOVQ R4, -48(R6)
|
||||
MOVQ R5, -40(R6)
|
||||
MOVQ R22, -32(R6)
|
||||
MOVQ R23, -24(R6)
|
||||
MOVQ R24, -16(R6)
|
||||
MOVQ R25, -8(R6)
|
||||
JMP _fblock
|
||||
|
||||
_f8tail:
|
||||
SUBL $(QUAD-1), R8, R9
|
||||
_f8block:
|
||||
CMPUGT R9, R6, R1
|
||||
BEQ R1, _f1tail
|
||||
|
||||
MOVQ (R7), R2
|
||||
ADDL $8, R6
|
||||
ADDL $8, R7
|
||||
MOVQ R2, -8(R6)
|
||||
JMP _f8block
|
||||
|
||||
_f1tail:
|
||||
CMPUGT R8, R6, R1
|
||||
BEQ R1, _fret
|
||||
MOVBU (R7), R2
|
||||
ADDL $1, R6, R6
|
||||
ADDL $1, R7, R7
|
||||
MOVB R2, -1(R6)
|
||||
JMP _f1tail
|
||||
|
||||
_fret:
|
||||
RET
|
||||
|
||||
_funaligned:
|
||||
SUBL $(16-1), R8, R9
|
||||
_fu8block:
|
||||
CMPUGT R9, R6, R1
|
||||
BEQ R1, _f1tail
|
||||
|
||||
MOVQU (R7), R2
|
||||
MOVQU 8(R7), R3
|
||||
MOVQU 16(R7), R4
|
||||
EXTQL R7, R2, R2
|
||||
EXTQH R7, R3, R5
|
||||
OR R5, R2, R11
|
||||
EXTQL R7, R3, R3
|
||||
MOVQ R11, (R6)
|
||||
EXTQH R7, R4, R4
|
||||
OR R3, R4, R11
|
||||
MOVQ R11, 8(R6)
|
||||
ADDL $16, R6
|
||||
ADDL $16, R7
|
||||
JMP _fu8block
|
|
@ -1,61 +0,0 @@
|
|||
TEXT memset(SB), $0
|
||||
MOVL R0, R6
|
||||
MOVBU data+4(FP), R2
|
||||
MOVL n+8(FP), R10
|
||||
|
||||
ADDL R10, R0, R8
|
||||
|
||||
CMPUGE $8, R10, R1 /* need at least 8 bytes */
|
||||
BNE R1, _1loop
|
||||
|
||||
SLLQ $8, R2, R1 /* replicate the byte */
|
||||
OR R1, R2
|
||||
SLLQ $16, R2, R1
|
||||
OR R1, R2
|
||||
SLLQ $32, R2, R1
|
||||
OR R1, R2
|
||||
|
||||
_align:
|
||||
AND $(8-1), R6, R1
|
||||
BEQ R1, _aligned
|
||||
|
||||
MOVB R2, (R6)
|
||||
ADDL $1, R6, R6
|
||||
JMP _align
|
||||
|
||||
_aligned:
|
||||
SUBL $(64-1), R8, R9 /* end pointer minus slop */
|
||||
_64loop:
|
||||
CMPUGT R9, R6, R1
|
||||
BEQ R1, _8tail
|
||||
|
||||
MOVQ R2, (R6)
|
||||
MOVQ R2, 8(R6)
|
||||
MOVQ R2, 16(R6)
|
||||
MOVQ R2, 24(R6)
|
||||
MOVQ R2, 32(R6)
|
||||
MOVQ R2, 40(R6)
|
||||
MOVQ R2, 48(R6)
|
||||
MOVQ R2, 56(R6)
|
||||
ADDL $64, R6, R6
|
||||
JMP _64loop
|
||||
|
||||
_8tail:
|
||||
SUBL $(8-1), R8, R9
|
||||
_8loop:
|
||||
CMPUGT R9, R6, R1
|
||||
BEQ R1, _1loop
|
||||
|
||||
MOVQ R2, (R6)
|
||||
ADDL $8, R6
|
||||
JMP _8loop
|
||||
|
||||
_1loop:
|
||||
CMPUGT R8, R6, R1
|
||||
BEQ R1, _ret
|
||||
MOVB R2, (R6)
|
||||
ADDL $1, R6
|
||||
JMP _1loop
|
||||
|
||||
_ret:
|
||||
RET
|
|
@ -1,23 +0,0 @@
|
|||
APE=/sys/src/ape
|
||||
<$APE/config
|
||||
LIB=/$objtype/lib/ape/libap.a
|
||||
OFILES=\
|
||||
_seek.$O\
|
||||
cycles.$O\
|
||||
divl.$O\
|
||||
divq.$O\
|
||||
getfcr.$O\
|
||||
lock.$O\
|
||||
main9.$O\
|
||||
main9p.$O\
|
||||
memcpy.$O\
|
||||
memmove.$O\
|
||||
memset.$O\
|
||||
notetramp.$O\
|
||||
setjmp.$O\
|
||||
tas.$O\
|
||||
|
||||
</sys/src/cmd/mksyslib
|
||||
|
||||
CFLAGS=-c -D_POSIX_SOURCE -D_PLAN9_SOURCE
|
||||
|
|
@ -1,72 +0,0 @@
|
|||
#include "../plan9/lib.h"
|
||||
#include "../plan9/sys9.h"
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
/* A stack to hold pcs when signals nest */
|
||||
#define MAXSIGSTACK 20
|
||||
typedef struct Pcstack Pcstack;
|
||||
static struct Pcstack {
|
||||
int sig;
|
||||
void (*hdlr)(int, char*, Ureg*);
|
||||
unsigned long restorepc;
|
||||
Ureg *u;
|
||||
} pcstack[MAXSIGSTACK];
|
||||
static int nstack = 0;
|
||||
|
||||
static void notecont(Ureg*, char*);
|
||||
|
||||
void
|
||||
_notetramp(int sig, void (*hdlr)(int, char*, Ureg*), Ureg *u)
|
||||
{
|
||||
Pcstack *p;
|
||||
|
||||
if(nstack >= MAXSIGSTACK)
|
||||
_NOTED(1); /* nesting too deep; just do system default */
|
||||
p = &pcstack[nstack];
|
||||
p->restorepc = u->pc;
|
||||
p->sig = sig;
|
||||
p->hdlr = hdlr;
|
||||
p->u = u;
|
||||
nstack++;
|
||||
u->pc = (unsigned long) notecont;
|
||||
_NOTED(2); /* NSAVE: clear note but hold state */
|
||||
}
|
||||
|
||||
static void
|
||||
notecont(Ureg *u, char *s)
|
||||
{
|
||||
Pcstack *p;
|
||||
void(*f)(int, char*, Ureg*);
|
||||
|
||||
p = &pcstack[nstack-1];
|
||||
f = p->hdlr;
|
||||
u->pc = p->restorepc;
|
||||
nstack--;
|
||||
(*f)(p->sig, s, u);
|
||||
_NOTED(3); /* NRSTR */
|
||||
}
|
||||
|
||||
#define JMPBUFPC 1
|
||||
#define JMPBUFSP 0
|
||||
|
||||
extern sigset_t _psigblocked;
|
||||
|
||||
void
|
||||
siglongjmp(sigjmp_buf j, int ret)
|
||||
{
|
||||
struct Ureg *u;
|
||||
|
||||
if(j[0])
|
||||
_psigblocked = j[1];
|
||||
if(nstack == 0 || pcstack[nstack-1].u->sp > j[2+JMPBUFSP])
|
||||
longjmp(j+2, ret);
|
||||
u = pcstack[nstack-1].u;
|
||||
nstack--;
|
||||
u->r0 = ret;
|
||||
if(ret == 0)
|
||||
u->r0 = 1;
|
||||
u->pc = j[2+JMPBUFPC];
|
||||
u->sp = j[2+JMPBUFSP];
|
||||
_NOTED(3); /* NRSTR */
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
TEXT setjmp(SB), 1, $-8
|
||||
MOVL R30, (R0)
|
||||
MOVL R26, 4(R0)
|
||||
MOVQ $0, R0
|
||||
RET
|
||||
|
||||
TEXT sigsetjmp(SB), 1, $-8
|
||||
MOVL savemask+4(FP), R3
|
||||
MOVL R3, 0(R0)
|
||||
MOVL $_psigblocked(SB), R3
|
||||
MOVL R3, 4(R0)
|
||||
MOVL R30, 8(R0)
|
||||
MOVL R26, 12(R0)
|
||||
MOVQ $0, R0
|
||||
RET
|
||||
|
||||
TEXT longjmp(SB), 1, $-8
|
||||
MOVL r+4(FP), R3
|
||||
BNE R3, ok /* ansi: "longjmp(0) => longjmp(1)" */
|
||||
MOVQ $1, R3 /* bless their pointed heads */
|
||||
ok: MOVL (R0), R30
|
||||
MOVL 4(R0), R26
|
||||
MOVL R3, R0
|
||||
RET
|
|
@ -1,10 +0,0 @@
|
|||
TEXT tas(SB), $-8
|
||||
MOVQ R0, R1 /* l */
|
||||
tas1:
|
||||
MOVLL (R1), R0 /* l->key */
|
||||
BNE R0, tas2
|
||||
MOVQ $1, R2
|
||||
MOVLC R2, (R1) /* l->key = 1 */
|
||||
BEQ R2, tas1 /* write failed, try again? */
|
||||
tas2:
|
||||
RET
|
|
@ -1,15 +0,0 @@
|
|||
APE=/sys/src/ape
|
||||
<$APE/config
|
||||
|
||||
LIB=/$objtype/lib/ape/libmp.a
|
||||
|
||||
HFILES=\
|
||||
/sys/include/ape/mp.h\
|
||||
../../../../libmp/port/dat.h
|
||||
|
||||
OFILES=\
|
||||
|
||||
UPDATE=mkfile\
|
||||
$HFILES\
|
||||
|
||||
</sys/src/cmd/mksyslib
|
|
@ -1,15 +0,0 @@
|
|||
APE=/sys/src/ape
|
||||
<$APE/config
|
||||
|
||||
LIB=/$objtype/lib/ape/libsec.a
|
||||
|
||||
OFILES= \
|
||||
|
||||
HFILES=/sys/include/ape/libsec.h
|
||||
|
||||
UPDATE=mkfile
|
||||
|
||||
</sys/src/cmd/mksyslib
|
||||
|
||||
%.$O: /sys/src/libsec/$objtype/%.s
|
||||
$AS $AFLAGS /sys/src/libsec/$objtype/$stem.s
|
|
@ -1,556 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
|
||||
#include "ip.h"
|
||||
|
||||
uchar broadcast[Eaddrlen] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
};
|
||||
|
||||
static ushort tftpport = 5000;
|
||||
static int Id = 1;
|
||||
static Netaddr myaddr;
|
||||
static Netaddr server;
|
||||
|
||||
typedef struct {
|
||||
uchar header[4];
|
||||
uchar data[Segsize];
|
||||
} Tftp;
|
||||
static Tftp tftpb;
|
||||
|
||||
int
|
||||
etherrxpkt(int ctlrno, Etherpkt *pkt, int timo)
|
||||
{
|
||||
int n;
|
||||
|
||||
for (;;) {
|
||||
n = devread(ctlrno, (uchar*)pkt, sizeof(*pkt), 0);
|
||||
if (n >= 0)
|
||||
return n;
|
||||
if (timo-- < 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ethertxpkt(int ctlrno, Etherpkt *pkt, int len, int timo)
|
||||
{
|
||||
USED(timo);
|
||||
return devwrite(ctlrno, (uchar*)pkt, len, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
hnputs(uchar *ptr, ushort val)
|
||||
{
|
||||
ptr[0] = val>>8;
|
||||
ptr[1] = val;
|
||||
}
|
||||
|
||||
static void
|
||||
hnputl(uchar *ptr, ulong val)
|
||||
{
|
||||
ptr[0] = val>>24;
|
||||
ptr[1] = val>>16;
|
||||
ptr[2] = val>>8;
|
||||
ptr[3] = val;
|
||||
}
|
||||
|
||||
static ulong
|
||||
nhgetl(uchar *ptr)
|
||||
{
|
||||
return ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
|
||||
}
|
||||
|
||||
static ushort
|
||||
nhgets(uchar *ptr)
|
||||
{
|
||||
return ((ptr[0]<<8) | ptr[1]);
|
||||
}
|
||||
|
||||
static short endian = 1;
|
||||
static char* aendian = (char*)&endian;
|
||||
#define LITTLE *aendian
|
||||
|
||||
static ushort
|
||||
ptcl_csum(void *a, int len)
|
||||
{
|
||||
uchar *addr;
|
||||
ulong t1, t2;
|
||||
ulong losum, hisum, mdsum, x;
|
||||
|
||||
addr = a;
|
||||
losum = 0;
|
||||
hisum = 0;
|
||||
mdsum = 0;
|
||||
|
||||
x = 0;
|
||||
if((ulong)addr & 1) {
|
||||
if(len) {
|
||||
hisum += addr[0];
|
||||
len--;
|
||||
addr++;
|
||||
}
|
||||
x = 1;
|
||||
}
|
||||
while(len >= 16) {
|
||||
t1 = *(ushort*)(addr+0);
|
||||
t2 = *(ushort*)(addr+2); mdsum += t1;
|
||||
t1 = *(ushort*)(addr+4); mdsum += t2;
|
||||
t2 = *(ushort*)(addr+6); mdsum += t1;
|
||||
t1 = *(ushort*)(addr+8); mdsum += t2;
|
||||
t2 = *(ushort*)(addr+10); mdsum += t1;
|
||||
t1 = *(ushort*)(addr+12); mdsum += t2;
|
||||
t2 = *(ushort*)(addr+14); mdsum += t1;
|
||||
mdsum += t2;
|
||||
len -= 16;
|
||||
addr += 16;
|
||||
}
|
||||
while(len >= 2) {
|
||||
mdsum += *(ushort*)addr;
|
||||
len -= 2;
|
||||
addr += 2;
|
||||
}
|
||||
if(x) {
|
||||
if(len)
|
||||
losum += addr[0];
|
||||
if(LITTLE)
|
||||
losum += mdsum;
|
||||
else
|
||||
hisum += mdsum;
|
||||
} else {
|
||||
if(len)
|
||||
hisum += addr[0];
|
||||
if(LITTLE)
|
||||
hisum += mdsum;
|
||||
else
|
||||
losum += mdsum;
|
||||
}
|
||||
|
||||
losum += hisum >> 8;
|
||||
losum += (hisum & 0xff) << 8;
|
||||
while(hisum = losum>>16)
|
||||
losum = hisum + (losum & 0xffff);
|
||||
|
||||
return ~losum;
|
||||
}
|
||||
|
||||
static ushort
|
||||
ip_csum(uchar *addr)
|
||||
{
|
||||
int len;
|
||||
ulong sum = 0;
|
||||
|
||||
len = (addr[0]&0xf)<<2;
|
||||
|
||||
while(len > 0) {
|
||||
sum += addr[0]<<8 | addr[1] ;
|
||||
len -= 2;
|
||||
addr += 2;
|
||||
}
|
||||
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
sum = (sum & 0xffff) + (sum >> 16);
|
||||
return (sum^0xffff);
|
||||
}
|
||||
|
||||
static void
|
||||
udpsend(int ctlrno, Netaddr *a, void *data, int dlen)
|
||||
{
|
||||
Udphdr *uh;
|
||||
Etherhdr *ip;
|
||||
Etherpkt pkt;
|
||||
int len, ptcllen;
|
||||
|
||||
|
||||
uh = (Udphdr*)&pkt;
|
||||
|
||||
memset(uh, 0, sizeof(Etherpkt));
|
||||
memmove(uh->udpcksum+sizeof(uh->udpcksum), data, dlen);
|
||||
|
||||
/*
|
||||
* UDP portion
|
||||
*/
|
||||
ptcllen = dlen + (UDP_HDRSIZE-UDP_PHDRSIZE);
|
||||
uh->ttl = 0;
|
||||
uh->udpproto = IP_UDPPROTO;
|
||||
uh->frag[0] = 0;
|
||||
uh->frag[1] = 0;
|
||||
hnputs(uh->udpplen, ptcllen);
|
||||
hnputl(uh->udpsrc, myaddr.ip);
|
||||
hnputs(uh->udpsport, myaddr.port);
|
||||
hnputl(uh->udpdst, a->ip);
|
||||
hnputs(uh->udpdport, a->port);
|
||||
hnputs(uh->udplen, ptcllen);
|
||||
uh->udpcksum[0] = 0;
|
||||
uh->udpcksum[1] = 0;
|
||||
dlen = (dlen+1)&~1;
|
||||
hnputs(uh->udpcksum, ptcl_csum(&uh->ttl, dlen+UDP_HDRSIZE));
|
||||
|
||||
/*
|
||||
* IP portion
|
||||
*/
|
||||
ip = (Etherhdr*)&pkt;
|
||||
len = UDP_EHSIZE+UDP_HDRSIZE+dlen; /* non-descriptive names */
|
||||
ip->vihl = IP_VER|IP_HLEN;
|
||||
ip->tos = 0;
|
||||
ip->ttl = 255;
|
||||
hnputs(ip->length, len-ETHER_HDR);
|
||||
hnputs(ip->id, Id++);
|
||||
ip->frag[0] = 0;
|
||||
ip->frag[1] = 0;
|
||||
ip->cksum[0] = 0;
|
||||
ip->cksum[1] = 0;
|
||||
hnputs(ip->cksum, ip_csum(&ip->vihl));
|
||||
|
||||
/*
|
||||
* Ethernet MAC portion
|
||||
*/
|
||||
hnputs(ip->type, ET_IP);
|
||||
memmove(ip->d, a->ea, sizeof(ip->d));
|
||||
|
||||
ethertxpkt(ctlrno, &pkt, len, Timeout);
|
||||
}
|
||||
|
||||
static void
|
||||
nak(int ctlrno, Netaddr *a, int code, char *msg, int report)
|
||||
{
|
||||
int n;
|
||||
char buf[128];
|
||||
|
||||
buf[0] = 0;
|
||||
buf[1] = Tftp_ERROR;
|
||||
buf[2] = 0;
|
||||
buf[3] = code;
|
||||
strcpy(buf+4, msg);
|
||||
n = strlen(msg) + 4 + 1;
|
||||
udpsend(ctlrno, a, buf, n);
|
||||
if(report)
|
||||
print("\ntftp: error(%d): %s\n", code, msg);
|
||||
}
|
||||
|
||||
static int
|
||||
udprecv(int ctlrno, Netaddr *a, void *data, int dlen)
|
||||
{
|
||||
int n, len;
|
||||
ushort csm;
|
||||
Udphdr *h;
|
||||
ulong addr, timo;
|
||||
Etherpkt pkt;
|
||||
static int rxactive;
|
||||
|
||||
if(rxactive == 0)
|
||||
timo = 1000;
|
||||
else
|
||||
timo = Timeout;
|
||||
timo += msec();
|
||||
while(timo > msec()){
|
||||
n = etherrxpkt(ctlrno, &pkt, timo-msec());
|
||||
if(n <= 0)
|
||||
continue;
|
||||
|
||||
h = (Udphdr*)&pkt;
|
||||
if(nhgets(h->type) != ET_IP)
|
||||
continue;
|
||||
|
||||
if(ip_csum(&h->vihl)) {
|
||||
print("ip chksum error\n");
|
||||
continue;
|
||||
}
|
||||
if(h->vihl != (IP_VER|IP_HLEN)) {
|
||||
print("ip bad vers/hlen\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(h->udpproto != IP_UDPPROTO)
|
||||
continue;
|
||||
|
||||
h->ttl = 0;
|
||||
len = nhgets(h->udplen);
|
||||
hnputs(h->udpplen, len);
|
||||
|
||||
if(nhgets(h->udpcksum)) {
|
||||
csm = ptcl_csum(&h->ttl, len+UDP_PHDRSIZE);
|
||||
if(csm != 0) {
|
||||
print("udp chksum error csum #%4lux len %d\n", csm, n);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(a->port != 0 && nhgets(h->udpsport) != a->port)
|
||||
continue;
|
||||
if(myaddr.port != 0 && nhgets(h->udpdport) != myaddr.port)
|
||||
continue;
|
||||
|
||||
addr = nhgetl(h->udpsrc);
|
||||
if(a->ip != Bcastip && addr != a->ip)
|
||||
continue;
|
||||
|
||||
len -= UDP_HDRSIZE-UDP_PHDRSIZE;
|
||||
if(len > dlen) {
|
||||
print("udp: packet too big\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
memmove(data, h->udpcksum+sizeof(h->udpcksum), len);
|
||||
a->ip = addr;
|
||||
a->port = nhgets(h->udpsport);
|
||||
memmove(a->ea, pkt.s, sizeof(a->ea));
|
||||
|
||||
rxactive = 1;
|
||||
return len;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tftpblockno;
|
||||
|
||||
static int
|
||||
tftpopen(int ctlrno, Netaddr *a, char *name, Tftp *tftp)
|
||||
{
|
||||
int i, len, rlen;
|
||||
char buf[Segsize+2];
|
||||
|
||||
buf[0] = 0;
|
||||
buf[1] = Tftp_READ;
|
||||
len = sprint(buf+2, "%s", name) + 2;
|
||||
len += sprint(buf+len+1, "octet") + 2;
|
||||
|
||||
for(i = 0; i < 5; i++){
|
||||
udpsend(ctlrno, a, buf, len);
|
||||
a->port = 0;
|
||||
if((rlen = udprecv(ctlrno, a, tftp, sizeof(Tftp))) < sizeof(tftp->header))
|
||||
continue;
|
||||
|
||||
switch((tftp->header[0]<<8)|tftp->header[1]){
|
||||
|
||||
case Tftp_ERROR:
|
||||
print("tftpopen: error (%d): %s\n",
|
||||
(tftp->header[2]<<8)|tftp->header[3], tftp->data);
|
||||
return -1;
|
||||
|
||||
case Tftp_DATA:
|
||||
tftpblockno = 1;
|
||||
len = (tftp->header[2]<<8)|tftp->header[3];
|
||||
if(len != tftpblockno){
|
||||
print("tftpopen: block error: %d\n", len);
|
||||
nak(ctlrno, a, 1, "block error", 0);
|
||||
return -1;
|
||||
}
|
||||
return rlen-sizeof(tftp->header);
|
||||
}
|
||||
}
|
||||
|
||||
print("tftpopen: failed to connect to server\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
tftpread(int ctlrno, Netaddr *a, Tftp *tftp, int dlen)
|
||||
{
|
||||
int blockno, len;
|
||||
uchar buf[4];
|
||||
|
||||
buf[0] = 0;
|
||||
buf[1] = Tftp_ACK;
|
||||
buf[2] = tftpblockno>>8;
|
||||
buf[3] = tftpblockno;
|
||||
tftpblockno++;
|
||||
|
||||
dlen += sizeof(tftp->header);
|
||||
|
||||
buggery:
|
||||
udpsend(ctlrno, a, buf, sizeof(buf));
|
||||
|
||||
if((len = udprecv(ctlrno, a, tftp, dlen)) != dlen){
|
||||
print("tftpread: %d != %d\n", len, dlen);
|
||||
nak(ctlrno, a, 2, "short read", 0);
|
||||
}
|
||||
|
||||
blockno = (tftp->header[2]<<8)|tftp->header[3];
|
||||
if(blockno != tftpblockno){
|
||||
print("tftpread: block error: %d, expected %d\n", blockno, tftpblockno);
|
||||
|
||||
if(blockno == tftpblockno-1)
|
||||
goto buggery;
|
||||
nak(ctlrno, a, 1, "block error", 0);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return len-sizeof(tftp->header);
|
||||
}
|
||||
|
||||
// #define BOOT_MAGIC L_MAGIC
|
||||
#define BOOT_MAGIC 0x0700e0c3
|
||||
|
||||
void
|
||||
getether(char *dev, uchar *ea)
|
||||
{
|
||||
int i;
|
||||
char *p;
|
||||
|
||||
p = dev;
|
||||
for (i = 0; i < 8; i++) {
|
||||
p = strchr(p, ' ');
|
||||
if (p == 0)
|
||||
panic("no ether addr");
|
||||
p++;
|
||||
}
|
||||
for (i = 0; i < 6; i++) {
|
||||
ea[i] = strtoul(p, &p, 16);
|
||||
if (*p != (i == 5 ? ' ' : '-'))
|
||||
panic("bad ether addr");
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
static char inibuf[BOOTARGSLEN];
|
||||
|
||||
int
|
||||
bootp(char *dev)
|
||||
{
|
||||
Bootp req, rep;
|
||||
int i, fd, dlen, segsize, text, data, bss, total;
|
||||
uchar *addr, *p, ea[6];
|
||||
char *cp;
|
||||
ulong entry;
|
||||
Exec *exec;
|
||||
char *filename, confname[32];
|
||||
|
||||
getether(dev, ea);
|
||||
fd = devopen(dev);
|
||||
if (fd < 0)
|
||||
panic("bootp devopen");
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
req.op = Bootrequest;
|
||||
req.htype = 1; /* ethernet */
|
||||
req.hlen = Eaddrlen; /* ethernet */
|
||||
memmove(req.chaddr, ea, Eaddrlen);
|
||||
|
||||
myaddr.ip = 0;
|
||||
myaddr.port = BPportsrc;
|
||||
memmove(myaddr.ea, ea, Eaddrlen);
|
||||
|
||||
for(i = 0; i < 10; i++) {
|
||||
server.ip = Bcastip;
|
||||
server.port = BPportdst;
|
||||
memmove(server.ea, broadcast, sizeof(server.ea));
|
||||
udpsend(fd, &server, &req, sizeof(req));
|
||||
if(udprecv(fd, &server, &rep, sizeof(rep)) <= 0)
|
||||
continue;
|
||||
if(memcmp(req.chaddr, rep.chaddr, Eaddrlen))
|
||||
continue;
|
||||
if(rep.htype != 1 || rep.hlen != Eaddrlen)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
if(i >= 10) {
|
||||
print("bootp timed out\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprint(confname, "/alpha/conf/%d.%d.%d.%d",
|
||||
rep.yiaddr[0],
|
||||
rep.yiaddr[1],
|
||||
rep.yiaddr[2],
|
||||
rep.yiaddr[3]);
|
||||
|
||||
if(rep.sname[0] != '\0')
|
||||
print("%s ", rep.sname);
|
||||
print("(%d.%d.%d.%d!%d): %s...",
|
||||
rep.siaddr[0],
|
||||
rep.siaddr[1],
|
||||
rep.siaddr[2],
|
||||
rep.siaddr[3],
|
||||
server.port,
|
||||
confname);
|
||||
|
||||
myaddr.ip = nhgetl(rep.yiaddr);
|
||||
myaddr.port = tftpport++;
|
||||
server.ip = nhgetl(rep.siaddr);
|
||||
server.port = TFTPport;
|
||||
|
||||
if((dlen = tftpopen(fd, &server, confname, &tftpb)) < 0)
|
||||
return -1;
|
||||
cp = inibuf;
|
||||
while(dlen > 0) {
|
||||
if(cp-inibuf+dlen > BOOTARGSLEN)
|
||||
panic("conf too large");
|
||||
memmove(cp, tftpb.data, dlen);
|
||||
cp += dlen;
|
||||
if(dlen != Segsize)
|
||||
break;
|
||||
if((dlen = tftpread(fd, &server, &tftpb, sizeof(tftpb.data))) < 0)
|
||||
return -1;
|
||||
}
|
||||
*cp = 0;
|
||||
setconf(inibuf);
|
||||
|
||||
filename = "/alpha/9apc";
|
||||
cp = getconf("bootfile");
|
||||
if(cp != nil)
|
||||
filename = cp;
|
||||
|
||||
print("%s\n", filename);
|
||||
myaddr.port = tftpport++;
|
||||
server.port = TFTPport;
|
||||
if((dlen = tftpopen(fd, &server, filename, &tftpb)) < 0)
|
||||
return -1;
|
||||
|
||||
exec = (Exec*)(tftpb.data);
|
||||
if(dlen < sizeof(Exec) || GLLONG(exec->magic) != BOOT_MAGIC){
|
||||
nak(fd, &server, 0, "bad magic number", 1);
|
||||
return -1;
|
||||
}
|
||||
text = GLLONG(exec->text);
|
||||
data = GLLONG(exec->data);
|
||||
bss = GLLONG(exec->bss);
|
||||
total = text+data+bss;
|
||||
entry = GLLONG(exec->entry);
|
||||
if (!validrgn(entry, entry+total))
|
||||
panic("memory range not available: %lux-%lux\n", entry, entry+total);
|
||||
print("%d", text);
|
||||
|
||||
addr = (uchar*)entry;
|
||||
p = tftpb.data+sizeof(Exec);
|
||||
dlen -= sizeof(Exec);
|
||||
segsize = text;
|
||||
for(;;){
|
||||
if(dlen == 0){
|
||||
if((dlen = tftpread(fd, &server, &tftpb, sizeof(tftpb.data))) < 0)
|
||||
return -1;
|
||||
p = tftpb.data;
|
||||
}
|
||||
if(segsize <= dlen)
|
||||
i = segsize;
|
||||
else
|
||||
i = dlen;
|
||||
memmove(addr, p, i);
|
||||
|
||||
addr += i;
|
||||
p += i;
|
||||
segsize -= i;
|
||||
dlen -= i;
|
||||
|
||||
if(segsize <= 0){
|
||||
if(data == 0)
|
||||
break;
|
||||
print("+%d", data);
|
||||
segsize = data;
|
||||
data = 0;
|
||||
// addr = (uchar*)pground((uvlong)addr);
|
||||
}
|
||||
}
|
||||
nak(fd, &server, 3, "ok", 0); /* tftpclose */
|
||||
print("+%d=%d\n", bss, total);
|
||||
print("entry: 0x%lux\n", entry);
|
||||
|
||||
kexec(entry);
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "lib.h"
|
||||
|
||||
static char *confname[MAXCONF];
|
||||
static char *confval[MAXCONF];
|
||||
static int nconf;
|
||||
static char bootargs[BOOTARGSLEN];
|
||||
|
||||
char*
|
||||
getconf(char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nconf; i++)
|
||||
if(strcmp(confname[i], name) == 0)
|
||||
return confval[i];
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
setconf(char *buf)
|
||||
{
|
||||
char *cp, *line[MAXCONF];
|
||||
int i, n;
|
||||
|
||||
/*
|
||||
* Keep a pristine copy.
|
||||
* Should change this to pass the parsed strings
|
||||
* to the booted programme instead of the raw
|
||||
* string, then it only gets done once.
|
||||
*/
|
||||
strcpy(bootargs, buf);
|
||||
/* print("boot: stashing /alpha/conf boot args at 0x%lux\n",
|
||||
bootargs); /* DEBUG */
|
||||
conf.bootargs = bootargs;
|
||||
|
||||
n = getcfields(buf, line, MAXCONF, "\n");
|
||||
for(i = 0; i < n; i++){
|
||||
if(*line[i] == '#')
|
||||
continue;
|
||||
cp = strchr(line[i], '=');
|
||||
if(cp == nil)
|
||||
continue;
|
||||
*cp++ = 0;
|
||||
if(cp - line[i] >= NAMELEN+1)
|
||||
*(line[i]+NAMELEN-1) = 0;
|
||||
confname[nconf] = line[i];
|
||||
confval[nconf] = cp;
|
||||
nconf++;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
getcfields(char* lp, char** fields, int n, char* sep)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; lp && *lp && i < n; i++){
|
||||
while(*lp && strchr(sep, *lp) != 0)
|
||||
*lp++ = 0;
|
||||
if(*lp == 0)
|
||||
break;
|
||||
fields[i] = lp;
|
||||
while(*lp && strchr(sep, *lp) == 0){
|
||||
if(*lp == '\\' && *(lp+1) == '\n')
|
||||
*lp++ = ' ';
|
||||
lp++;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
typedef struct Bank Bank;
|
||||
typedef struct Bootconf Bootconf;
|
||||
|
||||
struct Bootconf
|
||||
{
|
||||
int nbank;
|
||||
Bank *bank;
|
||||
PCB *pcb;
|
||||
uvlong maxphys;
|
||||
char *bootargs;
|
||||
};
|
||||
|
||||
struct Bank
|
||||
{
|
||||
uvlong min;
|
||||
uvlong max;
|
||||
};
|
||||
|
||||
#define BOOTARGSLEN (4096)
|
||||
#define MAXCONF 32
|
|
@ -1,243 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "lib.h"
|
||||
|
||||
enum {
|
||||
/* prom operations */
|
||||
Promop_getc = 1,
|
||||
Promop_puts = 2,
|
||||
Promop_open = 0x10,
|
||||
Promop_close = 0x11,
|
||||
Promop_read = 0x13,
|
||||
Promop_write = 0x14,
|
||||
Promop_getenv = 0x22,
|
||||
|
||||
/* environment variable indices for getenv */
|
||||
/* auto_action might be 1; it looks that way. */
|
||||
Promenv_booted_dev = 4,
|
||||
Promenv_booted_file = 6,
|
||||
Promenv_booted_osflags = 8,
|
||||
Promenv_tty_dev = 0xf,
|
||||
};
|
||||
|
||||
Hwrpb *hwrpb;
|
||||
|
||||
static uvlong dispatchf;
|
||||
static ulong clk2ms;
|
||||
|
||||
void
|
||||
consinit(void)
|
||||
{
|
||||
Procdesc *p;
|
||||
Hwcrb *crb;
|
||||
Hwdsr *dsr;
|
||||
char *s;
|
||||
|
||||
hwrpb = (Hwrpb*)0x10000000;
|
||||
|
||||
crb = (Hwcrb*)((ulong)hwrpb + hwrpb->crboff);
|
||||
p = (Procdesc*)(crb->dispatchva);
|
||||
dispatchf = p->addr;
|
||||
clk2ms = hwrpb->cfreq/1000;
|
||||
|
||||
print("\nAlpha Plan 9 secondary boot\n");
|
||||
if (hwrpb->rev >= 6) {
|
||||
dsr = (Hwdsr*)((ulong)hwrpb + hwrpb->dsroff);
|
||||
s = (char*)dsr + dsr->sysnameoff + 8;
|
||||
print("%s\n", s);
|
||||
}
|
||||
}
|
||||
|
||||
uvlong
|
||||
dispatch(uvlong r16, uvlong r17, uvlong r18, uvlong r19, uvlong r20)
|
||||
{
|
||||
return gendispatch(dispatchf, r16, r17, r18, r19, r20);
|
||||
};
|
||||
|
||||
int
|
||||
devopen(char *s)
|
||||
{
|
||||
vlong ret;
|
||||
int n;
|
||||
|
||||
n = strlen(s);
|
||||
ret = dispatch(0x10, (uvlong)s, n, 0, 0);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
return (int) ret;
|
||||
}
|
||||
|
||||
int
|
||||
devclose(int fd)
|
||||
{
|
||||
vlong ret;
|
||||
|
||||
ret = dispatch(0x11, fd, 0, 0, 0);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
devread(int fd, uchar *buf, int len, int blkno)
|
||||
{
|
||||
vlong ret;
|
||||
|
||||
ret = dispatch(0x13, fd, len, (uvlong)buf, blkno);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
return (int) ret;
|
||||
}
|
||||
|
||||
int
|
||||
devwrite(int fd, uchar *buf, int len, int blkno)
|
||||
{
|
||||
vlong ret;
|
||||
|
||||
ret = dispatch(0x14, fd, len, (uvlong)buf, blkno);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
return (int) ret;
|
||||
}
|
||||
|
||||
void
|
||||
dumpenv(void)
|
||||
{
|
||||
int id, n;
|
||||
static char buf[256];
|
||||
|
||||
/* old upper bound was 0x100, which blows up on my 164LX. 50 works. */
|
||||
for (id = 1; id < 50; id++) {
|
||||
n = dispatch(Promop_getenv, id, (uvlong)buf, sizeof(buf)-1, 0);
|
||||
if (n == 0)
|
||||
continue;
|
||||
if (n < 0) {
|
||||
print("dispatch failed at id %d\n", id);
|
||||
break;
|
||||
}
|
||||
buf[n] = 0;
|
||||
print("env[0x%x]: %s\n", id, buf);
|
||||
}
|
||||
}
|
||||
|
||||
char *
|
||||
getenv(char *name)
|
||||
{
|
||||
int id, n;
|
||||
static char buf[256];
|
||||
|
||||
if (strcmp(name, "booted_dev") == 0)
|
||||
id = Promenv_booted_dev;
|
||||
else
|
||||
return 0;
|
||||
n = dispatch(Promop_getenv, id, (uvlong)buf, sizeof(buf), 0);
|
||||
if (n < 0)
|
||||
return 0;
|
||||
buf[n] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
void
|
||||
putstrn0(char *s, int n)
|
||||
{
|
||||
uvlong ret;
|
||||
int cnt;
|
||||
|
||||
for (;;) {
|
||||
ret = dispatch(2, 0, (uvlong)s, n, 0);
|
||||
cnt = (int) ret;
|
||||
s += cnt;
|
||||
n -= cnt;
|
||||
if (n <= 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
putstrn(char *s, int n)
|
||||
{
|
||||
char *p;
|
||||
|
||||
for (;;) {
|
||||
if (n == 0)
|
||||
return;
|
||||
p = memchr(s, '\n', n);
|
||||
if (p == 0) {
|
||||
putstrn0(s, n);
|
||||
return;
|
||||
}
|
||||
putstrn0(s, p-s);
|
||||
putstrn0("\r\n", 2);
|
||||
n -= p-s+1;
|
||||
s = p+1;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
snprint(char *s, int n, char *fmt, ...)
|
||||
{
|
||||
va_list arg;
|
||||
|
||||
va_start(arg, fmt);
|
||||
n = doprint(s, s+n, fmt, arg) - s;
|
||||
va_end(arg);
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
sprint(char *s, char *fmt, ...)
|
||||
{
|
||||
int n;
|
||||
va_list arg;
|
||||
|
||||
va_start(arg, fmt);
|
||||
n = doprint(s, s+PRINTSIZE, fmt, arg) - s;
|
||||
va_end(arg);
|
||||
return n;
|
||||
}
|
||||
|
||||
int
|
||||
print(char *fmt, ...)
|
||||
{
|
||||
int n;
|
||||
va_list arg;
|
||||
char buf[PRINTSIZE];
|
||||
|
||||
va_start(arg, fmt);
|
||||
n = doprint(buf, buf+sizeof(buf), fmt, arg) - buf;
|
||||
va_end(arg);
|
||||
putstrn(buf, n);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
void
|
||||
panic(char *fmt, ...)
|
||||
{
|
||||
int n;
|
||||
va_list arg;
|
||||
char buf[PRINTSIZE];
|
||||
|
||||
strcpy(buf, "panic: ");
|
||||
va_start(arg, fmt);
|
||||
n = doprint(buf+strlen(buf), buf+sizeof(buf), fmt, arg) - buf;
|
||||
va_end(arg);
|
||||
buf[n] = '\n';
|
||||
putstrn(buf, n+1);
|
||||
firmware();
|
||||
}
|
||||
|
||||
ulong
|
||||
msec(void)
|
||||
{
|
||||
static ulong last, wrap;
|
||||
ulong cnt;
|
||||
|
||||
cnt = pcc_cnt();
|
||||
if (cnt < last)
|
||||
wrap++;
|
||||
last = cnt;
|
||||
return (((uvlong)wrap << 32) + cnt)/clk2ms;
|
||||
}
|
|
@ -1,169 +0,0 @@
|
|||
typedef struct Hwrpb Hwrpb;
|
||||
typedef struct Hwcpu Hwcpu;
|
||||
typedef struct Hwcrb Hwcrb;
|
||||
typedef struct Hwdsr Hwdsr;
|
||||
typedef struct Procdesc Procdesc;
|
||||
typedef struct Memdsc Memdsc;
|
||||
typedef struct Memclust Memclust;
|
||||
typedef struct PCB PCB;
|
||||
|
||||
struct Hwrpb
|
||||
{
|
||||
uvlong phys;
|
||||
uvlong sign;
|
||||
uvlong rev;
|
||||
uvlong size;
|
||||
uvlong cpu0;
|
||||
uvlong by2pg;
|
||||
uvlong pabits;
|
||||
uvlong maxasn;
|
||||
char ssn[16];
|
||||
uvlong systype;
|
||||
uvlong sysvar;
|
||||
uvlong sysrev;
|
||||
uvlong ifreq;
|
||||
uvlong cfreq;
|
||||
uvlong vptb;
|
||||
uvlong resv;
|
||||
uvlong tbhint;
|
||||
uvlong ncpu;
|
||||
uvlong cpulen;
|
||||
uvlong cpuoff;
|
||||
uvlong nctb;
|
||||
uvlong ctblen;
|
||||
uvlong ctboff;
|
||||
uvlong crboff;
|
||||
uvlong memoff;
|
||||
uvlong confoff;
|
||||
uvlong fruoff;
|
||||
uvlong termsaveva;
|
||||
uvlong termsavex;
|
||||
uvlong termrestva;
|
||||
uvlong termrestx;
|
||||
uvlong termresetva;
|
||||
uvlong termresetx;
|
||||
uvlong sysresv;
|
||||
uvlong hardresv;
|
||||
uvlong csum;
|
||||
uvlong rxrdymsk;
|
||||
uvlong txrdymsk;
|
||||
uvlong dsroff; /* rev 6 or higher */
|
||||
};
|
||||
|
||||
extern Hwrpb* hwrpb;
|
||||
|
||||
struct Hwcpu
|
||||
{
|
||||
uvlong hwpcb[16];
|
||||
uvlong state;
|
||||
uvlong palmainlen;
|
||||
uvlong palscratchlen;
|
||||
uvlong palmainpa;
|
||||
uvlong palscratchpa;
|
||||
uvlong palrev;
|
||||
uvlong cputype;
|
||||
uvlong cpuvar;
|
||||
uvlong cpurev;
|
||||
uvlong serial[2];
|
||||
/* more crap ... */
|
||||
};
|
||||
|
||||
struct Hwdsr
|
||||
{
|
||||
vlong smm;
|
||||
uvlong lurtoff;
|
||||
uvlong sysnameoff;
|
||||
};
|
||||
|
||||
struct Hwcrb
|
||||
{
|
||||
uvlong dispatchva;
|
||||
uvlong dispatchpa;
|
||||
uvlong fixupva;
|
||||
uvlong fixuppa;
|
||||
/* more, uninteresting crud */
|
||||
};
|
||||
|
||||
struct Procdesc
|
||||
{
|
||||
uvlong bollocks;
|
||||
uvlong addr;
|
||||
};
|
||||
|
||||
struct Memclust
|
||||
{
|
||||
uvlong pfn;
|
||||
uvlong npages;
|
||||
uvlong ntest;
|
||||
uvlong vabitm;
|
||||
uvlong pabitm;
|
||||
uvlong csumbitm;
|
||||
uvlong usage;
|
||||
};
|
||||
|
||||
struct Memdsc
|
||||
{
|
||||
uvlong csum;
|
||||
uvlong opt;
|
||||
uvlong nclust;
|
||||
Memclust clust[1];
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PRINTSIZE = 256,
|
||||
MB = (1024*1024),
|
||||
};
|
||||
|
||||
#define L_MAGIC ((((4*23)+0)*23)+7)
|
||||
|
||||
typedef struct Exec Exec;
|
||||
struct Exec
|
||||
{
|
||||
uchar magic[4]; /* magic number */
|
||||
uchar text[4]; /* size of text segment */
|
||||
uchar data[4]; /* size of initialized data */
|
||||
uchar bss[4]; /* size of uninitialized data */
|
||||
uchar syms[4]; /* size of symbol table */
|
||||
uchar entry[4]; /* entry point */
|
||||
uchar spsz[4]; /* size of sp/pc offset table */
|
||||
uchar pcsz[4]; /* size of pc/line number table */
|
||||
};
|
||||
|
||||
enum {
|
||||
Eaddrlen = 6,
|
||||
ETHERMINTU = 60, /* minimum transmit size */
|
||||
ETHERMAXTU = 1514, /* maximum transmit size */
|
||||
ETHERHDRSIZE = 14, /* size of an ethernet header */
|
||||
|
||||
MaxEther = 2,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uchar d[Eaddrlen];
|
||||
uchar s[Eaddrlen];
|
||||
uchar type[2];
|
||||
uchar data[1500];
|
||||
uchar crc[4];
|
||||
} Etherpkt;
|
||||
|
||||
/*
|
||||
* Process Control Block, used by OSF/1 PALcode when we switch to it
|
||||
*/
|
||||
struct PCB {
|
||||
uvlong ksp;
|
||||
uvlong usp;
|
||||
uvlong ptbr;
|
||||
ulong asn;
|
||||
ulong pcc;
|
||||
uvlong unique;
|
||||
ulong fen;
|
||||
ulong dummy;
|
||||
uvlong rsrv1;
|
||||
uvlong rsrv2;
|
||||
};
|
||||
|
||||
|
||||
#include "conf.h"
|
||||
|
||||
extern Bootconf conf;
|
|
@ -1,40 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "lib.h"
|
||||
|
||||
uchar pcbpage[64*1024+sizeof(PCB)];
|
||||
PCB *pcb;
|
||||
|
||||
void (*kentry)(Bootconf*);
|
||||
|
||||
void
|
||||
gokernel(void)
|
||||
{
|
||||
(*kentry)(&conf);
|
||||
}
|
||||
|
||||
void
|
||||
kexec(ulong entry)
|
||||
{
|
||||
uvlong pcbb, paltype;
|
||||
|
||||
pcb = (PCB*)(((ulong)pcbpage+0xffff) & ~0xffff); /* page align, even on 64K page Alphas */
|
||||
memset(pcb, 0, sizeof(PCB));
|
||||
pcb->ksp = (uvlong)&entry;
|
||||
pcb->ptbr = getptbr();
|
||||
pcb->fen = 1;
|
||||
conf.pcb = pcb;
|
||||
pcbb = paddr((uvlong)pcb);
|
||||
kentry = (void(*)(Bootconf*))entry;
|
||||
paltype = 2; /* OSF/1 please */
|
||||
switch (swppal(paltype, (uvlong)gokernel, pcbb, hwrpb->vptb, pcb->ksp)) {
|
||||
case 1:
|
||||
panic("unknown PALcode variant");
|
||||
case 2:
|
||||
panic("PALcode variant not loaded");
|
||||
default:
|
||||
panic("weird return status from swppal");
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
uvlong allocate(int);
|
||||
int bootp(char*);
|
||||
void consinit(void);
|
||||
int devopen(char*);
|
||||
int devclose(int);
|
||||
int devread(int, uchar*, int, int);
|
||||
int devwrite(int, uchar*, int, int);
|
||||
uvlong dispatch(uvlong, uvlong, uvlong, uvlong, uvlong);
|
||||
void dumpenv(void);
|
||||
void firmware(void);
|
||||
uvlong gendispatch(uvlong, uvlong, uvlong, uvlong, uvlong, uvlong);
|
||||
int getcfields(char*, char**, int, char*);
|
||||
char* getconf(char*);
|
||||
char* getenv(char*);
|
||||
uvlong getptbr(void);
|
||||
void kexec(ulong);
|
||||
uvlong ldqp(uvlong);
|
||||
void meminit(void);
|
||||
void mmuinit(void);
|
||||
ulong msec(void);
|
||||
uvlong rdv(uvlong);
|
||||
uvlong paddr(uvlong);
|
||||
void panic(char *, ...);
|
||||
ulong pcc_cnt(void);
|
||||
uvlong pground(uvlong);
|
||||
void putstrn(char *, int);
|
||||
void setconf(char*);
|
||||
void stqp(uvlong, uvlong);
|
||||
int swppal(uvlong, uvlong, uvlong, uvlong, uvlong);
|
||||
void tlbflush(void);
|
||||
int validrgn(ulong, ulong);
|
||||
void wrv(uvlong, uvlong);
|
||||
|
||||
#define GSHORT(p) (((p)[1]<<8)|(p)[0])
|
||||
#define GLONG(p) ((GSHORT(p+2)<<16)|GSHORT(p))
|
||||
#define GLSHORT(p) (((p)[0]<<8)|(p)[1])
|
||||
#define GLLONG(p) ((GLSHORT(p)<<16)|GLSHORT(p+2))
|
|
@ -1,98 +0,0 @@
|
|||
typedef struct Udphdr Udphdr;
|
||||
struct Udphdr
|
||||
{
|
||||
uchar d[6]; /* Ethernet destination */
|
||||
uchar s[6]; /* Ethernet source */
|
||||
uchar type[2]; /* Ethernet packet type */
|
||||
|
||||
uchar vihl; /* Version and header length */
|
||||
uchar tos; /* Type of service */
|
||||
uchar length[2]; /* packet length */
|
||||
uchar id[2]; /* Identification */
|
||||
uchar frag[2]; /* Fragment information */
|
||||
|
||||
/* Udp pseudo ip really starts here */
|
||||
uchar ttl;
|
||||
uchar udpproto; /* Protocol */
|
||||
uchar udpplen[2]; /* Header plus data length */
|
||||
uchar udpsrc[4]; /* Ip source */
|
||||
uchar udpdst[4]; /* Ip destination */
|
||||
uchar udpsport[2]; /* Source port */
|
||||
uchar udpdport[2]; /* Destination port */
|
||||
uchar udplen[2]; /* data length */
|
||||
uchar udpcksum[2]; /* Checksum */
|
||||
};
|
||||
|
||||
typedef struct Etherhdr Etherhdr;
|
||||
struct Etherhdr
|
||||
{
|
||||
uchar d[6];
|
||||
uchar s[6];
|
||||
uchar type[2];
|
||||
|
||||
/* Now we have the ip fields */
|
||||
uchar vihl; /* Version and header length */
|
||||
uchar tos; /* Type of service */
|
||||
uchar length[2]; /* packet length */
|
||||
uchar id[2]; /* Identification */
|
||||
uchar frag[2]; /* Fragment information */
|
||||
uchar ttl; /* Time to live */
|
||||
uchar proto; /* Protocol */
|
||||
uchar cksum[2]; /* Header checksum */
|
||||
uchar src[4]; /* Ip source */
|
||||
uchar dst[4]; /* Ip destination */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
IP_VER = 0x40,
|
||||
IP_HLEN = 0x05,
|
||||
UDP_EHSIZE = 22,
|
||||
UDP_PHDRSIZE = 12,
|
||||
UDP_HDRSIZE = 20,
|
||||
ETHER_HDR = 14,
|
||||
IP_UDPPROTO = 17,
|
||||
ET_IP = 0x800,
|
||||
Bcastip = 0xffffffff,
|
||||
BPportsrc = 68,
|
||||
BPportdst = 67,
|
||||
TFTPport = 69,
|
||||
Timeout = 5000, /* milliseconds */
|
||||
Bootrequest = 1,
|
||||
Bootreply = 2,
|
||||
Tftp_READ = 1,
|
||||
Tftp_WRITE = 2,
|
||||
Tftp_DATA = 3,
|
||||
Tftp_ACK = 4,
|
||||
Tftp_ERROR = 5,
|
||||
Segsize = 512,
|
||||
TFTPSZ = Segsize+10,
|
||||
};
|
||||
|
||||
typedef struct Bootp Bootp;
|
||||
struct Bootp
|
||||
{
|
||||
uchar op; /* opcode */
|
||||
uchar htype; /* hardware type */
|
||||
uchar hlen; /* hardware address len */
|
||||
uchar hops; /* hops */
|
||||
uchar xid[4]; /* a random number */
|
||||
uchar secs[2]; /* elapsed snce client started booting */
|
||||
uchar pad[2];
|
||||
uchar ciaddr[4]; /* client IP address (client tells server) */
|
||||
uchar yiaddr[4]; /* client IP address (server tells client) */
|
||||
uchar siaddr[4]; /* server IP address */
|
||||
uchar giaddr[4]; /* gateway IP address */
|
||||
uchar chaddr[16]; /* client hardware address */
|
||||
char sname[64]; /* server host name (optional) */
|
||||
char file[128]; /* boot file name */
|
||||
char vend[128]; /* vendor-specific goo */
|
||||
};
|
||||
|
||||
typedef struct Netaddr Netaddr;
|
||||
struct Netaddr
|
||||
{
|
||||
ulong ip;
|
||||
ushort port;
|
||||
char ea[Eaddrlen];
|
||||
};
|
|
@ -1,101 +0,0 @@
|
|||
#include "mem.h"
|
||||
#include "vmspal.h"
|
||||
|
||||
#define SP R30
|
||||
|
||||
TEXT _main(SB), $-8
|
||||
MOVQ $setSB(SB), R29
|
||||
MOVQ $edata(SB), R1
|
||||
MOVQ $end(SB), R2
|
||||
loop2:
|
||||
MOVQ R31, (R1)
|
||||
ADDQ $8, R1
|
||||
CMPUGT R1, R2, R3
|
||||
BEQ R3, loop2
|
||||
|
||||
JSR main(SB)
|
||||
|
||||
TEXT firmware(SB), $-8
|
||||
CALL_PAL $PALhalt
|
||||
MOVQ $_divq(SB), R31 /* touch _divq etc.; doesn't need to execute */
|
||||
MOVQ $_divl(SB), R31 /* touch _divl etc.; doesn't need to execute */
|
||||
RET
|
||||
|
||||
TEXT mb(SB), $-8
|
||||
MB
|
||||
RET
|
||||
|
||||
TEXT icflush(SB), $-8
|
||||
CALL_PAL $PALimb
|
||||
RET
|
||||
|
||||
TEXT tlbflush(SB), $-8
|
||||
CALL_PAL $PALmtpr_tbia
|
||||
RET
|
||||
|
||||
TEXT gendispatch(SB), $-8
|
||||
MOVQ 8(FP), R16
|
||||
MOVQ 16(FP), R17
|
||||
MOVQ 24(FP), R18
|
||||
MOVQ 32(FP), R19
|
||||
MOVQ 40(FP), R20
|
||||
MOVQ R26, R1
|
||||
JSR (R0)
|
||||
MOVQ R1, R26
|
||||
RET /* 7a bug: should be RET (R1) */
|
||||
|
||||
TEXT rdv(SB), $-8
|
||||
MOVQ (R0), R0
|
||||
RET
|
||||
|
||||
TEXT wrv(SB), $-8
|
||||
MOVQ 8(FP), R1
|
||||
MOVQ R1, (R0)
|
||||
RET
|
||||
|
||||
TEXT ipl(SB), $-8
|
||||
CALL_PAL $PALmfpr_ipl
|
||||
RET
|
||||
|
||||
TEXT mces(SB), $-8
|
||||
CALL_PAL $PALmfpr_mces
|
||||
RET
|
||||
|
||||
TEXT setipl(SB), $-8
|
||||
MOVQ R0, R16
|
||||
CALL_PAL $PALmtpr_ipl
|
||||
RET
|
||||
|
||||
TEXT setmces(SB), $-8
|
||||
MOVQ R0, R16
|
||||
CALL_PAL $PALmtpr_mces
|
||||
RET
|
||||
|
||||
TEXT ldqp(SB), $-8
|
||||
MOVQ R0, R16
|
||||
CALL_PAL $PALldqp
|
||||
RET
|
||||
|
||||
TEXT stqp(SB), $-8
|
||||
MOVQ R0, R16
|
||||
MOVQ 8(FP), R17
|
||||
CALL_PAL $PALstqp
|
||||
RET
|
||||
|
||||
TEXT getptbr(SB), $-8
|
||||
CALL_PAL $PALmfpr_ptbr
|
||||
RET
|
||||
|
||||
TEXT swppal(SB), $-8
|
||||
MOVQ R0, R16 /* which PALcode */
|
||||
MOVQ 8(FP), R17 /* new PC */
|
||||
MOVQ 16(FP), R18 /* PCBB (physical) */
|
||||
MOVQ 24(FP), R19 /* VPTB */
|
||||
MOVQ 32(FP), R20 /* new KSP */
|
||||
CALL_PAL $PALswppal
|
||||
RET
|
||||
|
||||
TEXT pcc_cnt(SB), $-8
|
||||
MOVQ PCC, R1
|
||||
MOVL R1, R0
|
||||
RET
|
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
* functions (possibly) linked in, complete, from libc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* mem routines
|
||||
*/
|
||||
extern void *memccpy(void*, void*, int, long);
|
||||
extern void *memset(void*, int, long);
|
||||
extern int memcmp(void*, void*, long);
|
||||
extern void *memmove(void*, void*, long);
|
||||
extern void *memchr(void*, int, long);
|
||||
|
||||
/*
|
||||
* string routines
|
||||
*/
|
||||
extern char *strcat(char*, char*);
|
||||
extern char *strchr(char*, char);
|
||||
extern int strcmp(char*, char*);
|
||||
extern char *strcpy(char*, char*);
|
||||
extern char *strncat(char*, char*, long);
|
||||
extern char *strncpy(char*, char*, long);
|
||||
extern int strncmp(char*, char*, long);
|
||||
extern long strlen(char*);
|
||||
extern int atoi(char*);
|
||||
|
||||
enum
|
||||
{
|
||||
UTFmax = 3, /* maximum bytes per rune */
|
||||
Runesync = 0x80, /* cannot represent part of a UTF sequence */
|
||||
Runeself = 0x80, /* rune and UTF sequences are the same (<) */
|
||||
Runeerror = 0x80, /* decoding error in UTF */
|
||||
};
|
||||
|
||||
/*
|
||||
* rune routines
|
||||
*/
|
||||
extern int runetochar(char*, Rune*);
|
||||
extern int chartorune(Rune*, char*);
|
||||
extern char* utfrune(char*, long);
|
||||
extern int utflen(char*);
|
||||
|
||||
extern int abs(int);
|
||||
|
||||
/*
|
||||
* print routines
|
||||
*/
|
||||
typedef
|
||||
struct
|
||||
{
|
||||
char* out; /* pointer to next output */
|
||||
char* eout; /* pointer to end */
|
||||
int f1;
|
||||
int f2;
|
||||
int f3;
|
||||
int chr;
|
||||
} Fconv;
|
||||
extern void strconv(char*, Fconv*);
|
||||
extern int numbconv(va_list*, Fconv*);
|
||||
extern char *doprint(char*, char*, char*, va_list);
|
||||
extern int fmtinstall(int, int (*)(va_list*, Fconv*));
|
||||
extern int sprint(char*, char*, ...);
|
||||
extern int snprint(char*, int, char*, ...);
|
||||
extern int print(char*, ...);
|
||||
|
||||
/*
|
||||
* one-of-a-kind
|
||||
*/
|
||||
extern long strtol(char*, char**, int);
|
||||
extern ulong strtoul(char*, char**, int);
|
||||
extern vlong strtovl(char*, char**, int);
|
||||
extern char etext[];
|
||||
extern char edata[];
|
||||
extern char end[];
|
||||
|
||||
/*
|
||||
* Syscall data structures
|
||||
*/
|
||||
#define MORDER 0x0003 /* mask for bits defining order of mounting */
|
||||
#define MREPL 0x0000 /* mount replaces object */
|
||||
#define MBEFORE 0x0001 /* mount goes before others in union directory */
|
||||
#define MAFTER 0x0002 /* mount goes after others in union directory */
|
||||
#define MCREATE 0x0004 /* permit creation in mounted directory */
|
||||
#define MRECOV 0x0008 /* perform recovery if mount channel is lost */
|
||||
#define MCACHE 0x0010 /* cache some data */
|
||||
#define MMASK 0x001F /* all bits on */
|
||||
|
||||
#define OREAD 0 /* open for read */
|
||||
#define OWRITE 1 /* write */
|
||||
#define ORDWR 2 /* read and write */
|
||||
#define OEXEC 3 /* execute, == read but check execute permission */
|
||||
#define OTRUNC 16 /* or'ed in (except for exec), truncate file first */
|
||||
#define OCEXEC 32 /* or'ed in, close on exec */
|
||||
#define ORCLOSE 64 /* or'ed in, remove on close */
|
||||
|
||||
#define NCONT 0 /* continue after note */
|
||||
#define NDFLT 1 /* terminate after note */
|
||||
#define NSAVE 2 /* clear note but hold state */
|
||||
#define NRSTR 3 /* restore saved state */
|
||||
|
||||
typedef struct Qid Qid;
|
||||
typedef struct Dir Dir;
|
||||
typedef struct Waitmsg Waitmsg;
|
||||
|
||||
#define ERRLEN 64
|
||||
#define DIRLEN 116
|
||||
#define NAMELEN 28
|
||||
|
||||
struct Qid
|
||||
{
|
||||
ulong path;
|
||||
ulong vers;
|
||||
};
|
||||
|
||||
struct Dir
|
||||
{
|
||||
char name[NAMELEN];
|
||||
char uid[NAMELEN];
|
||||
char gid[NAMELEN];
|
||||
Qid qid;
|
||||
ulong mode;
|
||||
long atime;
|
||||
long mtime;
|
||||
Length;
|
||||
short type;
|
||||
short dev;
|
||||
};
|
||||
|
||||
struct Waitmsg
|
||||
{
|
||||
char pid[12]; /* of loved one */
|
||||
char time[3*12]; /* of loved one and descendants */
|
||||
char msg[ERRLEN];
|
||||
};
|
|
@ -1,25 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "lib.h"
|
||||
|
||||
Bootconf conf;
|
||||
|
||||
void
|
||||
main(void)
|
||||
{
|
||||
char *dev;
|
||||
|
||||
consinit();
|
||||
meminit();
|
||||
mmuinit();
|
||||
|
||||
dev = getenv("booted_dev");
|
||||
if (dev == 0)
|
||||
panic("get dev name");
|
||||
if (strncmp(dev, "BOOTP", 5) == 0)
|
||||
bootp(dev);
|
||||
else
|
||||
print("boot device %s not supported\n", dev);
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
/*
|
||||
* Memory and machine-specific definitions. Used in C and assembler.
|
||||
*/
|
||||
|
||||
#define BI2BY 8 /* bits per byte */
|
||||
#define BI2WD 32 /* bits per word */
|
||||
#define BY2WD 4 /* bytes per word */
|
||||
#define BY2V 8 /* bytes per vlong */
|
||||
|
||||
#define KZERO 0x80000000
|
||||
|
||||
#define PTEVALID 0xff01
|
||||
#define PTEKVALID 0x1101
|
||||
#define PTEASM 0x0010
|
||||
#define PTEGH(s) ((s)<<5)
|
|
@ -1,108 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "lib.h"
|
||||
|
||||
static int debug;
|
||||
|
||||
enum {
|
||||
Maxbank = 2,
|
||||
};
|
||||
|
||||
Bank bank[Maxbank];
|
||||
int nbank;
|
||||
|
||||
void
|
||||
meminit(void)
|
||||
{
|
||||
Memdsc *mem;
|
||||
Memclust *c;
|
||||
int i;
|
||||
uvlong npage, p0, p1;
|
||||
extern ulong _main[], edata[];
|
||||
|
||||
mem = (Memdsc*)((ulong)hwrpb + hwrpb->memoff);
|
||||
if (debug)
|
||||
print("\nnumber of clusters: %lld\n", mem->nclust);
|
||||
npage = 0;
|
||||
conf.maxphys = 0;
|
||||
for (i = 0; i < mem->nclust; i++) {
|
||||
c = &mem->clust[i];
|
||||
p0 = c->pfn*hwrpb->by2pg;
|
||||
p1 = (c->pfn+c->npages)*hwrpb->by2pg;
|
||||
if (debug) {
|
||||
print("clust%d: %llux-%llux, tested %llud/%llud vabitm %llux usage %llux\n",
|
||||
i, p0, p1, c->ntest, c->npages, c->vabitm, c->usage);
|
||||
if (c->vabitm)
|
||||
print("\tfirst 64 pages: %llux\n", *(uvlong*)c->vabitm);
|
||||
}
|
||||
npage += c->npages;
|
||||
if (p1 > conf.maxphys)
|
||||
conf.maxphys = p1;
|
||||
switch ((ulong)c->usage&3) {
|
||||
case 0:
|
||||
if (nbank >= Maxbank) {
|
||||
print("increase Maxbank; lost %lldMB\n", c->npages*hwrpb->by2pg/MB);
|
||||
break;
|
||||
}
|
||||
bank[nbank].min = p0;
|
||||
bank[nbank].max = p1;
|
||||
nbank++;
|
||||
break;
|
||||
case 2:
|
||||
print("nvram skipped\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (debug)
|
||||
print("\n");
|
||||
|
||||
print("Memory size: %lludMB\n", npage*hwrpb->by2pg/MB);
|
||||
print("\n");
|
||||
|
||||
/* kernel virtual space = 2G. leave room for kmapio */
|
||||
if (conf.maxphys > 1024*MB) {
|
||||
print("meminit: too much physical memory; only first gigabyte mapped\n\n");
|
||||
conf.maxphys = 1024*MB;
|
||||
}
|
||||
|
||||
conf.nbank = nbank;
|
||||
conf.bank = bank;
|
||||
}
|
||||
|
||||
int
|
||||
validrgn(ulong min, ulong max)
|
||||
{
|
||||
int i;
|
||||
|
||||
min &= ~KZERO;
|
||||
max &= ~KZERO;
|
||||
for (i = 0; i < nbank; i++)
|
||||
if (bank[i].min <= min && max <= bank[i].max)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uvlong
|
||||
allocate(int pages)
|
||||
{
|
||||
uvlong top, len;
|
||||
int from, i;
|
||||
|
||||
top = 0;
|
||||
len = pages*hwrpb->by2pg;
|
||||
from = -1;
|
||||
for (i = 0; i < nbank; i++)
|
||||
if (bank[i].max - bank[i].min >= len && bank[i].max > top) {
|
||||
top = bank[i].max;
|
||||
from = i;
|
||||
}
|
||||
if (from < 0)
|
||||
return 0;
|
||||
bank[from].max -= len;
|
||||
conf.bank[from].max = bank[from].max;
|
||||
for (i = 0; i < len>>3; i++)
|
||||
stqp(bank[from].max+8*i, 0);
|
||||
return bank[from].max;
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
objtype=alpha
|
||||
</$objtype/mkfile
|
||||
|
||||
TARGET=bootalphapc
|
||||
OBJ=\
|
||||
l.$O\
|
||||
main.$O\
|
||||
conf.$O\
|
||||
cons.$O\
|
||||
exec.$O\
|
||||
bootp.$O\
|
||||
memory.$O\
|
||||
mmu.$O\
|
||||
print.$O\
|
||||
|
||||
HFILES=\
|
||||
u.h\
|
||||
mem.h\
|
||||
conf.h\
|
||||
dat.h\
|
||||
fns.h\
|
||||
lib.h\
|
||||
ip.h\
|
||||
|
||||
loadaddr = 0x20000020
|
||||
|
||||
$TARGET: $OBJ
|
||||
$LD -o $target -l -R8 -H3 -T$loadaddr $prereq -lc
|
||||
|
||||
install:V: $TARGET
|
||||
cp $TARGET /$objtype
|
||||
|
||||
clean nuke:V:
|
||||
rm -f *.$O $TARGET
|
||||
|
||||
%.$O: %.s
|
||||
$AS $stem.s
|
||||
|
||||
%.$O: %.c
|
||||
$CC $CFLAGS $stem.c
|
||||
|
||||
%.$O: $HFILES
|
|
@ -1,111 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "mem.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "lib.h"
|
||||
|
||||
static int debug;
|
||||
|
||||
static uvlong by2pg; /* hwrpb->by2pg */
|
||||
static uvlong pte2pg; /* by2pg/8 */
|
||||
static uvlong pgmask; /* by2pg-1 */
|
||||
static uvlong ptemask; /* pte2pg-1 */
|
||||
static uvlong pgshift; /* log2(by2pg) */
|
||||
static uvlong pteshift; /* log2(pte2pg) = pgshift - 3 */
|
||||
|
||||
#define L1(va) (((uvlong)(va)>>3*pteshift+3) & (pte2pg-1))
|
||||
#define L2(va) (((uvlong)(va)>>2*pteshift+3) & (pte2pg-1))
|
||||
#define L3(va) (((uvlong)(va)>>pgshift) & (pte2pg-1))
|
||||
#define OFF(va) (((uvlong)(va)) & (by2pg-1))
|
||||
|
||||
#define V1(l1) (((vlong)l1<<(64-pteshift)) >> 64-(3*pteshift+3))
|
||||
#define V2(l2) (((uvlong)l2<<(64-pteshift)) >> 64-(2*pteshift+3))
|
||||
#define V3(l3) (((uvlong)l3<<(64-pteshift)) >> 64-pgshift)
|
||||
#define VA(l1, l2, l3, off) (V1(l1) | V2(l2) | V3(l3) | (off))
|
||||
|
||||
static int
|
||||
log2(uvlong x)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((x & (x-1)) == 0)
|
||||
for (i = 0; i < 64; i++)
|
||||
if (x & (1<<i))
|
||||
return i;
|
||||
panic("log2: %llux", x);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
mmuinit(void)
|
||||
{
|
||||
int i;
|
||||
uvlong npage, nlvl2, nlvl3;
|
||||
uvlong l1p, l2p, lvl2, lvl3;
|
||||
extern ulong _main[], edata[];
|
||||
|
||||
/* map entire physical memory at KZERO */
|
||||
by2pg = hwrpb->by2pg;
|
||||
pte2pg = (by2pg >> 3);
|
||||
pgmask = by2pg-1;
|
||||
ptemask = pte2pg-1;
|
||||
pgshift = log2(by2pg);
|
||||
pteshift = pgshift-3;
|
||||
|
||||
l1p = (1LL<<3*pteshift+3)|(1LL<<2*pteshift+3)|(1LL<<pgshift);
|
||||
if (rdv(l1p+8*(pte2pg-1)) != 0 || rdv(l1p+8*(pte2pg-2)) != 0)
|
||||
panic("KZERO lvl1 already mapped");
|
||||
|
||||
npage = (conf.maxphys+pgmask)>>pgshift;
|
||||
nlvl3 = (npage+ptemask)>>pteshift;
|
||||
nlvl2 = (nlvl3+ptemask)>>pteshift;
|
||||
if (nlvl2 > 1)
|
||||
panic("meminit: nlvl2"); /* cannot happen, due to virtual space limitation */
|
||||
if (debug)
|
||||
print("nlvl1 %llud nlvl2 %llud nlvl3 %llud npage %llud\n", 1LL, nlvl2, nlvl3, npage);
|
||||
|
||||
lvl2 = allocate(nlvl2+nlvl3);
|
||||
lvl3 = lvl2 + nlvl2*by2pg;
|
||||
|
||||
wrv(l1p+8*(pte2pg-2), rdv(l1p+8)|PTEASM);
|
||||
wrv(l1p+8*(pte2pg-1), (lvl2<<(32-pgshift)) | PTEKVALID | PTEASM);
|
||||
|
||||
l2p = (1LL<<3*pteshift+3)|(1LL<<2*pteshift+3)|((vlong)KZERO >> 2*pteshift)&((1LL<<2*pteshift+3)-1);
|
||||
for (i = 0; i < nlvl3; i++)
|
||||
stqp(lvl2+(l2p&(by2pg-1))+8*i, ((lvl3+i*by2pg)<<(32-pgshift)) | PTEKVALID | PTEASM);
|
||||
|
||||
for (i = 0; i < npage; i++)
|
||||
stqp(lvl3+8*i, ((uvlong)i<<32) | PTEKVALID | PTEASM);
|
||||
|
||||
tlbflush();
|
||||
|
||||
if (debug)
|
||||
print("\n");
|
||||
}
|
||||
|
||||
uvlong
|
||||
paddr(uvlong va)
|
||||
{
|
||||
uvlong ptbr, x, pte;
|
||||
|
||||
ptbr = getptbr();
|
||||
pte = ldqp((ptbr<<pgshift)+8*L1(va));
|
||||
if ((pte&PTEKVALID) != PTEKVALID)
|
||||
return 0;
|
||||
x = ((pte>>32)<<pgshift);
|
||||
pte = ldqp(x+8*L2(va));
|
||||
if ((pte&PTEKVALID) != PTEKVALID)
|
||||
return 0;
|
||||
x = ((pte>>32)<<pgshift);
|
||||
pte = ldqp(x+8*L3(va));
|
||||
if ((pte&PTEKVALID) != PTEKVALID)
|
||||
return 0;
|
||||
x = ((pte>>32)<<pgshift);
|
||||
return x;
|
||||
}
|
||||
|
||||
uvlong
|
||||
pground(uvlong x)
|
||||
{
|
||||
return (x+pgmask) & ~pgmask;
|
||||
}
|
|
@ -1,575 +0,0 @@
|
|||
#include "u.h"
|
||||
#include "lib.h"
|
||||
|
||||
enum
|
||||
{
|
||||
SIZE = 1024,
|
||||
IDIGIT = 30,
|
||||
MAXCONV = 40,
|
||||
FDIGIT = 30,
|
||||
FDEFLT = 6,
|
||||
NONE = -1000,
|
||||
MAXFMT = 512,
|
||||
|
||||
FPLUS = 1<<0,
|
||||
FMINUS = 1<<1,
|
||||
FSHARP = 1<<2,
|
||||
FLONG = 1<<3,
|
||||
FSHORT = 1<<4,
|
||||
FUNSIGN = 1<<5,
|
||||
FVLONG = 1<<6,
|
||||
};
|
||||
|
||||
int printcol;
|
||||
|
||||
static int convcount;
|
||||
static char fmtindex[MAXFMT];
|
||||
|
||||
static int noconv(va_list*, Fconv*);
|
||||
static int flags(va_list*, Fconv*);
|
||||
|
||||
static int cconv(va_list*, Fconv*);
|
||||
static int sconv(va_list*, Fconv*);
|
||||
static int percent(va_list*, Fconv*);
|
||||
|
||||
int numbconv(va_list*, Fconv*);
|
||||
|
||||
static
|
||||
int (*fmtconv[MAXCONV])(va_list*, Fconv*) =
|
||||
{
|
||||
noconv
|
||||
};
|
||||
|
||||
static
|
||||
void
|
||||
initfmt(void)
|
||||
{
|
||||
int cc;
|
||||
|
||||
cc = 0;
|
||||
fmtconv[cc] = noconv;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = flags;
|
||||
fmtindex['+'] = cc;
|
||||
fmtindex['-'] = cc;
|
||||
fmtindex['#'] = cc;
|
||||
fmtindex['h'] = cc;
|
||||
fmtindex['l'] = cc;
|
||||
fmtindex['u'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = numbconv;
|
||||
fmtindex['d'] = cc;
|
||||
fmtindex['o'] = cc;
|
||||
fmtindex['x'] = cc;
|
||||
fmtindex['X'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = cconv;
|
||||
fmtindex['c'] = cc;
|
||||
fmtindex['C'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = sconv;
|
||||
fmtindex['s'] = cc;
|
||||
fmtindex['S'] = cc;
|
||||
cc++;
|
||||
|
||||
fmtconv[cc] = percent;
|
||||
fmtindex['%'] = cc;
|
||||
cc++;
|
||||
|
||||
convcount = cc;
|
||||
}
|
||||
|
||||
int
|
||||
fmtinstall(int c, int (*f)(va_list*, Fconv*))
|
||||
{
|
||||
|
||||
if(convcount == 0)
|
||||
initfmt();
|
||||
if(c < 0 || c >= MAXFMT)
|
||||
return -1;
|
||||
if(convcount >= MAXCONV)
|
||||
return -1;
|
||||
fmtconv[convcount] = f;
|
||||
fmtindex[c] = convcount;
|
||||
convcount++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char*
|
||||
doprint(char *s, char *es, char *fmt, va_list argp)
|
||||
{
|
||||
int n, c;
|
||||
Rune rune;
|
||||
Fconv local;
|
||||
|
||||
local.out = s;
|
||||
local.eout = es-UTFmax-1;
|
||||
|
||||
loop:
|
||||
c = *fmt & 0xff;
|
||||
if(c >= Runeself) {
|
||||
n = chartorune(&rune, fmt);
|
||||
fmt += n;
|
||||
c = rune;
|
||||
} else
|
||||
fmt++;
|
||||
switch(c) {
|
||||
case 0:
|
||||
*local.out = 0;
|
||||
return local.out;
|
||||
|
||||
default:
|
||||
printcol++;
|
||||
goto common;
|
||||
|
||||
case '\n':
|
||||
printcol = 0;
|
||||
goto common;
|
||||
|
||||
case '\t':
|
||||
printcol = (printcol+8) & ~7;
|
||||
goto common;
|
||||
|
||||
common:
|
||||
if(local.out < local.eout)
|
||||
if(c >= Runeself) {
|
||||
rune = c;
|
||||
n = runetochar(local.out, &rune);
|
||||
local.out += n;
|
||||
} else
|
||||
*local.out++ = c;
|
||||
goto loop;
|
||||
|
||||
case '%':
|
||||
break;
|
||||
}
|
||||
local.f1 = NONE;
|
||||
local.f2 = NONE;
|
||||
local.f3 = 0;
|
||||
|
||||
/*
|
||||
* read one of the following
|
||||
* 1. number, => f1, f2 in order.
|
||||
* 2. '*' same as number (from args)
|
||||
* 3. '.' ignored (separates numbers)
|
||||
* 4. flag => f3
|
||||
* 5. verb and terminate
|
||||
*/
|
||||
l0:
|
||||
c = *fmt & 0xff;
|
||||
if(c >= Runeself) {
|
||||
n = chartorune(&rune, fmt);
|
||||
fmt += n;
|
||||
c = rune;
|
||||
} else
|
||||
fmt++;
|
||||
|
||||
l1:
|
||||
if(c == 0) {
|
||||
fmt--;
|
||||
goto loop;
|
||||
}
|
||||
if(c == '.') {
|
||||
if(local.f1 == NONE)
|
||||
local.f1 = 0;
|
||||
local.f2 = 0;
|
||||
goto l0;
|
||||
}
|
||||
if((c >= '1' && c <= '9') ||
|
||||
(c == '0' && local.f1 != NONE)) { /* '0' is a digit for f2 */
|
||||
n = 0;
|
||||
while(c >= '0' && c <= '9') {
|
||||
n = n*10 + c-'0';
|
||||
c = *fmt++;
|
||||
}
|
||||
if(local.f1 == NONE)
|
||||
local.f1 = n;
|
||||
else
|
||||
local.f2 = n;
|
||||
goto l1;
|
||||
}
|
||||
if(c == '*') {
|
||||
n = va_arg(argp, int);
|
||||
if(local.f1 == NONE)
|
||||
local.f1 = n;
|
||||
else
|
||||
local.f2 = n;
|
||||
goto l0;
|
||||
}
|
||||
n = 0;
|
||||
if(c >= 0 && c < MAXFMT)
|
||||
n = fmtindex[c];
|
||||
local.chr = c;
|
||||
n = (*fmtconv[n])(&argp, &local);
|
||||
if(n < 0) {
|
||||
local.f3 |= -n;
|
||||
goto l0;
|
||||
}
|
||||
goto loop;
|
||||
}
|
||||
|
||||
int
|
||||
numbconv(va_list *arg, Fconv *fp)
|
||||
{
|
||||
char s[IDIGIT];
|
||||
int i, f, n, b, ucase;
|
||||
short h;
|
||||
long v;
|
||||
vlong vl;
|
||||
|
||||
SET(v);
|
||||
SET(vl);
|
||||
|
||||
ucase = 0;
|
||||
b = fp->chr;
|
||||
switch(fp->chr) {
|
||||
case 'u':
|
||||
fp->f3 |= FUNSIGN;
|
||||
case 'd':
|
||||
b = 10;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
b = 8;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
ucase = 1;
|
||||
case 'x':
|
||||
b = 16;
|
||||
break;
|
||||
}
|
||||
|
||||
f = 0;
|
||||
switch(fp->f3 & (FVLONG|FLONG|FSHORT|FUNSIGN)) {
|
||||
case FVLONG|FLONG:
|
||||
vl = va_arg(*arg, vlong);
|
||||
break;
|
||||
|
||||
case FUNSIGN|FVLONG|FLONG:
|
||||
vl = va_arg(*arg, uvlong);
|
||||
break;
|
||||
|
||||
case FLONG:
|
||||
v = va_arg(*arg, long);
|
||||
break;
|
||||
|
||||
case FUNSIGN|FLONG:
|
||||
v = va_arg(*arg, ulong);
|
||||
break;
|
||||
|
||||
case FSHORT:
|
||||
h = va_arg(*arg, int);
|
||||
v = h;
|
||||
break;
|
||||
|
||||
case FUNSIGN|FSHORT:
|
||||
h = va_arg(*arg, int);
|
||||
v = (ushort)h;
|
||||
break;
|
||||
|
||||
default:
|
||||
v = va_arg(*arg, int);
|
||||
break;
|
||||
|
||||
case FUNSIGN:
|
||||
v = va_arg(*arg, unsigned);
|
||||
break;
|
||||
}
|
||||
if(fp->f3 & FVLONG) {
|
||||
if(!(fp->f3 & FUNSIGN) && vl < 0) {
|
||||
vl = -vl;
|
||||
f = 1;
|
||||
}
|
||||
} else {
|
||||
if(!(fp->f3 & FUNSIGN) && v < 0) {
|
||||
v = -v;
|
||||
f = 1;
|
||||
}
|
||||
}
|
||||
s[IDIGIT-1] = 0;
|
||||
for(i = IDIGIT-2;; i--) {
|
||||
if(fp->f3 & FVLONG)
|
||||
n = (uvlong)vl % b;
|
||||
else
|
||||
n = (ulong)v % b;
|
||||
n += '0';
|
||||
if(n > '9') {
|
||||
n += 'a' - ('9'+1);
|
||||
if(ucase)
|
||||
n += 'A'-'a';
|
||||
}
|
||||
s[i] = n;
|
||||
if(i < 2)
|
||||
break;
|
||||
if(fp->f3 & FVLONG)
|
||||
vl = (uvlong)vl / b;
|
||||
else
|
||||
v = (ulong)v / b;
|
||||
if(fp->f2 != NONE && i >= IDIGIT-fp->f2)
|
||||
continue;
|
||||
if(fp->f3 & FVLONG) {
|
||||
if(vl <= 0)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
if(v <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if(fp->f3 & FSHARP) {
|
||||
if(b == 8 && s[i] != '0')
|
||||
s[--i] = '0';
|
||||
if(b == 16) {
|
||||
if(ucase)
|
||||
s[--i] = 'X';
|
||||
else
|
||||
s[--i] = 'x';
|
||||
s[--i] = '0';
|
||||
}
|
||||
}
|
||||
if(f)
|
||||
s[--i] = '-';
|
||||
fp->f2 = NONE;
|
||||
strconv(s+i, fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
Strconv(Rune *s, Fconv *fp)
|
||||
{
|
||||
int n, c, i;
|
||||
Rune rune;
|
||||
|
||||
if(fp->f3 & FMINUS)
|
||||
fp->f1 = -fp->f1;
|
||||
n = 0;
|
||||
if(fp->f1 != NONE && fp->f1 >= 0) {
|
||||
for(; s[n]; n++)
|
||||
;
|
||||
while(n < fp->f1) {
|
||||
if(fp->out < fp->eout)
|
||||
*fp->out++ = ' ';
|
||||
printcol++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
for(;;) {
|
||||
c = *s++;
|
||||
if(c == 0)
|
||||
break;
|
||||
n++;
|
||||
if(fp->f2 == NONE || fp->f2 > 0) {
|
||||
if(fp->out < fp->eout)
|
||||
if(c >= Runeself) {
|
||||
rune = c;
|
||||
i = runetochar(fp->out, &rune);
|
||||
fp->out += i;
|
||||
} else
|
||||
*fp->out++ = c;
|
||||
if(fp->f2 != NONE)
|
||||
fp->f2--;
|
||||
switch(c) {
|
||||
default:
|
||||
printcol++;
|
||||
break;
|
||||
case '\n':
|
||||
printcol = 0;
|
||||
break;
|
||||
case '\t':
|
||||
printcol = (printcol+8) & ~7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(fp->f1 != NONE && fp->f1 < 0) {
|
||||
fp->f1 = -fp->f1;
|
||||
while(n < fp->f1) {
|
||||
if(fp->out < fp->eout)
|
||||
*fp->out++ = ' ';
|
||||
printcol++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
strconv(char *s, Fconv *fp)
|
||||
{
|
||||
int n, c, i;
|
||||
Rune rune;
|
||||
|
||||
if(fp->f3 & FMINUS)
|
||||
fp->f1 = -fp->f1;
|
||||
n = 0;
|
||||
if(fp->f1 != NONE && fp->f1 >= 0) {
|
||||
n = utflen(s);
|
||||
while(n < fp->f1) {
|
||||
if(fp->out < fp->eout)
|
||||
*fp->out++ = ' ';
|
||||
printcol++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
for(;;) {
|
||||
c = *s & 0xff;
|
||||
if(c >= Runeself) {
|
||||
i = chartorune(&rune, s);
|
||||
s += i;
|
||||
c = rune;
|
||||
} else
|
||||
s++;
|
||||
if(c == 0)
|
||||
break;
|
||||
n++;
|
||||
if(fp->f2 == NONE || fp->f2 > 0) {
|
||||
if(fp->out < fp->eout)
|
||||
if(c >= Runeself) {
|
||||
rune = c;
|
||||
i = runetochar(fp->out, &rune);
|
||||
fp->out += i;
|
||||
} else
|
||||
*fp->out++ = c;
|
||||
if(fp->f2 != NONE)
|
||||
fp->f2--;
|
||||
switch(c) {
|
||||
default:
|
||||
printcol++;
|
||||
break;
|
||||
case '\n':
|
||||
printcol = 0;
|
||||
break;
|
||||
case '\t':
|
||||
printcol = (printcol+8) & ~7;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(fp->f1 != NONE && fp->f1 < 0) {
|
||||
fp->f1 = -fp->f1;
|
||||
while(n < fp->f1) {
|
||||
if(fp->out < fp->eout)
|
||||
*fp->out++ = ' ';
|
||||
printcol++;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
noconv(va_list *arg, Fconv *fp)
|
||||
{
|
||||
int n;
|
||||
char s[10];
|
||||
|
||||
if(convcount == 0) {
|
||||
initfmt();
|
||||
n = 0;
|
||||
if(fp->chr >= 0 && fp->chr < MAXFMT)
|
||||
n = fmtindex[fp->chr];
|
||||
return (*fmtconv[n])(arg, fp);
|
||||
}
|
||||
s[0] = '*';
|
||||
s[1] = fp->chr;
|
||||
s[2] = '*';
|
||||
s[3] = 0;
|
||||
fp->f1 = 0;
|
||||
fp->f2 = NONE;
|
||||
fp->f3 = 0;
|
||||
strconv(s, fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
cconv(va_list *arg, Fconv *fp)
|
||||
{
|
||||
char s[10];
|
||||
Rune rune;
|
||||
|
||||
rune = va_arg(*arg, int);
|
||||
if(fp->chr == 'c')
|
||||
rune &= 0xff;
|
||||
s[runetochar(s, &rune)] = 0;
|
||||
|
||||
fp->f2 = NONE;
|
||||
strconv(s, fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
sconv(va_list *arg, Fconv *fp)
|
||||
{
|
||||
char *s;
|
||||
Rune *r;
|
||||
|
||||
if(fp->chr == 's') {
|
||||
s = va_arg(*arg, char*);
|
||||
if(s == 0)
|
||||
s = "<null>";
|
||||
strconv(s, fp);
|
||||
} else {
|
||||
r = va_arg(*arg, Rune*);
|
||||
if(r == 0)
|
||||
r = L"<null>";
|
||||
Strconv(r, fp);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
percent(va_list *arg, Fconv *fp)
|
||||
{
|
||||
|
||||
USED(arg);
|
||||
if(fp->out < fp->eout)
|
||||
*fp->out++ = '%';
|
||||
printcol++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
flags(va_list *arg, Fconv *fp)
|
||||
{
|
||||
int f;
|
||||
|
||||
USED(arg);
|
||||
|
||||
f = 0;
|
||||
switch(fp->chr) {
|
||||
case '+':
|
||||
f = FPLUS;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
f = FMINUS;
|
||||
break;
|
||||
|
||||
case '#':
|
||||
f = FSHARP;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
f = FSHORT;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
f = FLONG;
|
||||
if(fp->f3 & FLONG)
|
||||
f = FVLONG;
|
||||
break;
|
||||
|
||||
case 'u':
|
||||
f = FUNSIGN;
|
||||
break;
|
||||
}
|
||||
return -f;
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
#define nil ((void*)0)
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned char uchar;
|
||||
typedef signed char schar;
|
||||
typedef unsigned long ulong;
|
||||
typedef unsigned int uint;
|
||||
typedef long long vlong;
|
||||
typedef unsigned long long uvlong;
|
||||
typedef union Length Length;
|
||||
typedef ushort Rune;
|
||||
|
||||
union Length
|
||||
{
|
||||
vlong length;
|
||||
};
|
||||
|
||||
/* stdarg */
|
||||
typedef char* va_list;
|
||||
#define va_start(list, start) list = (char*)(&(start)+1)
|
||||
#define va_end(list)
|
||||
#define va_arg(list, mode)\
|
||||
(sizeof(mode)==1?\
|
||||
((mode*)(list += 4))[-1]:\
|
||||
sizeof(mode)==2?\
|
||||
((mode*)(list += 4))[-1]:\
|
||||
sizeof(mode)>4?\
|
||||
((mode*)(list = (char*)((long)(list+7) & ~7) + sizeof(mode)))[-1]:\
|
||||
((mode*)(list += sizeof(mode)))[-1])
|
|
@ -1,105 +0,0 @@
|
|||
/*
|
||||
* VMS PALcode instructions, in numerical order.
|
||||
*/
|
||||
|
||||
#define PALhalt 0x00 /* required per Alpha architecture */
|
||||
#define PALcflush 0x01
|
||||
#define PALdraina 0x02 /* required per Alpha architecture */
|
||||
#define PALldqp 0x03
|
||||
|
||||
#define PALstqp 0x04
|
||||
#define PALswpctx 0x05
|
||||
#define PALmfpr_asn 0x06
|
||||
#define PALmtpr_asten 0x07
|
||||
#define PALmtpr_astsr 0x08
|
||||
#define PALcserve 0x09
|
||||
#define PALswppal 0x0a
|
||||
#define PALmfpr_fen 0x0b
|
||||
#define PALmtpr_fen 0x0c
|
||||
#define PALmtpr_ipir 0x0d
|
||||
#define PALmfpr_ipl 0x0e
|
||||
#define PALmtpr_ipl 0x0f
|
||||
#define PALmfpr_mces 0x10
|
||||
#define PALmtpr_mces 0x11
|
||||
#define PALmfpr_pcbb 0x12
|
||||
#define PALmfpr_prbr 0x13
|
||||
#define PALmtpr_prbr 0x14
|
||||
#define PALmfpr_ptbr 0x15
|
||||
#define PALmfpr_scbb 0x16
|
||||
#define PALmtpr_scbb 0x17
|
||||
#define PALmtpr_sirr 0x18
|
||||
#define PALmfpr_sisr 0x19
|
||||
#define PALmfpr_tbchk 0x1a
|
||||
#define PALmtpr_tbia 0x1b
|
||||
#define PALmtpr_tbiap 0x1c
|
||||
#define PALmtpr_tbis 0x1d
|
||||
#define PALmfpr_esp 0x1e
|
||||
#define PALmtpr_esp 0x1f
|
||||
#define PALmfpr_ssp 0x20
|
||||
#define PALmtpr_ssp 0x21
|
||||
#define PALmfpr_usp 0x22
|
||||
#define PALmtpr_usp 0x23
|
||||
#define PALmtpr_tbisd 0x24
|
||||
#define PALmtpr_tbisi 0x25
|
||||
#define PALmfpr_asten 0x26
|
||||
#define PALmfpr_astsr 0x27
|
||||
/* where is instruction 0x28 ? */
|
||||
#define PALmfpr_vptb 0x29
|
||||
#define PALmtpr_vptb 0x2a
|
||||
#define PALmtpr_perfmon 0x2b
|
||||
/* where is instruction 0x2c ? */
|
||||
/* where is instruction 0x2d ? */
|
||||
#define PALmtpr_datfx 0x2e
|
||||
/*
|
||||
* ... 0x2f to 0x3e ??
|
||||
*/
|
||||
#define PALmfpr_whami 0x3f
|
||||
/*
|
||||
* ... 0x40 to 0x7f ??
|
||||
*/
|
||||
#define PALbpt 0x80
|
||||
#define PALbugchk 0x81
|
||||
#define PALchime 0x82
|
||||
#define PALchmk 0x83
|
||||
#define PALchms 0x84
|
||||
#define PALchmu 0x85
|
||||
#define PALimb 0x86 /* required per Alpha architecture */
|
||||
#define PALinsqhil 0x87
|
||||
#define PALinsqtil 0x88
|
||||
#define PALinsqhiq 0x89
|
||||
#define PALinsqtiq 0x8a
|
||||
#define PALinsquel 0x8b
|
||||
#define PALinsqueq 0x8c
|
||||
#define PALinsqueld 0x8d /* INSQUEL/D */
|
||||
#define PALinsqueqd 0x8e /* INSQUEQ/D */
|
||||
#define PALprober 0x8f
|
||||
#define PALprobew 0x90
|
||||
#define PALrd_ps 0x91
|
||||
#define PALrei 0x92
|
||||
#define PALremqhil 0x93
|
||||
#define PALremqtil 0x94
|
||||
#define PALremqhiq 0x95
|
||||
#define PALremqtiq 0x96
|
||||
#define PALremquel 0x97
|
||||
#define PALremqueq 0x98
|
||||
#define PALremqueld 0x99 /* REMQUEL/D */
|
||||
#define PALremqueqd 0x9a /* REMQUEQ/D */
|
||||
#define PALswasten 0x9b
|
||||
#define PALwr_ps_sw 0x9c
|
||||
#define PALrscc 0x9d
|
||||
#define PALread_unq 0x9e
|
||||
#define PALwrite_unq 0x9f
|
||||
#define PALamovrr 0xa0
|
||||
#define PALamovrm 0xa1
|
||||
#define PALinsqhilr 0xa2
|
||||
#define PALinsqtilr 0xa3
|
||||
|
||||
#define PALinsqhiqr 0xa4
|
||||
#define PALinsqtiqr 0xa5
|
||||
#define PALremqhilr 0xa6
|
||||
|
||||
#define PALremqtilr 0xa7
|
||||
#define PALremqhiqr 0xa8
|
||||
#define PALremqtiqr 0xa9
|
||||
#define PALgentrap 0xaa
|
||||
|
|
@ -1,7 +1,8 @@
|
|||
ARCH=\
|
||||
alphapc\
|
||||
bitsy\
|
||||
efi\
|
||||
pc\
|
||||
zynq\
|
||||
|
||||
all:V:
|
||||
for(i in $ARCH)@{
|
||||
|
|
|
@ -1,208 +0,0 @@
|
|||
#include <u.h>
|
||||
#include <libc.h>
|
||||
#include <bio.h>
|
||||
#include "../7c/7.out.h"
|
||||
|
||||
#ifndef EXTERN
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
#define MAXALIGN 7
|
||||
|
||||
typedef struct Sym Sym;
|
||||
typedef struct Ref Ref;
|
||||
typedef struct Gen Gen;
|
||||
typedef struct Io Io;
|
||||
typedef struct Hist Hist;
|
||||
|
||||
#define FPCHIP 1
|
||||
#define NSYMB 500
|
||||
#define BUFSIZ 8192
|
||||
#define HISTSZ 20
|
||||
#define NINCLUDE 10
|
||||
#define NHUNK 10000
|
||||
#define EOF (-1)
|
||||
#define IGN (-2)
|
||||
#define GETC() ((--fi.c < 0)? filbuf(): *fi.p++ & 0xff)
|
||||
#define NHASH 503
|
||||
#define STRINGSZ 200
|
||||
#define NMACRO 10
|
||||
|
||||
#define ALLOC(lhs, type)\
|
||||
while(nhunk < sizeof(type))\
|
||||
gethunk();\
|
||||
lhs = (type*)hunk;\
|
||||
nhunk -= sizeof(type);\
|
||||
hunk += sizeof(type);
|
||||
|
||||
#define ALLOCN(lhs, len, n)\
|
||||
if(lhs+len != hunk || nhunk < n) {\
|
||||
while(nhunk <= len)\
|
||||
gethunk();\
|
||||
memmove(hunk, lhs, len);\
|
||||
lhs = hunk;\
|
||||
hunk += len;\
|
||||
nhunk -= len;\
|
||||
}\
|
||||
hunk += n;\
|
||||
nhunk -= n;
|
||||
|
||||
struct Sym
|
||||
{
|
||||
Sym* link;
|
||||
Ref* ref;
|
||||
char* macro;
|
||||
vlong value;
|
||||
long dummy_pad;
|
||||
ushort type;
|
||||
char *name;
|
||||
char sym;
|
||||
};
|
||||
#define S ((Sym*)0)
|
||||
|
||||
struct Ref
|
||||
{
|
||||
int class;
|
||||
};
|
||||
|
||||
struct
|
||||
{
|
||||
char* p;
|
||||
int c;
|
||||
} fi;
|
||||
|
||||
struct Io
|
||||
{
|
||||
Io* link;
|
||||
char b[BUFSIZ];
|
||||
char* p;
|
||||
short c;
|
||||
short f;
|
||||
};
|
||||
#define I ((Io*)0)
|
||||
|
||||
struct
|
||||
{
|
||||
Sym* sym;
|
||||
short type;
|
||||
} h[NSYM];
|
||||
|
||||
struct Gen
|
||||
{
|
||||
Sym* sym;
|
||||
vlong offset;
|
||||
long dummy_pad;
|
||||
short type;
|
||||
short reg;
|
||||
short name;
|
||||
double dval;
|
||||
char sval[8];
|
||||
};
|
||||
|
||||
struct Hist
|
||||
{
|
||||
Hist* link;
|
||||
char* name;
|
||||
long line;
|
||||
vlong offset;
|
||||
};
|
||||
#define H ((Hist*)0)
|
||||
|
||||
enum
|
||||
{
|
||||
CLAST,
|
||||
CMACARG,
|
||||
CMACRO,
|
||||
CPREPROC,
|
||||
};
|
||||
|
||||
char debug[256];
|
||||
Sym* hash[NHASH];
|
||||
char* Dlist[30];
|
||||
int nDlist;
|
||||
Hist* ehist;
|
||||
int newflag;
|
||||
Hist* hist;
|
||||
char* hunk;
|
||||
char* include[NINCLUDE];
|
||||
Io* iofree;
|
||||
Io* ionext;
|
||||
Io* iostack;
|
||||
long lineno;
|
||||
int nerrors;
|
||||
long nhunk;
|
||||
int ninclude;
|
||||
Gen nullgen;
|
||||
char* outfile;
|
||||
int pass;
|
||||
char* pathname;
|
||||
vlong pc;
|
||||
int peekc;
|
||||
int sym;
|
||||
char symb[NSYMB];
|
||||
int thechar;
|
||||
char* thestring;
|
||||
long thunk;
|
||||
Biobuf obuf;
|
||||
|
||||
void errorexit(void);
|
||||
void pushio(void);
|
||||
void newio(void);
|
||||
void newfile(char*, int);
|
||||
Sym* slookup(char*);
|
||||
Sym* lookup(void);
|
||||
void syminit(Sym*);
|
||||
long yylex(void);
|
||||
int getc(void);
|
||||
int getnsc(void);
|
||||
void unget(int);
|
||||
int escchar(int);
|
||||
void cinit(void);
|
||||
void pinit(char*);
|
||||
void cclean(void);
|
||||
int isreg(Gen*);
|
||||
void outcode(int, Gen*, int, Gen*);
|
||||
void zname(char*, int, int);
|
||||
void zaddr(Gen*, int);
|
||||
void ieeedtod(Ieee*, double);
|
||||
int filbuf(void);
|
||||
Sym* getsym(void);
|
||||
void domacro(void);
|
||||
void macund(void);
|
||||
void macdef(void);
|
||||
void macexpand(Sym*, char*);
|
||||
void macinc(void);
|
||||
void maclin(void);
|
||||
void macprag(void);
|
||||
void macif(int);
|
||||
void macend(void);
|
||||
void outhist(void);
|
||||
void dodefine(char*);
|
||||
void prfile(long);
|
||||
void linehist(char*, int);
|
||||
void gethunk(void);
|
||||
void yyerror(char*, ...);
|
||||
int yyparse(void);
|
||||
void setinclude(char*);
|
||||
int assemble(char*);
|
||||
|
||||
/*
|
||||
* system-dependent stuff from ../cc/compat.c
|
||||
*/
|
||||
|
||||
enum /* keep in synch with ../cc/cc.h */
|
||||
{
|
||||
Plan9 = 1<<0,
|
||||
Unix = 1<<1,
|
||||
Windows = 1<<2,
|
||||
};
|
||||
int mywait(int*);
|
||||
int mycreat(char*, int);
|
||||
int systemtype(int);
|
||||
int pathchar(void);
|
||||
char* mygetwd(char*, int);
|
||||
int myexec(char*, char*[]);
|
||||
int mydup(int, int);
|
||||
int myfork(void);
|
||||
int mypipe(int*);
|
||||
void* mysbrk(ulong);
|
|
@ -1,537 +0,0 @@
|
|||
%{
|
||||
#include "a.h"
|
||||
%}
|
||||
%union
|
||||
{
|
||||
Sym *sym;
|
||||
vlong lval;
|
||||
double dval;
|
||||
char sval[8];
|
||||
Gen gen;
|
||||
}
|
||||
%left '|'
|
||||
%left '^'
|
||||
%left '&'
|
||||
%left '<' '>'
|
||||
%left '+' '-'
|
||||
%left '*' '/' '%'
|
||||
%token <lval> LTYPE1 LTYPE2 LTYPE3 LTYPE4 LTYPE5
|
||||
%token <lval> LTYPE6 LTYPE7 LTYPE8 LTYPE9 LTYPEA
|
||||
%token <lval> LTYPEB LTYPEC LTYPED LTYPEE LTYPEF
|
||||
%token <lval> LTYPEG LTYPEH LTYPEI LTYPEJ LTYPEK
|
||||
%token <lval> LCONST LSP LSB LFP LPC LPREG LPCC
|
||||
%token <lval> LTYPEX LREG LFREG LFPCR LR LP LF
|
||||
%token <dval> LFCONST
|
||||
%token <sval> LSCONST
|
||||
%token <sym> LNAME LLAB LVAR
|
||||
%type <lval> con expr pointer offset sreg
|
||||
%type <gen> gen vgen lgen vlgen flgen rel reg freg preg fcreg
|
||||
%type <gen> imm ximm ireg name oreg imr nireg fgen pcc
|
||||
%%
|
||||
prog:
|
||||
| prog line
|
||||
|
||||
line:
|
||||
LLAB ':'
|
||||
{
|
||||
if($1->value != pc)
|
||||
yyerror("redeclaration of %s", $1->name);
|
||||
$1->value = pc;
|
||||
}
|
||||
line
|
||||
| LNAME ':'
|
||||
{
|
||||
$1->type = LLAB;
|
||||
$1->value = pc;
|
||||
}
|
||||
line
|
||||
| LNAME '=' expr ';'
|
||||
{
|
||||
$1->type = LVAR;
|
||||
$1->value = $3;
|
||||
}
|
||||
| LVAR '=' expr ';'
|
||||
{
|
||||
if($1->value != $3)
|
||||
yyerror("redeclaration of %s", $1->name);
|
||||
$1->value = $3;
|
||||
}
|
||||
| ';'
|
||||
| inst ';'
|
||||
| error ';'
|
||||
|
||||
inst:
|
||||
/*
|
||||
* Integer operates
|
||||
*/
|
||||
LTYPE1 imr ',' sreg ',' reg
|
||||
{
|
||||
outcode($1, &$2, $4, &$6);
|
||||
}
|
||||
| LTYPE1 imr ',' reg
|
||||
{
|
||||
outcode($1, &$2, NREG, &$4);
|
||||
}
|
||||
/*
|
||||
* floating-type
|
||||
*/
|
||||
| LTYPE2 freg ',' freg
|
||||
{
|
||||
outcode($1, &$2, NREG, &$4);
|
||||
}
|
||||
| LTYPE3 freg ',' freg
|
||||
{
|
||||
outcode($1, &$2, NREG, &$4);
|
||||
}
|
||||
| LTYPE3 freg ',' LFREG ',' freg
|
||||
{
|
||||
outcode($1, &$2, $4, &$6);
|
||||
}
|
||||
/*
|
||||
* MOVQ
|
||||
*/
|
||||
| LTYPE4 vlgen ',' vgen
|
||||
{
|
||||
if(!isreg(&$2) && !isreg(&$4))
|
||||
print("one side must be register\n");
|
||||
outcode($1, &$2, NREG, &$4);
|
||||
}
|
||||
/*
|
||||
* integer LOAD/STORE, but not MOVQ
|
||||
*/
|
||||
| LTYPE5 lgen ',' gen
|
||||
{
|
||||
if(!isreg(&$2) && !isreg(&$4))
|
||||
print("one side must be register\n");
|
||||
outcode($1, &$2, NREG, &$4);
|
||||
}
|
||||
/*
|
||||
* integer LOAD/STORE (only)
|
||||
*/
|
||||
| LTYPE6 oreg ',' reg
|
||||
{
|
||||
outcode($1, &$2, NREG, &$4);
|
||||
}
|
||||
| LTYPEK reg ',' oreg
|
||||
{
|
||||
outcode($1, &$2, NREG, &$4);
|
||||
}
|
||||
/*
|
||||
* floating LOAD/STORE
|
||||
*/
|
||||
| LTYPE7 flgen ',' fgen
|
||||
{
|
||||
if(!isreg(&$2) && !isreg(&$4))
|
||||
print("one side must be register\n");
|
||||
outcode($1, &$2, NREG, &$4);
|
||||
}
|
||||
/*
|
||||
* JMP/JSR/RET
|
||||
*/
|
||||
| LTYPE8 comma rel
|
||||
{
|
||||
outcode($1, &nullgen, NREG, &$3);
|
||||
}
|
||||
| LTYPE8 comma nireg
|
||||
{
|
||||
outcode($1, &nullgen, NREG, &$3);
|
||||
}
|
||||
| LTYPE8 sreg ',' nireg
|
||||
{
|
||||
outcode($1, &nullgen, $2, &$4);
|
||||
}
|
||||
| LTYPE9 comma
|
||||
{
|
||||
outcode($1, &nullgen, NREG, &nullgen);
|
||||
}
|
||||
/*
|
||||
* integer conditional branches
|
||||
*/
|
||||
| LTYPEA gen ',' rel
|
||||
{
|
||||
if(!isreg(&$2))
|
||||
print("left side must be register\n");
|
||||
outcode($1, &$2, NREG, &$4);
|
||||
}
|
||||
/*
|
||||
* floating conditional branches
|
||||
*/
|
||||
| LTYPEB fgen ',' rel
|
||||
{
|
||||
if(!isreg(&$2))
|
||||
print("left side must be register\n");
|
||||
outcode($1, &$2, NREG, &$4);
|
||||
}
|
||||
/*
|
||||
* TRAPB/MB/REI
|
||||
*/
|
||||
| LTYPEC comma
|
||||
{
|
||||
outcode($1, &nullgen, NREG, &nullgen);
|
||||
}
|
||||
/*
|
||||
* FETCH/FETCHM
|
||||
*/
|
||||
| LTYPED ireg comma
|
||||
{
|
||||
outcode($1, &$2, NREG, &nullgen);
|
||||
}
|
||||
/*
|
||||
* Call-pal
|
||||
*/
|
||||
| LTYPEE imm
|
||||
{
|
||||
outcode($1, &$2, NREG, &nullgen);
|
||||
}
|
||||
/*
|
||||
* TEXT/GLOBL
|
||||
*/
|
||||
| LTYPEF name ',' imm
|
||||
{
|
||||
outcode($1, &$2, NREG, &$4);
|
||||
}
|
||||
| LTYPEF name ',' con ',' imm
|
||||
{
|
||||
outcode($1, &$2, $4, &$6);
|
||||
}
|
||||
/*
|
||||
* DATA
|
||||
*/
|
||||
| LTYPEG name '/' con ',' ximm
|
||||
{
|
||||
outcode($1, &$2, $4, &$6);
|
||||
}
|
||||
/*
|
||||
* word
|
||||
*/
|
||||
| LTYPEH comma ximm
|
||||
{
|
||||
outcode($1, &nullgen, NREG, &$3);
|
||||
}
|
||||
/*
|
||||
* NOP
|
||||
*/
|
||||
| LTYPEI comma
|
||||
{
|
||||
outcode($1, &nullgen, NREG, &nullgen);
|
||||
}
|
||||
| LTYPEI ',' vgen
|
||||
{
|
||||
outcode($1, &nullgen, NREG, &$3);
|
||||
}
|
||||
| LTYPEI vgen comma
|
||||
{
|
||||
outcode($1, &$2, NREG, &nullgen);
|
||||
}
|
||||
|
||||
comma:
|
||||
| ','
|
||||
|
||||
rel:
|
||||
con '(' LPC ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_BRANCH;
|
||||
$$.offset = $1 + pc;
|
||||
}
|
||||
| LNAME offset
|
||||
{
|
||||
$$ = nullgen;
|
||||
if(pass == 2)
|
||||
yyerror("undefined label: %s", $1->name);
|
||||
$$.type = D_BRANCH;
|
||||
$$.sym = $1;
|
||||
$$.offset = $2;
|
||||
}
|
||||
| LLAB offset
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_BRANCH;
|
||||
$$.sym = $1;
|
||||
$$.offset = $1->value + $2;
|
||||
}
|
||||
|
||||
vlgen:
|
||||
lgen
|
||||
| preg
|
||||
| pcc
|
||||
|
||||
vgen:
|
||||
gen
|
||||
| preg
|
||||
|
||||
lgen:
|
||||
gen
|
||||
| ximm
|
||||
|
||||
flgen:
|
||||
fgen
|
||||
| ximm
|
||||
|
||||
fgen:
|
||||
gen
|
||||
| freg
|
||||
| fcreg
|
||||
|
||||
preg:
|
||||
LPREG
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_PREG;
|
||||
$$.reg = $1;
|
||||
}
|
||||
| LP '(' con ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_PREG;
|
||||
$$.reg = $1+$3;
|
||||
}
|
||||
|
||||
fcreg:
|
||||
LFPCR
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_FCREG;
|
||||
$$.reg = $1;
|
||||
}
|
||||
|
||||
freg:
|
||||
LFREG
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_FREG;
|
||||
$$.reg = $1;
|
||||
}
|
||||
| LF '(' con ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_FREG;
|
||||
$$.reg = $3;
|
||||
}
|
||||
|
||||
pcc:
|
||||
LPCC
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_PCC;
|
||||
$$.reg = $1;
|
||||
}
|
||||
|
||||
ximm: '$' con
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_CONST;
|
||||
$$.offset = $2;
|
||||
}
|
||||
| '$' oreg
|
||||
{
|
||||
$$ = $2;
|
||||
$$.type = D_CONST;
|
||||
}
|
||||
| '$' LSCONST
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_SCONST;
|
||||
memcpy($$.sval, $2, sizeof($$.sval));
|
||||
}
|
||||
| '$' LFCONST
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_FCONST;
|
||||
$$.dval = $2;
|
||||
}
|
||||
| '$' '-' LFCONST
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_FCONST;
|
||||
$$.dval = -$3;
|
||||
}
|
||||
|
||||
nireg:
|
||||
ireg
|
||||
| name
|
||||
{
|
||||
$$ = $1;
|
||||
if($1.name != D_EXTERN && $1.name != D_STATIC) {
|
||||
}
|
||||
}
|
||||
|
||||
ireg:
|
||||
'(' sreg ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_OREG;
|
||||
$$.reg = $2;
|
||||
$$.offset = 0;
|
||||
}
|
||||
|
||||
gen:
|
||||
reg
|
||||
| con
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_OREG;
|
||||
$$.offset = $1;
|
||||
}
|
||||
| oreg
|
||||
|
||||
oreg:
|
||||
name
|
||||
| name '(' sreg ')'
|
||||
{
|
||||
$$ = $1;
|
||||
$$.type = D_OREG;
|
||||
$$.reg = $3;
|
||||
}
|
||||
| '(' sreg ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_OREG;
|
||||
$$.reg = $2;
|
||||
$$.offset = 0;
|
||||
}
|
||||
| con '(' sreg ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_OREG;
|
||||
$$.reg = $3;
|
||||
$$.offset = $1;
|
||||
}
|
||||
|
||||
imr:
|
||||
reg
|
||||
| imm
|
||||
|
||||
imm: '$' con
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_CONST;
|
||||
$$.offset = $2;
|
||||
}
|
||||
|
||||
reg:
|
||||
sreg
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_REG;
|
||||
$$.reg = $1;
|
||||
}
|
||||
|
||||
sreg:
|
||||
LREG
|
||||
| LR '(' con ')'
|
||||
{
|
||||
if($$ < 0 || $$ >= NREG)
|
||||
print("register value out of range\n");
|
||||
$$ = $3;
|
||||
}
|
||||
|
||||
name:
|
||||
con '(' pointer ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_OREG;
|
||||
$$.name = $3;
|
||||
$$.sym = S;
|
||||
$$.offset = $1;
|
||||
}
|
||||
| LNAME offset '(' pointer ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_OREG;
|
||||
$$.name = $4;
|
||||
$$.sym = $1;
|
||||
$$.offset = $2;
|
||||
}
|
||||
| LNAME '<' '>' offset '(' LSB ')'
|
||||
{
|
||||
$$ = nullgen;
|
||||
$$.type = D_OREG;
|
||||
$$.name = D_STATIC;
|
||||
$$.sym = $1;
|
||||
$$.offset = $4;
|
||||
}
|
||||
|
||||
offset:
|
||||
{
|
||||
$$ = 0;
|
||||
}
|
||||
| '+' con
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| '-' con
|
||||
{
|
||||
$$ = -$2;
|
||||
}
|
||||
|
||||
pointer:
|
||||
LSB
|
||||
| LSP
|
||||
| LFP
|
||||
|
||||
con:
|
||||
LCONST
|
||||
| LVAR
|
||||
{
|
||||
$$ = $1->value;
|
||||
}
|
||||
| '-' con
|
||||
{
|
||||
$$ = -$2;
|
||||
}
|
||||
| '+' con
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
| '~' con
|
||||
{
|
||||
$$ = ~$2;
|
||||
}
|
||||
| '(' expr ')'
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
|
||||
expr:
|
||||
con
|
||||
| expr '+' expr
|
||||
{
|
||||
$$ = $1 + $3;
|
||||
}
|
||||
| expr '-' expr
|
||||
{
|
||||
$$ = $1 - $3;
|
||||
}
|
||||
| expr '*' expr
|
||||
{
|
||||
$$ = $1 * $3;
|
||||
}
|
||||
| expr '/' expr
|
||||
{
|
||||
$$ = $1 / $3;
|
||||
}
|
||||
| expr '%' expr
|
||||
{
|
||||
$$ = $1 % $3;
|
||||
}
|
||||
| expr '<' '<' expr
|
||||
{
|
||||
$$ = $1 << $4;
|
||||
}
|
||||
| expr '>' '>' expr
|
||||
{
|
||||
$$ = $1 >> $4;
|
||||
}
|
||||
| expr '&' expr
|
||||
{
|
||||
$$ = $1 & $3;
|
||||
}
|
||||
| expr '^' expr
|
||||
{
|
||||
$$ = $1 ^ $3;
|
||||
}
|
||||
| expr '|' expr
|
||||
{
|
||||
$$ = $1 | $3;
|
||||
}
|
|
@ -1,694 +0,0 @@
|
|||
#include <ctype.h>
|
||||
#define EXTERN
|
||||
#include "a.h"
|
||||
#include "y.tab.h"
|
||||
|
||||
void
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
char ofile[100], incfile[20], *p;
|
||||
int nout, nproc, status, i, c, of;
|
||||
|
||||
thechar = '7'; /* of 9 */
|
||||
thestring = "alpha";
|
||||
memset(debug, 0, sizeof(debug));
|
||||
cinit();
|
||||
outfile = 0;
|
||||
include[ninclude++] = ".";
|
||||
ARGBEGIN {
|
||||
default:
|
||||
c = ARGC();
|
||||
if(c >= 0 || c < sizeof(debug))
|
||||
debug[c] = 1;
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
outfile = ARGF();
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
p = ARGF();
|
||||
if(p)
|
||||
Dlist[nDlist++] = p;
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
p = ARGF();
|
||||
if(p)
|
||||
include[ninclude++] = p;
|
||||
break;
|
||||
} ARGEND
|
||||
if(*argv == 0) {
|
||||
print("usage: %ca [-options] file.s\n", thechar);
|
||||
errorexit();
|
||||
}
|
||||
nproc = 3;
|
||||
if(p = getenv("NPROC"))
|
||||
nproc = atol(p);
|
||||
if(argc > 1) {
|
||||
c = 0;
|
||||
nout = 0;
|
||||
for(;;) {
|
||||
while(nout < nproc && argc > 0) {
|
||||
i = fork();
|
||||
if(i < 0) {
|
||||
i = mywait(&status);
|
||||
if(i < 0)
|
||||
errorexit();
|
||||
if(status)
|
||||
c++;
|
||||
nout--;
|
||||
continue;
|
||||
}
|
||||
if(i == 0) {
|
||||
print("%s:\n", *argv);
|
||||
goto child;
|
||||
}
|
||||
nout++;
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
i = mywait(&status);
|
||||
if(i < 0) {
|
||||
if(c)
|
||||
errorexit();
|
||||
exits(0);
|
||||
}
|
||||
if(status)
|
||||
c++;
|
||||
nout--;
|
||||
}
|
||||
}
|
||||
|
||||
child:
|
||||
strecpy(ofile, ofile+sizeof ofile, *argv);
|
||||
if(p = strrchr(ofile, '/')) {
|
||||
include[0] = ofile;
|
||||
*p++ = 0;
|
||||
} else
|
||||
p = ofile;
|
||||
if(outfile == 0) {
|
||||
outfile = p;
|
||||
if(p = strrchr(outfile, '.'))
|
||||
if(p[1] == 's' && p[2] == 0)
|
||||
p[0] = 0;
|
||||
p = strrchr(outfile, 0);
|
||||
p[0] = '.';
|
||||
p[1] = thechar;
|
||||
p[2] = 0;
|
||||
}
|
||||
if(0) {
|
||||
strcpy(incfile, "/usr/%include");
|
||||
p = strrchr(incfile, '%');
|
||||
if(p)
|
||||
*p = thechar;
|
||||
} else {
|
||||
strcpy(incfile, "/");
|
||||
strcat(incfile, thestring);
|
||||
strcat(incfile, "/include");
|
||||
}
|
||||
include[ninclude++] = incfile;
|
||||
if(p = getenv("INCLUDE"))
|
||||
include[ninclude-1] = p; /* */
|
||||
of = mycreat(outfile, 0664);
|
||||
if(of < 0) {
|
||||
yyerror("%ca: cannot create %s", thechar, outfile);
|
||||
errorexit();
|
||||
}
|
||||
Binit(&obuf, of, OWRITE);
|
||||
|
||||
pass = 1;
|
||||
pinit(*argv);
|
||||
for(i=0; i<nDlist; i++)
|
||||
dodefine(Dlist[i]);
|
||||
yyparse();
|
||||
if(nerrors) {
|
||||
cclean();
|
||||
errorexit();
|
||||
}
|
||||
|
||||
pass = 2;
|
||||
outhist();
|
||||
pinit(*argv);
|
||||
for(i=0; i<nDlist; i++)
|
||||
dodefine(Dlist[i]);
|
||||
yyparse();
|
||||
cclean();
|
||||
if(nerrors)
|
||||
errorexit();
|
||||
exits(0);
|
||||
}
|
||||
|
||||
struct
|
||||
{
|
||||
char *name;
|
||||
ushort type;
|
||||
ushort value;
|
||||
} itab[] =
|
||||
{
|
||||
"SP", LSP, D_AUTO,
|
||||
"SB", LSB, D_EXTERN,
|
||||
"FP", LFP, D_PARAM,
|
||||
"PC", LPC, D_BRANCH,
|
||||
|
||||
"R", LR, 0,
|
||||
"R0", LREG, 0,
|
||||
"R1", LREG, 1,
|
||||
"R2", LREG, 2,
|
||||
"R3", LREG, 3,
|
||||
"R4", LREG, 4,
|
||||
"R5", LREG, 5,
|
||||
"R6", LREG, 6,
|
||||
"R7", LREG, 7,
|
||||
"R8", LREG, 8,
|
||||
"R9", LREG, 9,
|
||||
"R10", LREG, 10,
|
||||
"R11", LREG, 11,
|
||||
"R12", LREG, 12,
|
||||
"R13", LREG, 13,
|
||||
"R14", LREG, 14,
|
||||
"R15", LREG, 15,
|
||||
"R16", LREG, 16,
|
||||
"R17", LREG, 17,
|
||||
"R18", LREG, 18,
|
||||
"R19", LREG, 19,
|
||||
"R20", LREG, 20,
|
||||
"R21", LREG, 21,
|
||||
"R22", LREG, 22,
|
||||
"R23", LREG, 23,
|
||||
"R24", LREG, 24,
|
||||
"R25", LREG, 25,
|
||||
"R26", LREG, 26,
|
||||
"R27", LREG, 27,
|
||||
"R28", LREG, 28,
|
||||
"R29", LREG, 29,
|
||||
"R30", LREG, 30,
|
||||
"R31", LREG, 31,
|
||||
|
||||
"P", LP, 0,
|
||||
"I", LP, 32,
|
||||
"A", LP, 64,
|
||||
"IA", LP, 96,
|
||||
"T", LP, 128,
|
||||
"IT", LP, 32+128,
|
||||
"AT", LP, 64+128,
|
||||
"IAT", LP, 96+128,
|
||||
"T0", LPREG, 0+128,
|
||||
"T1", LPREG, 1+128,
|
||||
"T2", LPREG, 2+128,
|
||||
"T3", LPREG, 3+128,
|
||||
"T4", LPREG, 4+128,
|
||||
"T5", LPREG, 5+128,
|
||||
"T6", LPREG, 6+128,
|
||||
"T7", LPREG, 7+128,
|
||||
"T8", LPREG, 8+128,
|
||||
"T9", LPREG, 9+128,
|
||||
"T10", LPREG, 10+128,
|
||||
"T11", LPREG, 11+128,
|
||||
"T12", LPREG, 12+128,
|
||||
"T13", LPREG, 13+128,
|
||||
"T14", LPREG, 14+128,
|
||||
"T15", LPREG, 15+128,
|
||||
"T16", LPREG, 16+128,
|
||||
"T17", LPREG, 17+128,
|
||||
"T18", LPREG, 18+128,
|
||||
"T19", LPREG, 19+128,
|
||||
"T20", LPREG, 20+128,
|
||||
"T21", LPREG, 21+128,
|
||||
"T22", LPREG, 22+128,
|
||||
"T23", LPREG, 23+128,
|
||||
"T24", LPREG, 24+128,
|
||||
"T25", LPREG, 25+128,
|
||||
"T26", LPREG, 26+128,
|
||||
"T27", LPREG, 27+128,
|
||||
"T28", LPREG, 28+128,
|
||||
"T29", LPREG, 29+128,
|
||||
"T30", LPREG, 30+128,
|
||||
"T31", LPREG, 31+128,
|
||||
|
||||
"F", LF, 0,
|
||||
|
||||
"F0", LFREG, 0,
|
||||
"F1", LFREG, 1,
|
||||
"F2", LFREG, 2,
|
||||
"F3", LFREG, 3,
|
||||
"F4", LFREG, 4,
|
||||
"F5", LFREG, 5,
|
||||
"F6", LFREG, 6,
|
||||
"F7", LFREG, 7,
|
||||
"F8", LFREG, 8,
|
||||
"F9", LFREG, 9,
|
||||
"F10", LFREG, 10,
|
||||
"F11", LFREG, 11,
|
||||
"F12", LFREG, 12,
|
||||
"F13", LFREG, 13,
|
||||
"F14", LFREG, 14,
|
||||
"F15", LFREG, 15,
|
||||
"F16", LFREG, 16,
|
||||
"F17", LFREG, 17,
|
||||
"F18", LFREG, 18,
|
||||
"F19", LFREG, 19,
|
||||
"F20", LFREG, 20,
|
||||
"F21", LFREG, 21,
|
||||
"F22", LFREG, 22,
|
||||
"F23", LFREG, 23,
|
||||
"F24", LFREG, 24,
|
||||
"F25", LFREG, 25,
|
||||
"F26", LFREG, 26,
|
||||
"F27", LFREG, 27,
|
||||
"F28", LFREG, 28,
|
||||
"F29", LFREG, 29,
|
||||
"F30", LFREG, 30,
|
||||
"F31", LFREG, 31,
|
||||
|
||||
"FPCR", LFPCR, 0,
|
||||
"PCC", LPCC, 0,
|
||||
|
||||
/* 1: integer operates */
|
||||
"ADDQ", LTYPE1, AADDQ,
|
||||
"ADDL", LTYPE1, AADDL,
|
||||
"SUBL", LTYPE1, ASUBL,
|
||||
"SUBQ", LTYPE1, ASUBQ,
|
||||
"CMPEQ", LTYPE1, ACMPEQ,
|
||||
"CMPGT", LTYPE1, ACMPGT,
|
||||
"CMPGE", LTYPE1, ACMPGE,
|
||||
"CMPUGT", LTYPE1, ACMPUGT,
|
||||
"CMPUGE", LTYPE1, ACMPUGE,
|
||||
"CMPBLE", LTYPE1, ACMPBLE,
|
||||
|
||||
"AND", LTYPE1, AAND,
|
||||
"ANDNOT", LTYPE1, AANDNOT,
|
||||
"OR", LTYPE1, AOR,
|
||||
"ORNOT", LTYPE1, AORNOT,
|
||||
"XOR", LTYPE1, AXOR,
|
||||
"XORNOT", LTYPE1, AXORNOT,
|
||||
|
||||
"CMOVEQ", LTYPE1, ACMOVEQ,
|
||||
"CMOVNE", LTYPE1, ACMOVNE,
|
||||
"CMOVLT", LTYPE1, ACMOVLT,
|
||||
"CMOVGE", LTYPE1, ACMOVGE,
|
||||
"CMOVLE", LTYPE1, ACMOVLE,
|
||||
"CMOVGT", LTYPE1, ACMOVGT,
|
||||
"CMOVLBS", LTYPE1, ACMOVLBS,
|
||||
"CMOVLBC", LTYPE1, ACMOVLBC,
|
||||
|
||||
"MULL", LTYPE1, AMULL,
|
||||
"MULQ", LTYPE1, AMULQ,
|
||||
"UMULH", LTYPE1, AUMULH,
|
||||
"DIVQ", LTYPE1, ADIVQ,
|
||||
"MODQ", LTYPE1, AMODQ,
|
||||
"DIVQU", LTYPE1, ADIVQU,
|
||||
"MODQU", LTYPE1, AMODQU,
|
||||
"DIVL", LTYPE1, ADIVL,
|
||||
"MODL", LTYPE1, AMODL,
|
||||
"DIVLU", LTYPE1, ADIVLU,
|
||||
"MODLU", LTYPE1, AMODLU,
|
||||
|
||||
"SLLQ", LTYPE1, ASLLQ,
|
||||
"SRLQ", LTYPE1, ASRLQ,
|
||||
"SRAQ", LTYPE1, ASRAQ,
|
||||
|
||||
"SLLL", LTYPE1, ASLLL,
|
||||
"SRLL", LTYPE1, ASRLL,
|
||||
"SRAL", LTYPE1, ASRAL,
|
||||
|
||||
"EXTBL", LTYPE1, AEXTBL,
|
||||
"EXTWL", LTYPE1, AEXTWL,
|
||||
"EXTLL", LTYPE1, AEXTLL,
|
||||
"EXTQL", LTYPE1, AEXTQL,
|
||||
"EXTWH", LTYPE1, AEXTWH,
|
||||
"EXTLH", LTYPE1, AEXTLH,
|
||||
"EXTQH", LTYPE1, AEXTQH,
|
||||
|
||||
"INSBL", LTYPE1, AINSBL,
|
||||
"INSWL", LTYPE1, AINSWL,
|
||||
"INSLL", LTYPE1, AINSLL,
|
||||
"INSQL", LTYPE1, AINSQL,
|
||||
"INSWH", LTYPE1, AINSWH,
|
||||
"INSLH", LTYPE1, AINSLH,
|
||||
"INSQH", LTYPE1, AINSQH,
|
||||
|
||||
"MSKBL", LTYPE1, AMSKBL,
|
||||
"MSKWL", LTYPE1, AMSKWL,
|
||||
"MSKLL", LTYPE1, AMSKLL,
|
||||
"MSKQL", LTYPE1, AMSKQL,
|
||||
"MSKWH", LTYPE1, AMSKWH,
|
||||
"MSKLH", LTYPE1, AMSKLH,
|
||||
"MSKQH", LTYPE1, AMSKQH,
|
||||
|
||||
"ZAP", LTYPE1, AZAP,
|
||||
"ZAPNOT", LTYPE1, AZAPNOT,
|
||||
|
||||
/* 2: floating operates with 2 operands */
|
||||
"CVTQS", LTYPE2, ACVTQS,
|
||||
"CVTQT", LTYPE2, ACVTQT,
|
||||
"CVTTS", LTYPE2, ACVTTS,
|
||||
"CVTTQ", LTYPE2, ACVTTQ,
|
||||
"CVTLQ", LTYPE2, ACVTLQ,
|
||||
"CVTQL", LTYPE2, ACVTQL,
|
||||
|
||||
/* 3: floating operates with 2 or 3 operands */
|
||||
"CPYS", LTYPE3, ACPYS,
|
||||
"CPYSN", LTYPE3, ACPYSN,
|
||||
"CPYSE", LTYPE3, ACPYSE,
|
||||
"ADDS", LTYPE3, AADDS,
|
||||
"ADDT", LTYPE3, AADDT,
|
||||
"CMPTEQ", LTYPE3, ACMPTEQ,
|
||||
"CMPTGT", LTYPE3, ACMPTGT,
|
||||
"CMPTGE", LTYPE3, ACMPTGE,
|
||||
"CMPTUN", LTYPE3, ACMPTUN,
|
||||
"DIVS", LTYPE3, ADIVS,
|
||||
"DIVT", LTYPE3, ADIVT,
|
||||
"MULS", LTYPE3, AMULS,
|
||||
"MULT", LTYPE3, AMULT,
|
||||
"SUBS", LTYPE3, ASUBS,
|
||||
"SUBT", LTYPE3, ASUBT,
|
||||
"FCMOVEQ", LTYPE3, AFCMOVEQ,
|
||||
"FCMOVNE", LTYPE3, AFCMOVNE,
|
||||
"FCMOVLT", LTYPE3, AFCMOVLT,
|
||||
"FCMOVGE", LTYPE3, AFCMOVGE,
|
||||
"FCMOVLE", LTYPE3, AFCMOVLE,
|
||||
"FCMOVGT", LTYPE3, AFCMOVGT,
|
||||
|
||||
/* 4: integer load/store and reg->reg (incl special regs) */
|
||||
"MOVQ", LTYPE4, AMOVQ,
|
||||
|
||||
/* 5: integer load/store and reg->reg */
|
||||
"MOVL", LTYPE5, AMOVL,
|
||||
"MOVQU", LTYPE5, AMOVQU,
|
||||
"MOVB", LTYPE5, AMOVB,
|
||||
"MOVBU", LTYPE5, AMOVBU,
|
||||
"MOVW", LTYPE5, AMOVW,
|
||||
"MOVWU", LTYPE5, AMOVWU,
|
||||
"MOVLP", LTYPE5, AMOVLP,
|
||||
"MOVQP", LTYPE5, AMOVQP,
|
||||
|
||||
/* 6: integer load/store (only) */
|
||||
"MOVA", LTYPE6, AMOVA,
|
||||
"MOVAH", LTYPE6, AMOVAH,
|
||||
"MOVLL", LTYPE6, AMOVLL,
|
||||
"MOVQL", LTYPE6, AMOVQL,
|
||||
"MOVLC", LTYPEK, AMOVLC,
|
||||
"MOVQC", LTYPEK, AMOVQC,
|
||||
|
||||
/* 7: floating load/store and reg->reg */
|
||||
"MOVS", LTYPE7, AMOVS,
|
||||
"MOVT", LTYPE7, AMOVT,
|
||||
|
||||
/* 8,9: jumps */
|
||||
"JMP", LTYPE8, AJMP,
|
||||
"JSR", LTYPE8, AJSR,
|
||||
"RET", LTYPE9, ARET,
|
||||
|
||||
/* A: integer conditional branches */
|
||||
"BEQ", LTYPEA, ABEQ,
|
||||
"BNE", LTYPEA, ABNE,
|
||||
"BLT", LTYPEA, ABLT,
|
||||
"BGE", LTYPEA, ABGE,
|
||||
"BLE", LTYPEA, ABLE,
|
||||
"BGT", LTYPEA, ABGT,
|
||||
"BLBC", LTYPEA, ABLBC,
|
||||
"BLBS", LTYPEA, ABLBS,
|
||||
|
||||
/* B: floating conditional branches */
|
||||
"FBEQ", LTYPEB, AFBEQ,
|
||||
"FBNE", LTYPEB, AFBNE,
|
||||
"FBLT", LTYPEB, AFBLT,
|
||||
"FBGE", LTYPEB, AFBGE,
|
||||
"FBLE", LTYPEB, AFBLE,
|
||||
"FBGT", LTYPEB, AFBGT,
|
||||
|
||||
/* C-J: miscellaneous */
|
||||
"TRAPB", LTYPEC, ATRAPB,
|
||||
"MB", LTYPEC, AMB,
|
||||
"REI", LTYPEC, AREI,
|
||||
"END", LTYPEC, AEND,
|
||||
"FETCH", LTYPED, AFETCH,
|
||||
"FETCHM", LTYPED, AFETCHM,
|
||||
"CALL_PAL", LTYPEE, ACALL_PAL,
|
||||
"TEXT", LTYPEF, ATEXT,
|
||||
"GLOBL", LTYPEF, AGLOBL,
|
||||
"DATA", LTYPEG, ADATA,
|
||||
"WORD", LTYPEH, AWORD,
|
||||
"NOP", LTYPEI, ANOP,
|
||||
0
|
||||
};
|
||||
|
||||
void
|
||||
cinit(void)
|
||||
{
|
||||
Sym *s;
|
||||
int i;
|
||||
|
||||
nullgen.sym = S;
|
||||
nullgen.offset = 0;
|
||||
nullgen.type = D_NONE;
|
||||
nullgen.name = D_NONE;
|
||||
nullgen.reg = NREG;
|
||||
if(FPCHIP)
|
||||
nullgen.dval = 0;
|
||||
for(i=0; i<sizeof(nullgen.sval); i++)
|
||||
nullgen.sval[i] = 0;
|
||||
|
||||
nerrors = 0;
|
||||
iostack = I;
|
||||
iofree = I;
|
||||
peekc = IGN;
|
||||
nhunk = 0;
|
||||
for(i=0; i<NHASH; i++)
|
||||
hash[i] = S;
|
||||
for(i=0; itab[i].name; i++) {
|
||||
s = slookup(itab[i].name);
|
||||
s->type = itab[i].type;
|
||||
s->value = itab[i].value;
|
||||
}
|
||||
|
||||
ALLOCN(pathname, 0, 100);
|
||||
if(getwd(pathname, 99) == 0) {
|
||||
ALLOCN(pathname, 100, 900);
|
||||
if(getwd(pathname, 999) == 0)
|
||||
strcpy(pathname, "/???");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
syminit(Sym *s)
|
||||
{
|
||||
|
||||
s->type = LNAME;
|
||||
s->value = 0;
|
||||
}
|
||||
|
||||
int
|
||||
isreg(Gen *g)
|
||||
{
|
||||
|
||||
USED(g);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
cclean(void)
|
||||
{
|
||||
|
||||
outcode(AEND, &nullgen, NREG, &nullgen);
|
||||
Bflush(&obuf);
|
||||
}
|
||||
|
||||
void
|
||||
zname(char *n, int t, int s)
|
||||
{
|
||||
|
||||
Bputc(&obuf, ANAME);
|
||||
Bputc(&obuf, t); /* type */
|
||||
Bputc(&obuf, s); /* sym */
|
||||
while(*n) {
|
||||
Bputc(&obuf, *n);
|
||||
n++;
|
||||
}
|
||||
Bputc(&obuf, 0);
|
||||
}
|
||||
|
||||
void
|
||||
zaddr(Gen *a, int s)
|
||||
{
|
||||
vlong l;
|
||||
int i;
|
||||
char *n;
|
||||
Ieee e;
|
||||
|
||||
Bputc(&obuf, a->type);
|
||||
Bputc(&obuf, a->reg);
|
||||
Bputc(&obuf, s);
|
||||
Bputc(&obuf, a->name);
|
||||
switch(a->type) {
|
||||
default:
|
||||
print("unknown type %d\n", a->type);
|
||||
exits("arg");
|
||||
|
||||
case D_NONE:
|
||||
case D_REG:
|
||||
case D_FREG:
|
||||
case D_PREG:
|
||||
case D_FCREG:
|
||||
case D_PCC:
|
||||
break;
|
||||
|
||||
case D_OREG:
|
||||
case D_CONST:
|
||||
case D_BRANCH:
|
||||
l = a->offset;
|
||||
Bputc(&obuf, l);
|
||||
Bputc(&obuf, l>>8);
|
||||
Bputc(&obuf, l>>16);
|
||||
Bputc(&obuf, l>>24);
|
||||
Bputc(&obuf, l>>32);
|
||||
Bputc(&obuf, l>>40);
|
||||
Bputc(&obuf, l>>48);
|
||||
Bputc(&obuf, l>>56);
|
||||
break;
|
||||
|
||||
case D_SCONST:
|
||||
n = a->sval;
|
||||
for(i=0; i<NSNAME; i++) {
|
||||
Bputc(&obuf, *n);
|
||||
n++;
|
||||
}
|
||||
break;
|
||||
|
||||
case D_FCONST:
|
||||
ieeedtod(&e, a->dval);
|
||||
Bputc(&obuf, e.l);
|
||||
Bputc(&obuf, e.l>>8);
|
||||
Bputc(&obuf, e.l>>16);
|
||||
Bputc(&obuf, e.l>>24);
|
||||
Bputc(&obuf, e.h);
|
||||
Bputc(&obuf, e.h>>8);
|
||||
Bputc(&obuf, e.h>>16);
|
||||
Bputc(&obuf, e.h>>24);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
outcode(int a, Gen *g1, int reg, Gen *g2)
|
||||
{
|
||||
int sf, st, t;
|
||||
Sym *s;
|
||||
|
||||
if(pass == 1)
|
||||
goto out;
|
||||
jackpot:
|
||||
sf = 0;
|
||||
s = g1->sym;
|
||||
while(s != S) {
|
||||
sf = s->sym;
|
||||
if(sf < 0 || sf >= NSYM)
|
||||
sf = 0;
|
||||
t = g1->name;
|
||||
if(h[sf].type == t)
|
||||
if(h[sf].sym == s)
|
||||
break;
|
||||
zname(s->name, t, sym);
|
||||
s->sym = sym;
|
||||
h[sym].sym = s;
|
||||
h[sym].type = t;
|
||||
sf = sym;
|
||||
sym++;
|
||||
if(sym >= NSYM)
|
||||
sym = 1;
|
||||
break;
|
||||
}
|
||||
st = 0;
|
||||
s = g2->sym;
|
||||
while(s != S) {
|
||||
st = s->sym;
|
||||
if(st < 0 || st >= NSYM)
|
||||
st = 0;
|
||||
t = g2->name;
|
||||
if(h[st].type == t)
|
||||
if(h[st].sym == s)
|
||||
break;
|
||||
zname(s->name, t, sym);
|
||||
s->sym = sym;
|
||||
h[sym].sym = s;
|
||||
h[sym].type = t;
|
||||
st = sym;
|
||||
sym++;
|
||||
if(sym >= NSYM)
|
||||
sym = 1;
|
||||
if(st == sf)
|
||||
goto jackpot;
|
||||
break;
|
||||
}
|
||||
Bputc(&obuf, a);
|
||||
Bputc(&obuf, reg);
|
||||
Bputc(&obuf, lineno);
|
||||
Bputc(&obuf, lineno>>8);
|
||||
Bputc(&obuf, lineno>>16);
|
||||
Bputc(&obuf, lineno>>24);
|
||||
zaddr(g1, sf);
|
||||
zaddr(g2, st);
|
||||
|
||||
out:
|
||||
if(a != AGLOBL && a != ADATA)
|
||||
pc++;
|
||||
}
|
||||
|
||||
void
|
||||
outhist(void)
|
||||
{
|
||||
Gen g;
|
||||
Hist *h;
|
||||
char *p, *q, *op;
|
||||
int n;
|
||||
|
||||
g = nullgen;
|
||||
for(h = hist; h != H; h = h->link) {
|
||||
p = h->name;
|
||||
op = 0;
|
||||
if(p && p[0] != '/' && h->offset == 0 && pathname && pathname[0] == '/') {
|
||||
op = p;
|
||||
p = pathname;
|
||||
}
|
||||
while(p) {
|
||||
q = strchr(p, '/');
|
||||
if(q) {
|
||||
n = q-p;
|
||||
if(n == 0)
|
||||
n = 1; /* leading "/" */
|
||||
q++;
|
||||
} else {
|
||||
n = strlen(p);
|
||||
q = 0;
|
||||
}
|
||||
if(n) {
|
||||
Bputc(&obuf, ANAME);
|
||||
Bputc(&obuf, D_FILE); /* type */
|
||||
Bputc(&obuf, 1); /* sym */
|
||||
Bputc(&obuf, '<');
|
||||
Bwrite(&obuf, p, n);
|
||||
Bputc(&obuf, 0);
|
||||
}
|
||||
p = q;
|
||||
if(p == 0 && op) {
|
||||
p = op;
|
||||
op = 0;
|
||||
}
|
||||
}
|
||||
g.offset = h->offset;
|
||||
|
||||
Bputc(&obuf, AHISTORY);
|
||||
Bputc(&obuf, 0);
|
||||
Bputc(&obuf, h->line);
|
||||
Bputc(&obuf, h->line>>8);
|
||||
Bputc(&obuf, h->line>>16);
|
||||
Bputc(&obuf, h->line>>24);
|
||||
zaddr(&nullgen, 0);
|
||||
zaddr(&g, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#include "../cc/lexbody"
|
||||
#include "../cc/macbody"
|
||||
#include "../cc/compat"
|
|
@ -1,19 +0,0 @@
|
|||
</$objtype/mkfile
|
||||
|
||||
TARG=7a
|
||||
OFILES=\
|
||||
y.tab.$O\
|
||||
lex.$O\
|
||||
|
||||
HFILES=\
|
||||
../7c/7.out.h\
|
||||
y.tab.h\
|
||||
a.h\
|
||||
|
||||
YFILES=a.y\
|
||||
|
||||
BIN=/$objtype/bin
|
||||
< /sys/src/cmd/mkone
|
||||
YFLAGS=-D1 -d
|
||||
|
||||
lex.$O: ../cc/macbody ../cc/lexbody
|
|
@ -1,265 +0,0 @@
|
|||
#define NSNAME 8
|
||||
#define NSYM 50
|
||||
#define NREG 32
|
||||
#define NOPROF (1<<0)
|
||||
#define DUPOK (1<<1)
|
||||
|
||||
enum
|
||||
{
|
||||
REGRET = 0, /* return register and first temp, grows++ */
|
||||
REGARG = 0, /* first arg passed in */
|
||||
REGEXT = 15, /* first external register, grows-- */
|
||||
|
||||
REGLINK = 26, /* subroutine linkage */
|
||||
REGTMP = 27, /* used by the loader */
|
||||
REGTMP2 = 28, /* used by the loader */
|
||||
REGSB = 29, /* static pointer */
|
||||
REGSP = 30, /* stack pointer */
|
||||
REGZERO = 31, /* always zero */
|
||||
|
||||
FREGRET = 0,
|
||||
FREGEXT = 27, /* first external register */
|
||||
FREGHALF = 28, /* double */
|
||||
FREGONE = 29, /* double */
|
||||
FREGTWO = 30, /* double */
|
||||
FREGZERO = 31, /* both float and double */
|
||||
};
|
||||
|
||||
enum as
|
||||
{
|
||||
AXXX,
|
||||
AGOK,
|
||||
ATEXT,
|
||||
ADATA,
|
||||
AGLOBL,
|
||||
AHISTORY,
|
||||
ANAME,
|
||||
AWORD,
|
||||
|
||||
ANOP,
|
||||
|
||||
AMOVL,
|
||||
AMOVLU,
|
||||
AMOVQ,
|
||||
AMOVQU,
|
||||
AMOVS,
|
||||
AMOVT,
|
||||
|
||||
AMOVB,
|
||||
AMOVBU,
|
||||
AMOVW,
|
||||
AMOVWU,
|
||||
|
||||
AMOVA,
|
||||
AMOVAH,
|
||||
|
||||
AMOVLL,
|
||||
AMOVQL,
|
||||
AMOVLC,
|
||||
AMOVQC,
|
||||
|
||||
AMOVQP,
|
||||
AMOVLP,
|
||||
|
||||
AADDL,
|
||||
AADDLV,
|
||||
AADDQ,
|
||||
AADDQV,
|
||||
AS4ADDL,
|
||||
AS4ADDQ,
|
||||
AS8ADDL,
|
||||
AS8ADDQ,
|
||||
AS4SUBL,
|
||||
AS4SUBQ,
|
||||
AS8SUBL,
|
||||
AS8SUBQ,
|
||||
ASUBL,
|
||||
ASUBLV,
|
||||
ASUBQ,
|
||||
ASUBQV,
|
||||
|
||||
ACMPEQ,
|
||||
ACMPGT,
|
||||
ACMPGE,
|
||||
ACMPUGT,
|
||||
ACMPUGE,
|
||||
ACMPBLE,
|
||||
|
||||
AAND,
|
||||
AANDNOT,
|
||||
AOR,
|
||||
AORNOT,
|
||||
AXOR,
|
||||
AXORNOT,
|
||||
|
||||
ACMOVEQ,
|
||||
ACMOVNE,
|
||||
ACMOVLT,
|
||||
ACMOVGE,
|
||||
ACMOVLE,
|
||||
ACMOVGT,
|
||||
ACMOVLBC,
|
||||
ACMOVLBS,
|
||||
|
||||
AMULL,
|
||||
AMULQ,
|
||||
AMULLV,
|
||||
AMULQV,
|
||||
AUMULH,
|
||||
ADIVQ,
|
||||
AMODQ,
|
||||
ADIVQU,
|
||||
AMODQU,
|
||||
ADIVL,
|
||||
AMODL,
|
||||
ADIVLU,
|
||||
AMODLU,
|
||||
|
||||
ASLLQ,
|
||||
ASRLQ,
|
||||
ASRAQ,
|
||||
ASLLL,
|
||||
ASRLL,
|
||||
ASRAL,
|
||||
|
||||
AEXTBL,
|
||||
AEXTWL,
|
||||
AEXTLL,
|
||||
AEXTQL,
|
||||
AEXTWH,
|
||||
AEXTLH,
|
||||
AEXTQH,
|
||||
|
||||
AINSBL,
|
||||
AINSWL,
|
||||
AINSLL,
|
||||
AINSQL,
|
||||
AINSWH,
|
||||
AINSLH,
|
||||
AINSQH,
|
||||
|
||||
AMSKBL,
|
||||
AMSKWL,
|
||||
AMSKLL,
|
||||
AMSKQL,
|
||||
AMSKWH,
|
||||
AMSKLH,
|
||||
AMSKQH,
|
||||
|
||||
AZAP,
|
||||
AZAPNOT,
|
||||
|
||||
AJMP,
|
||||
AJSR,
|
||||
ARET,
|
||||
|
||||
ABR,
|
||||
ABSR,
|
||||
|
||||
ABEQ,
|
||||
ABNE,
|
||||
ABLT,
|
||||
ABGE,
|
||||
ABLE,
|
||||
ABGT,
|
||||
ABLBC,
|
||||
ABLBS,
|
||||
|
||||
AFBEQ,
|
||||
AFBNE,
|
||||
AFBLT,
|
||||
AFBGE,
|
||||
AFBLE,
|
||||
AFBGT,
|
||||
|
||||
ATRAPB,
|
||||
AMB,
|
||||
AFETCH,
|
||||
AFETCHM,
|
||||
ARPCC,
|
||||
|
||||
ACPYS,
|
||||
ACPYSN,
|
||||
ACPYSE,
|
||||
ACVTLQ,
|
||||
ACVTQL,
|
||||
AFCMOVEQ,
|
||||
AFCMOVNE,
|
||||
AFCMOVLT,
|
||||
AFCMOVGE,
|
||||
AFCMOVLE,
|
||||
AFCMOVGT,
|
||||
|
||||
AADDS,
|
||||
AADDT,
|
||||
ACMPTEQ,
|
||||
ACMPTGT,
|
||||
ACMPTGE,
|
||||
ACMPTUN,
|
||||
ACVTQS,
|
||||
ACVTQT,
|
||||
ACVTTS,
|
||||
ACVTTQ,
|
||||
ADIVS,
|
||||
ADIVT,
|
||||
AMULS,
|
||||
AMULT,
|
||||
ASUBS,
|
||||
ASUBT,
|
||||
|
||||
ACALL_PAL,
|
||||
AREI,
|
||||
|
||||
AEND,
|
||||
|
||||
ADYNT,
|
||||
AINIT,
|
||||
|
||||
ASIGNAME,
|
||||
|
||||
ALAST,
|
||||
};
|
||||
|
||||
/* type/name */
|
||||
enum
|
||||
{
|
||||
D_GOK = 0,
|
||||
D_NONE,
|
||||
|
||||
/* name */
|
||||
D_EXTERN,
|
||||
D_STATIC,
|
||||
D_AUTO,
|
||||
D_PARAM,
|
||||
|
||||
/* type */
|
||||
D_BRANCH,
|
||||
D_OREG,
|
||||
D_CONST,
|
||||
D_FCONST,
|
||||
D_SCONST,
|
||||
D_REG,
|
||||
D_FREG,
|
||||
D_FCREG,
|
||||
D_PREG,
|
||||
D_PCC,
|
||||
D_FILE,
|
||||
D_FILE1,
|
||||
};
|
||||
|
||||
/*
|
||||
* this is the ranlib header
|
||||
*/
|
||||
#define SYMDEF "__.SYMDEF"
|
||||
|
||||
/*
|
||||
* this is the simulated IEEE floating point
|
||||
*/
|
||||
typedef struct ieee Ieee;
|
||||
struct ieee
|
||||
{
|
||||
long l; /* contains ls-man 0xffffffff */
|
||||
long h; /* contains sign 0x80000000
|
||||
exp 0x7ff00000
|
||||
ms-man 0x000fffff */
|
||||
};
|
File diff suppressed because it is too large
Load diff
|
@ -1,165 +0,0 @@
|
|||
char* anames[] =
|
||||
{
|
||||
"XXX",
|
||||
"GOK",
|
||||
"TEXT",
|
||||
"DATA",
|
||||
"GLOBL",
|
||||
"HISTORY",
|
||||
"NAME",
|
||||
"WORD",
|
||||
"NOP",
|
||||
"MOVL",
|
||||
"MOVLU",
|
||||
"MOVQ",
|
||||
"MOVQU",
|
||||
"MOVS",
|
||||
"MOVT",
|
||||
"MOVB",
|
||||
"MOVBU",
|
||||
"MOVW",
|
||||
"MOVWU",
|
||||
"MOVA",
|
||||
"MOVAH",
|
||||
"MOVLL",
|
||||
"MOVQL",
|
||||
"MOVLC",
|
||||
"MOVQC",
|
||||
"MOVQP",
|
||||
"MOVLP",
|
||||
"ADDL",
|
||||
"ADDLV",
|
||||
"ADDQ",
|
||||
"ADDQV",
|
||||
"S4ADDL",
|
||||
"S4ADDQ",
|
||||
"S8ADDL",
|
||||
"S8ADDQ",
|
||||
"S4SUBL",
|
||||
"S4SUBQ",
|
||||
"S8SUBL",
|
||||
"S8SUBQ",
|
||||
"SUBL",
|
||||
"SUBLV",
|
||||
"SUBQ",
|
||||
"SUBQV",
|
||||
"CMPEQ",
|
||||
"CMPGT",
|
||||
"CMPGE",
|
||||
"CMPUGT",
|
||||
"CMPUGE",
|
||||
"CMPBLE",
|
||||
"AND",
|
||||
"ANDNOT",
|
||||
"OR",
|
||||
"ORNOT",
|
||||
"XOR",
|
||||
"XORNOT",
|
||||
"CMOVEQ",
|
||||
"CMOVNE",
|
||||
"CMOVLT",
|
||||
"CMOVGE",
|
||||
"CMOVLE",
|
||||
"CMOVGT",
|
||||
"CMOVLBC",
|
||||
"CMOVLBS",
|
||||
"MULL",
|
||||
"MULQ",
|
||||
"MULLV",
|
||||
"MULQV",
|
||||
"UMULH",
|
||||
"DIVQ",
|
||||
"MODQ",
|
||||
"DIVQU",
|
||||
"MODQU",
|
||||
"DIVL",
|
||||
"MODL",
|
||||
"DIVLU",
|
||||
"MODLU",
|
||||
"SLLQ",
|
||||
"SRLQ",
|
||||
"SRAQ",
|
||||
"SLLL",
|
||||
"SRLL",
|
||||
"SRAL",
|
||||
"EXTBL",
|
||||
"EXTWL",
|
||||
"EXTLL",
|
||||
"EXTQL",
|
||||
"EXTWH",
|
||||
"EXTLH",
|
||||
"EXTQH",
|
||||
"INSBL",
|
||||
"INSWL",
|
||||
"INSLL",
|
||||
"INSQL",
|
||||
"INSWH",
|
||||
"INSLH",
|
||||
"INSQH",
|
||||
"MSKBL",
|
||||
"MSKWL",
|
||||
"MSKLL",
|
||||
"MSKQL",
|
||||
"MSKWH",
|
||||
"MSKLH",
|
||||
"MSKQH",
|
||||
"ZAP",
|
||||
"ZAPNOT",
|
||||
"JMP",
|
||||
"JSR",
|
||||
"RET",
|
||||
"BR",
|
||||
"BSR",
|
||||
"BEQ",
|
||||
"BNE",
|
||||
"BLT",
|
||||
"BGE",
|
||||
"BLE",
|
||||
"BGT",
|
||||
"BLBC",
|
||||
"BLBS",
|
||||
"FBEQ",
|
||||
"FBNE",
|
||||
"FBLT",
|
||||
"FBGE",
|
||||
"FBLE",
|
||||
"FBGT",
|
||||
"TRAPB",
|
||||
"MB",
|
||||
"FETCH",
|
||||
"FETCHM",
|
||||
"RPCC",
|
||||
"CPYS",
|
||||
"CPYSN",
|
||||
"CPYSE",
|
||||
"CVTLQ",
|
||||
"CVTQL",
|
||||
"FCMOVEQ",
|
||||
"FCMOVNE",
|
||||
"FCMOVLT",
|
||||
"FCMOVGE",
|
||||
"FCMOVLE",
|
||||
"FCMOVGT",
|
||||
"ADDS",
|
||||
"ADDT",
|
||||
"CMPTEQ",
|
||||
"CMPTGT",
|
||||
"CMPTGE",
|
||||
"CMPTUN",
|
||||
"CVTQS",
|
||||
"CVTQT",
|
||||
"CVTTS",
|
||||
"CVTTQ",
|
||||
"DIVS",
|
||||
"DIVT",
|
||||
"MULS",
|
||||
"MULT",
|
||||
"SUBS",
|
||||
"SUBT",
|
||||
"CALL_PAL",
|
||||
"REI",
|
||||
"END",
|
||||
"DYNT",
|
||||
"INIT",
|
||||
"LAST",
|
||||
};
|
|
@ -1,343 +0,0 @@
|
|||
#include "../cc/cc.h"
|
||||
#include "../7c/7.out.h"
|
||||
|
||||
/*
|
||||
* 7c/alpha
|
||||
* DEC Alpha
|
||||
*/
|
||||
#define SZ_CHAR 1
|
||||
#define SZ_SHORT 2
|
||||
#define SZ_INT 4
|
||||
#define SZ_LONG 4
|
||||
#define SZ_IND 4
|
||||
#define SZ_FLOAT 4
|
||||
#define SZ_VLONG 8
|
||||
#define SZ_DOUBLE 8
|
||||
#define FNX 100
|
||||
|
||||
typedef struct Adr Adr;
|
||||
typedef struct Prog Prog;
|
||||
typedef struct Case Case;
|
||||
typedef struct C1 C1;
|
||||
typedef struct Multab Multab;
|
||||
typedef struct Hintab Hintab;
|
||||
typedef struct Bits Bits;
|
||||
typedef struct Var Var;
|
||||
typedef struct Reg Reg;
|
||||
typedef struct Rgn Rgn;
|
||||
|
||||
struct Adr
|
||||
{
|
||||
union
|
||||
{
|
||||
vlong offset;
|
||||
double dval;
|
||||
char sval[NSNAME];
|
||||
Ieee ieee;
|
||||
};
|
||||
Sym* sym;
|
||||
char type;
|
||||
char reg;
|
||||
char name;
|
||||
char etype;
|
||||
};
|
||||
#define A ((Adr*)0)
|
||||
|
||||
#define INDEXED 9
|
||||
struct Prog
|
||||
{
|
||||
Adr from;
|
||||
Adr to;
|
||||
Prog* link;
|
||||
long lineno;
|
||||
uchar as;
|
||||
char reg;
|
||||
};
|
||||
#define P ((Prog*)0)
|
||||
|
||||
struct Case
|
||||
{
|
||||
Case* link;
|
||||
vlong val;
|
||||
long label;
|
||||
char def;
|
||||
char isv;
|
||||
};
|
||||
#define C ((Case*)0)
|
||||
|
||||
struct C1
|
||||
{
|
||||
vlong val;
|
||||
long label;
|
||||
};
|
||||
|
||||
struct Multab
|
||||
{
|
||||
long val;
|
||||
char code[20];
|
||||
};
|
||||
|
||||
struct Hintab
|
||||
{
|
||||
ushort val;
|
||||
char hint[10];
|
||||
};
|
||||
|
||||
struct Var
|
||||
{
|
||||
vlong offset;
|
||||
Sym* sym;
|
||||
char name;
|
||||
char etype;
|
||||
};
|
||||
|
||||
struct Reg
|
||||
{
|
||||
long pc;
|
||||
long rpo; /* reverse post ordering */
|
||||
|
||||
Bits set;
|
||||
Bits use1;
|
||||
Bits use2;
|
||||
|
||||
Bits refbehind;
|
||||
Bits refahead;
|
||||
Bits calbehind;
|
||||
Bits calahead;
|
||||
Bits regdiff;
|
||||
Bits act;
|
||||
|
||||
long regu;
|
||||
long loop; /* could be shorter */
|
||||
|
||||
union
|
||||
{
|
||||
Reg* log5;
|
||||
long active;
|
||||
};
|
||||
Reg* p1;
|
||||
Reg* p2;
|
||||
Reg* p2link;
|
||||
Reg* s1;
|
||||
Reg* s2;
|
||||
Reg* link;
|
||||
Prog* prog;
|
||||
};
|
||||
#define R ((Reg*)0)
|
||||
|
||||
#define NRGN 600
|
||||
struct Rgn
|
||||
{
|
||||
Reg* enter;
|
||||
short cost;
|
||||
short varno;
|
||||
short regno;
|
||||
};
|
||||
|
||||
EXTERN long breakpc;
|
||||
EXTERN long nbreak;
|
||||
EXTERN Case* cases;
|
||||
EXTERN Node constnode;
|
||||
EXTERN Node fconstnode;
|
||||
EXTERN long continpc;
|
||||
EXTERN long curarg;
|
||||
EXTERN long cursafe;
|
||||
EXTERN Prog* firstp;
|
||||
EXTERN Prog* lastp;
|
||||
EXTERN long maxargsafe;
|
||||
EXTERN int mnstring;
|
||||
EXTERN Multab multab[20];
|
||||
EXTERN int hintabsize;
|
||||
EXTERN Node* nodrat;
|
||||
EXTERN Node* nodret;
|
||||
EXTERN Node* nodsafe;
|
||||
EXTERN long nrathole;
|
||||
EXTERN long nstring;
|
||||
EXTERN Prog* p;
|
||||
EXTERN long pc;
|
||||
EXTERN Node regnode;
|
||||
EXTERN char string[NSNAME];
|
||||
EXTERN Sym* symrathole;
|
||||
EXTERN Node znode;
|
||||
EXTERN Prog zprog;
|
||||
EXTERN char reg[NREG+NREG];
|
||||
EXTERN long exregoffset;
|
||||
EXTERN long exfregoffset;
|
||||
|
||||
#define BLOAD(r) band(bnot(r->refbehind), r->refahead)
|
||||
#define BSTORE(r) band(bnot(r->calbehind), r->calahead)
|
||||
#define LOAD(r) (~r->refbehind.b[z] & r->refahead.b[z])
|
||||
#define STORE(r) (~r->calbehind.b[z] & r->calahead.b[z])
|
||||
|
||||
#define bset(a,n) ((a).b[(n)/32]&(1L<<(n)%32))
|
||||
|
||||
#define CLOAD 4
|
||||
#define CREF 5
|
||||
#define CINF 1000
|
||||
#define LOOP 3
|
||||
|
||||
EXTERN Rgn region[NRGN];
|
||||
EXTERN Rgn* rgp;
|
||||
EXTERN int nregion;
|
||||
EXTERN int nvar;
|
||||
|
||||
EXTERN Bits externs;
|
||||
EXTERN Bits params;
|
||||
EXTERN Bits consts;
|
||||
EXTERN Bits addrs;
|
||||
EXTERN Bits zbits;
|
||||
|
||||
EXTERN long regbits;
|
||||
EXTERN long exregbits;
|
||||
|
||||
EXTERN int change;
|
||||
EXTERN int suppress;
|
||||
|
||||
EXTERN Reg* firstr;
|
||||
EXTERN Reg* lastr;
|
||||
EXTERN Reg zreg;
|
||||
EXTERN Reg* freer;
|
||||
EXTERN Var var[NVAR];
|
||||
EXTERN long* idom;
|
||||
EXTERN Reg** rpo2r;
|
||||
EXTERN long maxnr;
|
||||
|
||||
extern char* anames[];
|
||||
extern Hintab hintab[];
|
||||
|
||||
/*
|
||||
* sgen.c
|
||||
*/
|
||||
void codgen(Node*, Node*);
|
||||
void gen(Node*);
|
||||
void usedset(Node*, int);
|
||||
void noretval(int);
|
||||
void xcom(Node*);
|
||||
int bcomplex(Node*, Node*);
|
||||
|
||||
/*
|
||||
* cgen.c
|
||||
*/
|
||||
void cgen(Node*, Node*);
|
||||
void reglcgen(Node*, Node*, Node*);
|
||||
void lcgen(Node*, Node*);
|
||||
void bcgen(Node*, int);
|
||||
void boolgen(Node*, int, Node*);
|
||||
void sugen(Node*, Node*, long);
|
||||
void layout(Node*, Node*, int, int, Node*);
|
||||
|
||||
/*
|
||||
* txt.c
|
||||
*/
|
||||
void ginit(void);
|
||||
void gclean(void);
|
||||
void nextpc(void);
|
||||
void gargs(Node*, Node*, Node*);
|
||||
void garg1(Node*, Node*, Node*, int, Node**);
|
||||
Node* nodconst(long);
|
||||
Node* nod32const(vlong);
|
||||
Node* nodfconst(double);
|
||||
void nodreg(Node*, Node*, int);
|
||||
void regret(Node*, Node*);
|
||||
void regalloc(Node*, Node*, Node*);
|
||||
void regfree(Node*);
|
||||
void regialloc(Node*, Node*, Node*);
|
||||
void regsalloc(Node*, Node*);
|
||||
void regaalloc1(Node*, Node*);
|
||||
void regaalloc(Node*, Node*);
|
||||
void regind(Node*, Node*);
|
||||
void gprep(Node*, Node*);
|
||||
void raddr(Node*, Prog*);
|
||||
void naddr(Node*, Adr*);
|
||||
void gmove(Node*, Node*);
|
||||
void gins(int a, Node*, Node*);
|
||||
void gopcode(int, Node*, Node*, Node*);
|
||||
int samaddr(Node*, Node*);
|
||||
void gbranch(int);
|
||||
void patch(Prog*, long);
|
||||
int bconst(Node*);
|
||||
int sconst(Node*);
|
||||
int bval(vlong);
|
||||
int sval(long);
|
||||
void gpseudo(int, Sym*, Node*);
|
||||
|
||||
/*
|
||||
* swt.c
|
||||
*/
|
||||
int swcmp(void*, void*);
|
||||
void doswit(Node*);
|
||||
void swit1(C1*, int, long, Node*);
|
||||
void swit2(C1*, int, long, Node*, Node*);
|
||||
void casf(void);
|
||||
void bitload(Node*, Node*, Node*, Node*, Node*);
|
||||
void bitstore(Node*, Node*, Node*, Node*, Node*);
|
||||
long outstring(char*, long);
|
||||
int vlog(Node*);
|
||||
int mulcon(Node*, Node*);
|
||||
Multab* mulcon0(long);
|
||||
void nullwarn(Node*, Node*);
|
||||
void sextern(Sym*, Node*, long, long);
|
||||
void gextern(Sym*, Node*, long, long);
|
||||
void outcode(void);
|
||||
void ieeedtod(Ieee*, double);
|
||||
|
||||
/*
|
||||
* list
|
||||
*/
|
||||
void listinit(void);
|
||||
int Pconv(Fmt*);
|
||||
int Aconv(Fmt*);
|
||||
int Dconv(Fmt*);
|
||||
int Sconv(Fmt*);
|
||||
int Nconv(Fmt*);
|
||||
int Bconv(Fmt*);
|
||||
|
||||
/*
|
||||
* reg.c
|
||||
*/
|
||||
Reg* rega(void);
|
||||
int rcmp(void*, void*);
|
||||
void regopt(Prog*);
|
||||
void addmove(Reg*, int, int, int);
|
||||
Bits mkvar(Adr*, int);
|
||||
void prop(Reg*, Bits, Bits);
|
||||
void loopit(Reg*, long);
|
||||
void synch(Reg*, Bits);
|
||||
ulong allreg(ulong, Rgn*);
|
||||
void paint1(Reg*, int);
|
||||
ulong paint2(Reg*, int);
|
||||
void paint3(Reg*, int, long, int);
|
||||
void addreg(Adr*, int);
|
||||
|
||||
/*
|
||||
* peep.c
|
||||
*/
|
||||
void peep(void);
|
||||
void excise(Reg*);
|
||||
Reg* uniqp(Reg*);
|
||||
Reg* uniqs(Reg*);
|
||||
int regtyp(Adr*);
|
||||
int regzer(Adr*);
|
||||
int anyvar(Adr*);
|
||||
int subprop(Reg*);
|
||||
int copyprop(Reg*);
|
||||
int copy1(Adr*, Adr*, Reg*, int);
|
||||
int copyu(Prog*, Adr*, Adr*);
|
||||
|
||||
int copyas(Adr*, Adr*);
|
||||
int copyau(Adr*, Adr*);
|
||||
int copyau1(Prog*, Adr*);
|
||||
int copysub(Adr*, Adr*, Adr*, int);
|
||||
int copysub1(Prog*, Adr*, Adr*, int);
|
||||
|
||||
long RtoB(int);
|
||||
long FtoB(int);
|
||||
int BtoR(long);
|
||||
int BtoF(long);
|
||||
|
||||
#pragma varargck type "A" int
|
||||
#pragma varargck type "B" Bits
|
||||
#pragma varargck type "D" Adr*
|
||||
#pragma varargck type "N" Adr*
|
||||
#pragma varargck type "P" Prog*
|
||||
#pragma varargck type "S" char*
|
|
@ -1,231 +0,0 @@
|
|||
#define EXTERN
|
||||
#include "gc.h"
|
||||
|
||||
void
|
||||
listinit(void)
|
||||
{
|
||||
|
||||
fmtinstall('A', Aconv);
|
||||
fmtinstall('P', Pconv);
|
||||
fmtinstall('S', Sconv);
|
||||
fmtinstall('N', Nconv);
|
||||
fmtinstall('B', Bconv);
|
||||
fmtinstall('D', Dconv);
|
||||
}
|
||||
|
||||
int
|
||||
Bconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ], ss[STRINGSZ], *s;
|
||||
Bits bits;
|
||||
int i;
|
||||
|
||||
memset(str, 0, sizeof str);
|
||||
bits = va_arg(fp->args, Bits);
|
||||
while(bany(&bits)) {
|
||||
i = bnum(bits);
|
||||
if(str[0])
|
||||
strncat(str, " ", sizeof str - 1);
|
||||
if(var[i].sym == S) {
|
||||
snprint(ss, sizeof ss, "$%lld", var[i].offset);
|
||||
s = ss;
|
||||
} else
|
||||
s = var[i].sym->name;
|
||||
strncat(str, s, sizeof str - 1);
|
||||
bits.b[i/32] &= ~(1L << (i%32));
|
||||
}
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
int
|
||||
Pconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ];
|
||||
Prog *p;
|
||||
int a;
|
||||
|
||||
p = va_arg(fp->args, Prog*);
|
||||
a = p->as;
|
||||
if(a == ADATA)
|
||||
snprint(str, sizeof str, " %A %D/%d,%D", a, &p->from, p->reg, &p->to);
|
||||
else
|
||||
if(p->as == ATEXT)
|
||||
snprint(str, sizeof str, " %A %D,%d,%D", a, &p->from, p->reg, &p->to);
|
||||
else
|
||||
if(p->reg == NREG)
|
||||
snprint(str, sizeof str, " %A %D,%D", a, &p->from, &p->to);
|
||||
else
|
||||
if(p->from.type != D_FREG)
|
||||
snprint(str, sizeof str, " %A %D,R%d,%D", a, &p->from, p->reg, &p->to);
|
||||
else
|
||||
snprint(str, sizeof str, " %A %D,F%d,%D", a, &p->from, p->reg, &p->to);
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
int
|
||||
Aconv(Fmt *fp)
|
||||
{
|
||||
char *s;
|
||||
int a;
|
||||
|
||||
a = va_arg(fp->args, int);
|
||||
s = "???";
|
||||
if(a >= AXXX && a < ALAST)
|
||||
s = anames[a];
|
||||
return fmtstrcpy(fp, s);
|
||||
}
|
||||
|
||||
int
|
||||
Dconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ];
|
||||
Adr *a;
|
||||
|
||||
a = va_arg(fp->args, Adr*);
|
||||
switch(a->type) {
|
||||
|
||||
default:
|
||||
snprint(str, sizeof str, "GOK-type(%d)", a->type);
|
||||
break;
|
||||
|
||||
case D_NONE:
|
||||
str[0] = 0;
|
||||
if(a->name != D_NONE || a->reg != NREG || a->sym != S)
|
||||
snprint(str, sizeof str, "%N(R%d)(NONE)", a, a->reg);
|
||||
break;
|
||||
|
||||
case D_CONST:
|
||||
if(a->reg != NREG)
|
||||
snprint(str, sizeof str, "$%N(R%d)", a, a->reg);
|
||||
else
|
||||
snprint(str, sizeof str, "$%N", a);
|
||||
break;
|
||||
|
||||
case D_OREG:
|
||||
if(a->reg != NREG)
|
||||
snprint(str, sizeof str, "%N(R%d)", a, a->reg);
|
||||
else
|
||||
snprint(str, sizeof str, "%N", a);
|
||||
break;
|
||||
|
||||
case D_REG:
|
||||
snprint(str, sizeof str, "R%d", a->reg);
|
||||
if(a->name != D_NONE || a->sym != S)
|
||||
snprint(str, sizeof str, "%N(R%d)(REG)", a, a->reg);
|
||||
break;
|
||||
|
||||
case D_FREG:
|
||||
snprint(str, sizeof str, "F%d", a->reg);
|
||||
if(a->name != D_NONE || a->sym != S)
|
||||
snprint(str, sizeof str, "%N(R%d)(REG)", a, a->reg);
|
||||
break;
|
||||
|
||||
case D_FCREG:
|
||||
snprint(str, sizeof str, "FPCR");
|
||||
if(a->reg != 0 || a->name != D_NONE || a->sym != S)
|
||||
snprint(str, sizeof str, "%N(FPCR%d)(REG)", a, a->reg);
|
||||
break;
|
||||
|
||||
case D_BRANCH:
|
||||
snprint(str, sizeof str, "%lld(PC)", a->offset-pc);
|
||||
break;
|
||||
|
||||
case D_FCONST:
|
||||
snprint(str, sizeof str, "$%.17e", a->dval);
|
||||
break;
|
||||
|
||||
case D_SCONST:
|
||||
snprint(str, sizeof str, "$\"%S\"", a->sval);
|
||||
break;
|
||||
}
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
int
|
||||
Sconv(Fmt *fp)
|
||||
{
|
||||
int i, c;
|
||||
char str[STRINGSZ], *p, *a;
|
||||
|
||||
a = va_arg(fp->args, char*);
|
||||
p = str;
|
||||
for(i=0; i<NSNAME; i++) {
|
||||
c = a[i] & 0xff;
|
||||
if(c >= 'a' && c <= 'z' ||
|
||||
c >= 'A' && c <= 'Z' ||
|
||||
c >= '0' && c <= '9' ||
|
||||
c == ' ' || c == '%') {
|
||||
*p++ = c;
|
||||
continue;
|
||||
}
|
||||
*p++ = '\\';
|
||||
switch(c) {
|
||||
case 0:
|
||||
*p++ = 'z';
|
||||
continue;
|
||||
case '\\':
|
||||
case '"':
|
||||
*p++ = c;
|
||||
continue;
|
||||
case '\n':
|
||||
*p++ = 'n';
|
||||
continue;
|
||||
case '\t':
|
||||
*p++ = 't';
|
||||
continue;
|
||||
case '\r':
|
||||
*p++ = 'r';
|
||||
continue;
|
||||
case '\f':
|
||||
*p++ = 'f';
|
||||
continue;
|
||||
}
|
||||
*p++ = (c>>6) + '0';
|
||||
*p++ = ((c>>3) & 7) + '0';
|
||||
*p++ = (c & 7) + '0';
|
||||
}
|
||||
*p = 0;
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
||||
|
||||
int
|
||||
Nconv(Fmt *fp)
|
||||
{
|
||||
char str[STRINGSZ];
|
||||
Adr *a;
|
||||
Sym *s;
|
||||
|
||||
a = va_arg(fp->args, Adr*);
|
||||
s = a->sym;
|
||||
if(s == S) {
|
||||
snprint(str, sizeof str, "%lld", a->offset);
|
||||
goto out;
|
||||
}
|
||||
switch(a->name) {
|
||||
default:
|
||||
snprint(str, sizeof str, "GOK-name(%d)", a->name);
|
||||
break;
|
||||
|
||||
case D_NONE:
|
||||
snprint(str, sizeof str, "%lld", a->offset);
|
||||
break;
|
||||
|
||||
case D_EXTERN:
|
||||
snprint(str, sizeof str, "%s+%lld(SB)", s->name, a->offset);
|
||||
break;
|
||||
|
||||
case D_STATIC:
|
||||
snprint(str, sizeof str, "%s<>+%lld(SB)", s->name, a->offset);
|
||||
break;
|
||||
|
||||
case D_AUTO:
|
||||
snprint(str, sizeof str, "%s-%lld(SP)", s->name, -a->offset);
|
||||
break;
|
||||
|
||||
case D_PARAM:
|
||||
snprint(str, sizeof str, "%s+%lld(FP)", s->name, a->offset);
|
||||
break;
|
||||
}
|
||||
out:
|
||||
return fmtstrcpy(fp, str);
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
#include "gc.h"
|
||||
|
||||
int
|
||||
machcap(Node *n)
|
||||
{
|
||||
if(n == Z) /* test */
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
ed - ../7c/7.out.h <<'!'
|
||||
v/^ A/d
|
||||
,s/^ A/ "/
|
||||
g/ .*$/s///
|
||||
,s/,*$/",/
|
||||
1i
|
||||
char* anames[] =
|
||||
{
|
||||
.
|
||||
$a
|
||||
};
|
||||
.
|
||||
w enam.c
|
||||
Q
|
||||
!
|
|
@ -1,39 +0,0 @@
|
|||
</$objtype/mkfile
|
||||
|
||||
TARG=7c
|
||||
OFILES=\
|
||||
cgen.$O\
|
||||
enam.$O\
|
||||
list.$O\
|
||||
machcap.$O\
|
||||
peep.$O\
|
||||
pgen.$O\
|
||||
pswt.$O\
|
||||
reg.$O\
|
||||
sgen.$O\
|
||||
swt.$O\
|
||||
txt.$O\
|
||||
mul.$O\
|
||||
|
||||
HFILES=\
|
||||
gc.h\
|
||||
7.out.h\
|
||||
../cc/cc.h\
|
||||
|
||||
LIB=../cc/cc.a$O
|
||||
|
||||
BIN=/$objtype/bin
|
||||
</sys/src/cmd/mkone
|
||||
|
||||
$LIB:
|
||||
cd ../cc
|
||||
mk install
|
||||
mk clean
|
||||
|
||||
%.$O: ../cc/%.c
|
||||
$CC $CFLAGS ../cc/$stem.c
|
||||
|
||||
t:V: $O.out
|
||||
$O.out -S t
|
||||
$LD -o t.out t.$O
|
||||
t.out
|
|
@ -1,608 +0,0 @@
|
|||
#include "gc.h"
|
||||
|
||||
/*
|
||||
* code sequences for multiply by constant.
|
||||
* [a-l][0-3]
|
||||
* lsl $(A-'a'),r0,r1
|
||||
* [+][0-7]
|
||||
* add r0,r1,r2
|
||||
* [-][0-7]
|
||||
* sub r0,r1,r2
|
||||
*/
|
||||
|
||||
static int multabp;
|
||||
static long mulval;
|
||||
static char* mulcp;
|
||||
static long valmax;
|
||||
static int shmax;
|
||||
|
||||
static int docode(char *hp, char *cp, int r0, int r1);
|
||||
static int gen1(int len);
|
||||
static int gen2(int len, long r1);
|
||||
static int gen3(int len, long r0, long r1, int flag);
|
||||
enum
|
||||
{
|
||||
SR1 = 1<<0, /* r1 has been shifted */
|
||||
SR0 = 1<<1, /* r0 has been shifted */
|
||||
UR1 = 1<<2, /* r1 has not been used */
|
||||
UR0 = 1<<3, /* r0 has not been used */
|
||||
};
|
||||
|
||||
Multab*
|
||||
mulcon0(long v)
|
||||
{
|
||||
int a1, a2, g;
|
||||
Multab *m, *m1;
|
||||
char hint[10];
|
||||
|
||||
if(v < 0)
|
||||
v = -v;
|
||||
|
||||
/*
|
||||
* look in cache
|
||||
*/
|
||||
m = multab;
|
||||
for(g=0; g<nelem(multab); g++) {
|
||||
if(m->val == v) {
|
||||
if(m->code[0] == 0)
|
||||
return 0;
|
||||
return m;
|
||||
}
|
||||
m++;
|
||||
}
|
||||
|
||||
/*
|
||||
* select a spot in cache to overwrite
|
||||
*/
|
||||
multabp++;
|
||||
if(multabp < 0 || multabp >= nelem(multab))
|
||||
multabp = 0;
|
||||
m = multab+multabp;
|
||||
m->val = v;
|
||||
mulval = v;
|
||||
|
||||
/*
|
||||
* look in execption hint table
|
||||
*/
|
||||
a1 = 0;
|
||||
a2 = hintabsize;
|
||||
for(;;) {
|
||||
if(a1 >= a2)
|
||||
goto no;
|
||||
g = (a2 + a1)/2;
|
||||
if(v < hintab[g].val) {
|
||||
a2 = g;
|
||||
continue;
|
||||
}
|
||||
if(v > hintab[g].val) {
|
||||
a1 = g+1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(docode(hintab[g].hint, m->code, 1, 0))
|
||||
return m;
|
||||
print("multiply table failure %ld\n", v);
|
||||
m->code[0] = 0;
|
||||
return 0;
|
||||
|
||||
no:
|
||||
/*
|
||||
* try to search
|
||||
*/
|
||||
hint[0] = 0;
|
||||
for(g=1; g<=6; g++) {
|
||||
if(g >= 6 && v >= 65535)
|
||||
break;
|
||||
mulcp = hint+g;
|
||||
*mulcp = 0;
|
||||
if(gen1(g)) {
|
||||
if(docode(hint, m->code, 1, 0))
|
||||
return m;
|
||||
print("multiply table failure %ld\n", v);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* try a recur followed by a shift
|
||||
*/
|
||||
g = 0;
|
||||
while(!(v & 1)) {
|
||||
g++;
|
||||
v >>= 1;
|
||||
}
|
||||
if(g) {
|
||||
m1 = mulcon0(v);
|
||||
if(m1) {
|
||||
strcpy(m->code, m1->code);
|
||||
sprint(strchr(m->code, 0), "%c0", g+'a');
|
||||
return m;
|
||||
}
|
||||
}
|
||||
m->code[0] = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
docode(char *hp, char *cp, int r0, int r1)
|
||||
{
|
||||
int c, i;
|
||||
|
||||
c = *hp++;
|
||||
*cp = c;
|
||||
cp += 2;
|
||||
switch(c) {
|
||||
default:
|
||||
c -= 'a';
|
||||
if(c < 1 || c >= 30)
|
||||
break;
|
||||
for(i=0; i<4; i++) {
|
||||
switch(i) {
|
||||
case 0:
|
||||
if(docode(hp, cp, r0<<c, r1))
|
||||
goto out;
|
||||
break;
|
||||
case 1:
|
||||
if(docode(hp, cp, r1<<c, r1))
|
||||
goto out;
|
||||
break;
|
||||
case 2:
|
||||
if(docode(hp, cp, r0, r0<<c))
|
||||
goto out;
|
||||
break;
|
||||
case 3:
|
||||
if(docode(hp, cp, r0, r1<<c))
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '+':
|
||||
for(i=0; i<8; i++) {
|
||||
cp[-1] = i+'0';
|
||||
switch(i) {
|
||||
case 1:
|
||||
if(docode(hp, cp, r0+r1, r1))
|
||||
goto out;
|
||||
break;
|
||||
case 5:
|
||||
if(docode(hp, cp, r0, r0+r1))
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '-':
|
||||
for(i=0; i<8; i++) {
|
||||
cp[-1] = i+'0';
|
||||
switch(i) {
|
||||
case 1:
|
||||
if(docode(hp, cp, r0-r1, r1))
|
||||
goto out;
|
||||
break;
|
||||
case 2:
|
||||
if(docode(hp, cp, r1-r0, r1))
|
||||
goto out;
|
||||
break;
|
||||
case 5:
|
||||
if(docode(hp, cp, r0, r0-r1))
|
||||
goto out;
|
||||
break;
|
||||
case 6:
|
||||
if(docode(hp, cp, r0, r1-r0))
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if(r0 == mulval)
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
out:
|
||||
cp[-1] = i+'0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
gen1(int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(shmax=1; shmax<30; shmax++) {
|
||||
valmax = 1<<shmax;
|
||||
if(valmax >= mulval)
|
||||
break;
|
||||
}
|
||||
if(mulval == 1)
|
||||
return 1;
|
||||
|
||||
len--;
|
||||
for(i=1; i<=shmax; i++)
|
||||
if(gen2(len, 1<<i)) {
|
||||
*--mulcp = 'a'+i;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
gen2(int len, long r1)
|
||||
{
|
||||
int i;
|
||||
|
||||
if(len <= 0) {
|
||||
if(r1 == mulval)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
len--;
|
||||
if(len == 0)
|
||||
goto calcr0;
|
||||
|
||||
if(gen3(len, r1, r1+1, UR1)) {
|
||||
i = '+';
|
||||
goto out;
|
||||
}
|
||||
if(gen3(len, r1-1, r1, UR0)) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
if(gen3(len, 1, r1+1, UR1)) {
|
||||
i = '+';
|
||||
goto out;
|
||||
}
|
||||
if(gen3(len, 1, r1-1, UR1)) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
calcr0:
|
||||
if(mulval == r1+1) {
|
||||
i = '+';
|
||||
goto out;
|
||||
}
|
||||
if(mulval == r1-1) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
return 0;
|
||||
|
||||
out:
|
||||
*--mulcp = i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
gen3(int len, long r0, long r1, int flag)
|
||||
{
|
||||
int i, f1, f2;
|
||||
long x;
|
||||
|
||||
if(r0 <= 0 ||
|
||||
r0 >= r1 ||
|
||||
r1 > valmax)
|
||||
return 0;
|
||||
|
||||
len--;
|
||||
if(len == 0)
|
||||
goto calcr0;
|
||||
|
||||
if(!(flag & UR1)) {
|
||||
f1 = UR1|SR1;
|
||||
for(i=1; i<=shmax; i++) {
|
||||
x = r0<<i;
|
||||
if(x > valmax)
|
||||
break;
|
||||
if(gen3(len, r0, x, f1)) {
|
||||
i += 'a';
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!(flag & UR0)) {
|
||||
f1 = UR1|SR1;
|
||||
for(i=1; i<=shmax; i++) {
|
||||
x = r1<<i;
|
||||
if(x > valmax)
|
||||
break;
|
||||
if(gen3(len, r1, x, f1)) {
|
||||
i += 'a';
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!(flag & SR1)) {
|
||||
f1 = UR1|SR1|(flag&UR0);
|
||||
for(i=1; i<=shmax; i++) {
|
||||
x = r1<<i;
|
||||
if(x > valmax)
|
||||
break;
|
||||
if(gen3(len, r0, x, f1)) {
|
||||
i += 'a';
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!(flag & SR0)) {
|
||||
f1 = UR0|SR0|(flag&(SR1|UR1));
|
||||
|
||||
f2 = UR1|SR1;
|
||||
if(flag & UR1)
|
||||
f2 |= UR0;
|
||||
if(flag & SR1)
|
||||
f2 |= SR0;
|
||||
|
||||
for(i=1; i<=shmax; i++) {
|
||||
x = r0<<i;
|
||||
if(x > valmax)
|
||||
break;
|
||||
if(x > r1) {
|
||||
if(gen3(len, r1, x, f2)) {
|
||||
i += 'a';
|
||||
goto out;
|
||||
}
|
||||
} else
|
||||
if(gen3(len, x, r1, f1)) {
|
||||
i += 'a';
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
x = r1+r0;
|
||||
if(gen3(len, r0, x, UR1)) {
|
||||
i = '+';
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(gen3(len, r1, x, UR1)) {
|
||||
i = '+';
|
||||
goto out;
|
||||
}
|
||||
|
||||
x = r1-r0;
|
||||
if(gen3(len, x, r1, UR0)) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
|
||||
if(x > r0) {
|
||||
if(gen3(len, r0, x, UR1)) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
} else
|
||||
if(gen3(len, x, r0, UR0)) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
calcr0:
|
||||
f1 = flag & (UR0|UR1);
|
||||
if(f1 == UR1) {
|
||||
for(i=1; i<=shmax; i++) {
|
||||
x = r1<<i;
|
||||
if(x >= mulval) {
|
||||
if(x == mulval) {
|
||||
i += 'a';
|
||||
goto out;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(mulval == r1+r0) {
|
||||
i = '+';
|
||||
goto out;
|
||||
}
|
||||
if(mulval == r1-r0) {
|
||||
i = '-';
|
||||
goto out;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out:
|
||||
*--mulcp = i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* hint table has numbers that
|
||||
* the search algorithm fails on.
|
||||
* <1000:
|
||||
* all numbers
|
||||
* <5000:
|
||||
* ÷ by 5
|
||||
* <10000:
|
||||
* ÷ by 50
|
||||
* <65536:
|
||||
* ÷ by 250
|
||||
*/
|
||||
Hintab hintab[] =
|
||||
{
|
||||
683, "b++d+e+",
|
||||
687, "b+e++e-",
|
||||
691, "b++d+e+",
|
||||
731, "b++d+e+",
|
||||
811, "b++d+i+",
|
||||
821, "b++e+e+",
|
||||
843, "b+d++e+",
|
||||
851, "b+f-+e-",
|
||||
853, "b++e+e+",
|
||||
877, "c++++g-",
|
||||
933, "b+c++g-",
|
||||
981, "c-+e-d+",
|
||||
1375, "b+c+b+h-",
|
||||
1675, "d+b++h+",
|
||||
2425, "c++f-e+",
|
||||
2675, "c+d++f-",
|
||||
2750, "b+d-b+h-",
|
||||
2775, "c-+g-e-",
|
||||
3125, "b++e+g+",
|
||||
3275, "b+c+g+e+",
|
||||
3350, "c++++i+",
|
||||
3475, "c-+e-f-",
|
||||
3525, "c-+d+g-",
|
||||
3625, "c-+e-j+",
|
||||
3675, "b+d+d+e+",
|
||||
3725, "b+d-+h+",
|
||||
3925, "b+d+f-d-",
|
||||
4275, "b+g++e+",
|
||||
4325, "b+h-+d+",
|
||||
4425, "b+b+g-j-",
|
||||
4525, "b+d-d+f+",
|
||||
4675, "c++d-g+",
|
||||
4775, "b+d+b+g-",
|
||||
4825, "c+c-+i-",
|
||||
4850, "c++++i-",
|
||||
4925, "b++e-g-",
|
||||
4975, "c+f++e-",
|
||||
5500, "b+g-c+d+",
|
||||
6700, "d+b++i+",
|
||||
9700, "d++++j-",
|
||||
11000, "b+f-c-h-",
|
||||
11750, "b+d+g+j-",
|
||||
12500, "b+c+e-k+",
|
||||
13250, "b+d+e-f+",
|
||||
13750, "b+h-c-d+",
|
||||
14250, "b+g-c+e-",
|
||||
14500, "c+f+j-d-",
|
||||
14750, "d-g--f+",
|
||||
16750, "b+e-d-n+",
|
||||
17750, "c+h-b+e+",
|
||||
18250, "d+b+h-d+",
|
||||
18750, "b+g-++f+",
|
||||
19250, "b+e+b+h+",
|
||||
19750, "b++h--f-",
|
||||
20250, "b+e-l-c+",
|
||||
20750, "c++bi+e-",
|
||||
21250, "b+i+l+c+",
|
||||
22000, "b+e+d-g-",
|
||||
22250, "b+d-h+k-",
|
||||
22750, "b+d-e-g+",
|
||||
23250, "b+c+h+e-",
|
||||
23500, "b+g-c-g-",
|
||||
23750, "b+g-b+h-",
|
||||
24250, "c++g+m-",
|
||||
24750, "b+e+e+j-",
|
||||
25000, "b++dh+g+",
|
||||
25250, "b+e+d-g-",
|
||||
25750, "b+e+b+j+",
|
||||
26250, "b+h+c+e+",
|
||||
26500, "b+h+c+g+",
|
||||
26750, "b+d+e+g-",
|
||||
27250, "b+e+e+f+",
|
||||
27500, "c-i-c-d+",
|
||||
27750, "b+bd++j+",
|
||||
28250, "d-d-++i-",
|
||||
28500, "c+c-h-e-",
|
||||
29000, "b+g-d-f+",
|
||||
29500, "c+h+++e-",
|
||||
29750, "b+g+f-c+",
|
||||
30250, "b+f-g-c+",
|
||||
33500, "c-f-d-n+",
|
||||
33750, "b+d-b+j-",
|
||||
34250, "c+e+++i+",
|
||||
35250, "e+b+d+k+",
|
||||
35500, "c+e+d-g-",
|
||||
35750, "c+i-++e+",
|
||||
36250, "b+bh-d+e+",
|
||||
36500, "c+c-h-e-",
|
||||
36750, "d+e--i+",
|
||||
37250, "b+g+g+b+",
|
||||
37500, "b+h-b+f+",
|
||||
37750, "c+be++j-",
|
||||
38500, "b+e+b+i+",
|
||||
38750, "d+i-b+d+",
|
||||
39250, "b+g-l-+d+",
|
||||
39500, "b+g-c+g-",
|
||||
39750, "b+bh-c+f-",
|
||||
40250, "b+bf+d+g-",
|
||||
40500, "b+g-c+g+",
|
||||
40750, "c+b+i-e+",
|
||||
41250, "d++bf+h+",
|
||||
41500, "b+j+c+d-",
|
||||
41750, "c+f+b+h-",
|
||||
42500, "c+h++g+",
|
||||
42750, "b+g+d-f-",
|
||||
43250, "b+l-e+d-",
|
||||
43750, "c+bd+h+f-",
|
||||
44000, "b+f+g-d-",
|
||||
44250, "b+d-g--f+",
|
||||
44500, "c+e+c+h+",
|
||||
44750, "b+e+d-h-",
|
||||
45250, "b++g+j-g+",
|
||||
45500, "c+d+e-g+",
|
||||
45750, "b+d-h-e-",
|
||||
46250, "c+bd++j+",
|
||||
46500, "b+d-c-j-",
|
||||
46750, "e-e-b+g-",
|
||||
47000, "b+c+d-j-",
|
||||
47250, "b+e+e-g-",
|
||||
47500, "b+g-c-h-",
|
||||
47750, "b+f-c+h-",
|
||||
48250, "d--h+n-",
|
||||
48500, "b+c-g+m-",
|
||||
48750, "b+e+e-g+",
|
||||
49500, "c-f+e+j-",
|
||||
49750, "c+c+g++f-",
|
||||
50000, "b+e+e+k+",
|
||||
50250, "b++i++g+",
|
||||
50500, "c+g+f-i+",
|
||||
50750, "b+e+d+k-",
|
||||
51500, "b+i+c-f+",
|
||||
51750, "b+bd+g-e-",
|
||||
52250, "b+d+g-j+",
|
||||
52500, "c+c+f+g+",
|
||||
52750, "b+c+e+i+",
|
||||
53000, "b+i+c+g+",
|
||||
53500, "c+g+g-n+",
|
||||
53750, "b+j+d-c+",
|
||||
54250, "b+d-g-j-",
|
||||
54500, "c-f+e+f+",
|
||||
54750, "b+f-+c+g+",
|
||||
55000, "b+g-d-g-",
|
||||
55250, "b+e+e+g+",
|
||||
55500, "b+cd++j+",
|
||||
55750, "b+bh-d-f-",
|
||||
56250, "c+d-b+j-",
|
||||
56500, "c+d+c+i+",
|
||||
56750, "b+e+d++h-",
|
||||
57000, "b+d+g-f+",
|
||||
57250, "b+f-m+d-",
|
||||
57750, "b+i+c+e-",
|
||||
58000, "b+e+d+h+",
|
||||
58250, "c+b+g+g+",
|
||||
58750, "d-e-j--e+",
|
||||
59000, "d-i-+e+",
|
||||
59250, "e--h-m+",
|
||||
59500, "c+c-h+f-",
|
||||
59750, "b+bh-e+i-",
|
||||
60250, "b+bh-e-e-",
|
||||
60500, "c+c-g-g-",
|
||||
60750, "b+e-l-e-",
|
||||
61250, "b+g-g-c+",
|
||||
61750, "b+g-c+g+",
|
||||
62250, "f--+c-i-",
|
||||
62750, "e+f--+g+",
|
||||
64750, "b+f+d+p-",
|
||||
};
|
||||
int hintabsize = nelem(hintab);
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue