00001 /* 00002 * Copyright (c) 2007, Takahide Matsutsuka. 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above 00011 * copyright notice, this list of conditions and the following 00012 * disclaimer in the documentation and/or other materials provided 00013 * with the distribution. 00014 * 3. The name of the author may not be used to endorse or promote 00015 * products derived from this software without specific prior 00016 * written permission. 00017 * 00018 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 00019 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 00020 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00021 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 00022 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00023 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 00024 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 00026 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00027 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00029 * 00030 */ 00031 /* 00032 * \file 00033 * Z80 machine-specific implementation for supporting multithread. 00034 * \author 00035 * Takahide Matsutsuka <markn@markn.org> 00036 */ 00037 #include "sys/mt.h" 00038 #include "mtarch.h" 00039 00040 /*--------------------------------------------------------------------------*/ 00041 void 00042 mtarch_init(void) 00043 { 00044 } 00045 /*--------------------------------------------------------------------------*/ 00046 void 00047 mtarch_start(struct mtarch_thread *t, 00048 void (*function)(void *), void *data) 00049 { 00050 u16_t i; 00051 00052 for(i = 0; i < MTARCH_STACKSIZE; i++) { 00053 t->stack[i] = i; 00054 } 00055 00056 t->sp = &t->stack[MTARCH_STACKSIZE - 1]; 00057 00058 00059 /* A parameter for method for thread function. */ 00060 *t->sp = (u16_t)data; 00061 --t->sp; 00062 00063 /* This will be a return address of thread function. */ 00064 *t->sp = (u16_t)mt_exit; 00065 --t->sp; 00066 00067 /* The thread function, is used as a return address of mtarch_switch. */ 00068 *t->sp = (u16_t)function; 00069 --t->sp; 00070 00071 /* 00072 * Space for registers. 00073 * af, bc, de, hl, ix, iy, af', bc', de', hl' 00074 */ 00075 /* 00076 * Z80 stack basis: 00077 * push stores the data AFTER decrementing sp. 00078 * pop reads the data BEFORE incrementing sp. 00079 */ 00080 00081 t->sp = t->sp - 9; 00082 } 00083 /*--------------------------------------------------------------------------*/ 00084 static struct mtarch_thread *running_thread; 00085 static u16_t *sptmp; 00086 static void 00087 mtarch_switch() 00088 { 00089 __asm 00090 di ; disable interrupt 00091 ; normal registers 00092 push af 00093 push bc 00094 push de 00095 push hl 00096 push ix 00097 push iy 00098 00099 ; back registers 00100 ex af,af' 00101 push af 00102 exx 00103 push bc 00104 push de 00105 push hl 00106 00107 ; swap between running_thread->sp and SP reg 00108 ; _running_thread in asembler below points running_thread->sp 00109 ; sptmp = sp; 00110 ld (_sptmp),sp 00111 00112 ; sp = *(running_thread->sp); 00113 ld ix,(_running_thread) 00114 ld l,0(ix) 00115 ld h,1(ix) 00116 ld sp,hl 00117 00118 ; running_thread->sp = sptmp; 00119 ld hl,(_sptmp) 00120 ld 0(ix),l 00121 ld 1(ix),h 00122 00123 ; back registers 00124 pop hl 00125 pop de 00126 pop bc 00127 exx 00128 pop af 00129 ex af,af' 00130 00131 ; normal registers 00132 pop iy 00133 pop ix 00134 pop hl 00135 pop de 00136 pop bc 00137 pop af 00138 ei ; enable interrupt 00139 __endasm; 00140 // here sp indicates the address that point the function 00141 } 00142 /*--------------------------------------------------------------------------*/ 00143 void 00144 mtarch_exec(struct mtarch_thread *t) 00145 { 00146 running_thread = t; 00147 mtarch_switch(); 00148 running_thread = NULL; 00149 } 00150 /*--------------------------------------------------------------------------*/ 00151 void 00152 mtarch_remove() 00153 { 00154 } 00155 /*--------------------------------------------------------------------------*/ 00156 void 00157 mtarch_yield() 00158 { 00159 if (running_thread == NULL) { 00160 /* ERROR! we have no runnning thread. */ 00161 return; 00162 } 00163 mtarch_switch(); 00164 } 00165 /*--------------------------------------------------------------------------*/ 00166 void mtarch_stop(struct mtarch_thread *thread) 00167 { 00168 } 00169 /*--------------------------------------------------------------------------*/ 00170 void 00171 mtarch_pstop() 00172 { 00173 } 00174 /*--------------------------------------------------------------------------*/ 00175 void 00176 mtarch_pstart() 00177 { 00178 } 00179 /*--------------------------------------------------------------------------*/ 00180 int 00181 mtarch_stack_usage(struct mtarch_thread *t) 00182 { 00183 u16_t i; 00184 for (i = 0; i < MTARCH_STACKSIZE; i++) { 00185 if (t->stack[i] != i) { 00186 return MTARCH_STACKSIZE - i; 00187 } 00188 } 00189 00190 return 0; 00191 } 00192 /*--------------------------------------------------------------------------*/